public async Task UpdateConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (client == null) throw new ArgumentNullException("client"); if (user == null) throw new ArgumentNullException("user"); if (client.AllowRememberConsent) { var subject = user.GetSubjectId(); var clientId = client.ClientId; if (scopes != null && scopes.Any()) { var consent = new Consent { Subject = subject, ClientId = clientId, Scopes = scopes }; await _store.UpdateAsync(consent); } else { await _store.RevokeAsync(subject, clientId); } } }
public virtual async Task<IEnumerable<Claim>> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, Client client, IEnumerable<Scope> scopes, bool includeAllIdentityClaims, NameValueCollection request) { Logger.Debug("Getting claims for identity token"); List<Claim> outputClaims = new List<Claim>(GetStandardSubjectClaims(subject)); var additionalClaims = new List<string>(); // fetch all identity claims that need to go into the id token foreach (var scope in scopes) { if (scope.IsOpenIdScope) { foreach (var scopeClaim in scope.Claims) { if (includeAllIdentityClaims || scopeClaim.AlwaysIncludeInIdToken) { additionalClaims.Add(scopeClaim.Name); } } } } if (additionalClaims.Count > 0) { var claims = await _users.GetProfileDataAsync(subject.GetSubjectId(), additionalClaims); if (claims != null) { outputClaims.AddRange(claims); } } return outputClaims; }
public async Task<bool> RequiresConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (client == null) throw new ArgumentNullException("client"); if (user == null) throw new ArgumentNullException("user"); if (!client.RequireConsent) { return false; } // TODO: validate that this is a correct statement if (!client.AllowRememberConsent) { return true; } if (scopes == null || !scopes.Any()) { return false; } var consent = await _store.LoadAsync(user.GetSubjectId(), client.ClientId); if (consent != null && consent.Scopes != null) { var intersect = scopes.Intersect(consent.Scopes); return !(scopes.Count() == intersect.Count()); } return true; }
public Task<IEnumerable<Claim>> GetProfileDataAsync(ClaimsPrincipal subject, IEnumerable<string> requestedClaimTypes = null) { var user = _users.SingleOrDefault(x => x.Subject == subject.GetSubjectId()); if (user == null) { return Task.FromResult<IEnumerable<Claim>>(null); } return Task.FromResult(user.Claims.Where(x => requestedClaimTypes.Contains(x.Type))); }
public async Task UpdateConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (client == null) throw new ArgumentNullException("client"); if (user == null) throw new ArgumentNullException("user"); if (client.AllowRememberConsent) { await _store.UpdateConsentAsync(client.ClientId, user.GetSubjectId(), scopes); } }
public async Task<ValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject) { _validatedRequest.Raw = parameters; _validatedRequest.Subject = subject; if (!subject.Identity.IsAuthenticated) { return Invalid(); } var idTokenHint = parameters.Get(Constants.EndSessionRequest.IdTokenHint); if (idTokenHint.IsPresent()) { // validate id_token - no need to validate token life time var tokenValidationResult = await _tokenValidator.ValidateIdentityTokenAsync(idTokenHint, null, false); if (tokenValidationResult.IsError) { return Invalid(); } _validatedRequest.Client = tokenValidationResult.Client; // validate sub claim against currently logged on user var subClaim = tokenValidationResult.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Subject); if (subClaim != null) { if (subject.GetSubjectId() != subClaim.Value) { return Invalid(); } } var redirectUri = parameters.Get(Constants.EndSessionRequest.PostLogoutRedirectUri); if (redirectUri.IsPresent()) { if (await _uriValidator.IsPostLogoutRedirecUriValidAsync(redirectUri, _validatedRequest.Client) == true) { _validatedRequest.PostLogOutUri = redirectUri; } else { return Invalid(); } var state = parameters.Get(Constants.EndSessionRequest.State); if (state.IsPresent()) { _validatedRequest.State = state; } } } return Valid(); }
public async Task<bool> RequiresConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (client == null) throw new ArgumentNullException("client"); if (user == null) throw new ArgumentNullException("user"); if (!client.RequireConsent) { return false; } return await _store.RequiresConsentAsync(client.ClientId, user.GetSubjectId(), scopes); }
/// <summary> /// Returns claims for an identity token /// </summary> /// <param name="subject">The subject</param> /// <param name="client">The client</param> /// <param name="scopes">The requested scopes</param> /// <param name="includeAllIdentityClaims">Specifies if all claims should be included in the token, or if the userinfo endpoint can be used to retrieve them</param> /// <param name="request">The raw request</param> /// <returns> /// Claims for the identity token /// </returns> public virtual async Task<IEnumerable<Claim>> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, Client client, IEnumerable<Scope> scopes, bool includeAllIdentityClaims, ValidatedRequest request) { Logger.Info("Getting claims for identity token for subject: " + subject.GetSubjectId()); var outputClaims = new List<Claim>(GetStandardSubjectClaims(subject)); outputClaims.AddRange(GetOptionalClaims(subject)); var additionalClaims = new List<string>(); // if a include all claims rule exists, call the user service without a claims filter if (scopes.IncludesAllClaimsForUserRule(ScopeType.Identity)) { Logger.Info("All claims rule found - emitting all claims for user."); var claims = await _users.GetProfileDataAsync(subject); if (claims != null) { outputClaims.AddRange(claims); } return outputClaims; } // fetch all identity claims that need to go into the id token foreach (var scope in scopes) { if (scope.Type == ScopeType.Identity) { foreach (var scopeClaim in scope.Claims) { if (includeAllIdentityClaims || scopeClaim.AlwaysIncludeInIdToken) { additionalClaims.Add(scopeClaim.Name); } } } } if (additionalClaims.Count > 0) { var claims = await _users.GetProfileDataAsync(subject, additionalClaims); if (claims != null) { outputClaims.AddRange(claims); } } return outputClaims; }
public Task UpdateConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (client.AllowRememberConsent) { var consent = new Consent { ClientId = client.ClientId, Subject = user.GetSubjectId(), Scopes = string.Join(" ", scopes.OrderBy(s => s).ToArray()) }; _consents.Add(consent); } return Task.FromResult(0); }
public Task<bool> RequiresConsentAsync(Client client, ClaimsPrincipal user, IEnumerable<string> scopes) { if (!client.RequireConsent) { return Task.FromResult(false); } var orderedScopes = string.Join(" ", scopes.OrderBy(s => s).ToArray()); var query = from c in _consents where c.ClientId == client.ClientId && c.Scopes == orderedScopes && c.Subject == user.GetSubjectId() select c; var hit = query.FirstOrDefault(); return Task.FromResult(hit == null); }
/// <summary> /// Checks if consent is required. /// </summary> /// <param name="client">The client.</param> /// <param name="subject">The user.</param> /// <param name="scopes">The scopes.</param> /// <returns>Boolean if consent is required.</returns> public virtual async Task<bool> RequiresConsentAsync(Client client, ClaimsPrincipal subject, IEnumerable<string> scopes) { if (client == null) throw new ArgumentNullException("client"); if (subject == null) throw new ArgumentNullException("subject"); if (!client.RequireConsent) { return false; } // TODO: validate that this is a correct statement if (!client.AllowRememberConsent) { return true; } if (scopes == null || !scopes.Any()) { return false; } // we always require consent for offline access if // the client has not disabled RequireConsent if (scopes.Contains(Constants.StandardScopes.OfflineAccess)) { return true; } var consent = await _store.LoadAsync(subject.GetSubjectId(), client.ClientId); if (consent != null && consent.Scopes != null) { var intersect = scopes.Intersect(consent.Scopes); return !(scopes.Count() == intersect.Count()); } return true; }
/// <summary> /// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint) /// </summary> /// <param name="subject">The subject.</param> /// <param name="requestedClaimTypes">The requested claim types.</param> /// <returns> /// Claims /// </returns> public virtual Task<IEnumerable<Claim>> GetProfileDataAsync(ClaimsPrincipal subject, IEnumerable<string> requestedClaimTypes = null) { var query = from u in _users where u.Subject == subject.GetSubjectId() select u; var user = query.Single(); var claims = new List<Claim>{ new Claim(Constants.ClaimTypes.Subject, user.Subject), }; claims.AddRange(user.Claims); if (requestedClaimTypes != null) { claims = claims.Where(x => requestedClaimTypes.Contains(x.Type)).ToList(); } return Task.FromResult<IEnumerable<Claim>>(claims); }
public Task<bool> IsActiveAsync(ClaimsPrincipal subject) { var user = Users.SingleOrDefault(x => x.Subject == subject.GetSubjectId()); return Task.FromResult(user != null && user.AcceptedEula); }
public async Task<ValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject) { Logger.Info("Start end session request validation"); _validatedRequest.Raw = parameters; _validatedRequest.Subject = subject; if (!subject.Identity.IsAuthenticated && _options.AuthenticationOptions.RequireAuthenticatedUserForSignOutMessage) { Logger.Warn("User is anonymous. Ignoring end session parameters"); return Invalid(); } var idTokenHint = parameters.Get(Constants.EndSessionRequest.IdTokenHint); if (idTokenHint.IsPresent()) { // validate id_token - no need to validate token life time var tokenValidationResult = await _tokenValidator.ValidateIdentityTokenAsync(idTokenHint, null, false); if (tokenValidationResult.IsError) { LogError("Error validating id token hint."); return Invalid(); } _validatedRequest.Client = tokenValidationResult.Client; // validate sub claim against currently logged on user var subClaim = tokenValidationResult.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Subject); if (subClaim != null && subject.Identity.IsAuthenticated) { if (subject.GetSubjectId() != subClaim.Value) { LogError("Current user does not match identity token"); return Invalid(); } } var redirectUri = parameters.Get(Constants.EndSessionRequest.PostLogoutRedirectUri); if (redirectUri.IsPresent()) { _validatedRequest.PostLogOutUri = redirectUri; if (await _uriValidator.IsPostLogoutRedirectUriValidAsync(redirectUri, _validatedRequest.Client) == false) { LogError("Invalid post logout URI"); return Invalid(); } var state = parameters.Get(Constants.EndSessionRequest.State); if (state.IsPresent()) { _validatedRequest.State = state; } } } LogSuccess(); return Valid(); }
private static void PerformTwoFactorAuthentication(PostAuthenticationContext context, ClaimsPrincipal authenticatedUser) { var twoFactorTokenService = new TwoFactorTokenService(); if (twoFactorTokenService.HasVerifiedTwoFactorCode(authenticatedUser.GetSubjectId())) { return; } twoFactorTokenService.GenerateTwoFactorCodeFor(authenticatedUser.GetSubjectId()); context.AuthenticateResult = new AuthenticateResult("~/twofactorauthentication", authenticatedUser.GetSubjectId(), authenticatedUser.GetName(), authenticatedUser.Claims); }
internal async Task<IEndpointResult> ProcessAuthorizeRequestAsync(NameValueCollection parameters, ClaimsPrincipal user, ConsentResponse consent) { if (user != null) { _logger.LogTrace("User in authorize request: name:{0}, sub:{1}", user.GetName(), user.GetSubjectId()); } else { _logger.LogTrace("No user present in authorize request"); } // validate request var result = await _validator.ValidateAsync(parameters, user); if (result.IsError) { return await ErrorPageAsync( result.ErrorType, result.Error, result.ValidatedRequest); } var request = result.ValidatedRequest; // determine user interaction var interactionResult = await _interactionGenerator.ProcessInteractionAsync(request, consent); if (interactionResult.IsError) { return await ErrorPageAsync( interactionResult.Error.ErrorType, interactionResult.Error.Error, request); } if (interactionResult.IsLogin) { return await LoginPageAsync(request); } if (interactionResult.IsConsent) { return await ConsentPageAsync(request); } // issue response return await SuccessfulAuthorizationAsync(request); }
private string GetKey(ClaimsPrincipal subject, IEnumerable<string> requestedClaimTypes) { var sub = subject.GetSubjectId(); if (requestedClaimTypes == null) return sub; return sub + ":" + requestedClaimTypes.OrderBy(x => x).Aggregate((x, y) => x + "," + y); }
/// <summary> /// Gets the standard subject claims. /// </summary> /// <param name="subject">The subject.</param> /// <returns>A list of standard claims</returns> protected virtual IEnumerable<Claim> GetStandardSubjectClaims(ClaimsPrincipal subject) { var claims = new List<Claim> { new Claim(Constants.ClaimTypes.Subject, subject.GetSubjectId()), new Claim(Constants.ClaimTypes.AuthenticationMethod, subject.GetAuthenticationMethod()), new Claim(Constants.ClaimTypes.AuthenticationTime, subject.GetAuthenticationTimeEpoch().ToString(), ClaimValueTypes.Integer), new Claim(Constants.ClaimTypes.IdentityProvider, subject.GetIdentityProvider()), }; return claims; }
/// <summary> /// This method gets called whenever identity server needs to determine if the user is valid or active (e.g. during token issuance or validation) /// </summary> /// <param name="subject">The subject.</param> /// <returns> /// true or false /// </returns> /// <exception cref="System.ArgumentNullException">subject</exception> public virtual Task<bool> IsActiveAsync(ClaimsPrincipal subject) { if (subject == null) throw new ArgumentNullException("subject"); var query = from u in _users where u.Subject == subject.GetSubjectId() select u; var user = query.SingleOrDefault(); if (user == null) { return Task.FromResult(false); } return Task.FromResult(user.Enabled); }