/// <inheritdoc /> public override async Task RefreshSignInAsync(TUser user) { // borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs#L126 // replaced in order to use a custom auth type AuthenticateResult auth = await Context.AuthenticateAsync(AuthenticationType); IList <Claim> claims = Array.Empty <Claim>(); Claim?authenticationMethod = auth.Principal?.FindFirst(ClaimTypes.AuthenticationMethod); Claim?amr = auth.Principal?.FindFirst("amr"); if (authenticationMethod != null || amr != null) { claims = new List <Claim>(); if (authenticationMethod != null) { claims.Add(authenticationMethod); } if (amr != null) { claims.Add(amr); } } await SignInWithClaimsAsync(user, auth.Properties, claims); }
public async Task <TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate <TResponse> next) { if (httpContext?.User?.Claims == null) { _logger.LogError("no user or claims in httpContext"); return(await next()); } Claim?claim = httpContext.User.Claims.FirstOrDefault(x => x.Type.Equals(ClaimTypes.Name)); if (string.IsNullOrEmpty(claim?.Value)) { _logger.LogError("no matching claim found"); return(await next()); } if (request is UserContext userContext && (userContext.User == null || userContext.CurrentContract == null)) { userContext.UserEmail = claim.Value.ToUpper(); userContext.User = _context.Users.Include(x => x.Contracts.Where(c => c.IsCurrent)).Where(x => x.NormalizedEmail == userContext.UserEmail).SingleOrDefault(); userContext.CurrentContract = userContext.User.Contracts.FirstOrDefault(); } return(await next()); }
/// <summary> /// Removes a <see cref="Claim"/> from the internal list. /// </summary> /// <param name="claim">the <see cref="Claim"/> to match.</param> /// <remarks> It is possible that a <see cref="Claim"/> returned from <see cref="Claims"/> cannot be removed. This would be the case for 'External' claims that are provided by reference. /// <para>object.ReferenceEquals is used to 'match'.</para> /// </remarks> /// <exception cref="InvalidOperationException">if 'claim' cannot be removed.</exception> public virtual void RemoveClaim(Claim?claim) { if (!TryRemoveClaim(claim)) { throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ClaimCannotBeRemoved, claim)); } }
internal static void ThrowForReason(AddClaimForbideReason reason, Claim?claim) { switch (reason) { case AddClaimForbideReason.ProjectNotActive: throw new ProjectDeactivedException(); case AddClaimForbideReason.ProjectClaimsClosed: case AddClaimForbideReason.SlotsExhausted: case AddClaimForbideReason.NotForDirectClaims: case AddClaimForbideReason.Busy: case AddClaimForbideReason.Npc: throw new ClaimTargetIsNotAcceptingClaims(); case AddClaimForbideReason.AlreadySent: throw new ClaimAlreadyPresentException(); case AddClaimForbideReason.OnlyOneCharacter: throw new OnlyOneApprovedClaimException(); case AddClaimForbideReason.ApprovedClaimMovedToGroup: case AddClaimForbideReason.CheckedInClaimCantBeMoved: throw new ClaimWrongStatusException(claim !); default: throw new ArgumentOutOfRangeException(nameof(reason), reason, message: null); } }
private User AuthenticateUser() { AuthenticationGuard.AgainstNull(_ctx.HttpContext?.User?.Identity); AuthenticationGuard.Affirm(_ctx.HttpContext?.User.Identity.IsAuthenticated); var ci = _ctx.HttpContext?.User.Identity as ClaimsIdentity; AuthenticationGuard.AgainstNull(ci); Claim?emailClaim = ci.Claims.SingleOrDefault(c => c.Type == "email") ?? ci.Claims.SingleOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"); AuthenticationGuard.AgainstNull(emailClaim); string email = emailClaim.Value; AuthenticationGuard.AgainstNullOrEmpty(email); using var session = _store.OpenSession(); User user = session.Query <User>().SingleOrDefault(x => x.Email == email); if (user == null) { user = new User { Email = email }; session.Store(user); session.SaveChanges(); } AuthenticationGuard.AgainstNull(user); return(user); }
/// <summary> /// When applied to an <see cref="HttpContext"/>, verifies that the user authenticated in the /// web API has any of the accepted scopes. /// If there is no authenticated user, the response is a 401 (Unauthenticated). /// If the authenticated user does not have any of these <paramref name="acceptedScopes"/>, the /// method updates the HTTP response providing a status code 403 (Forbidden) /// and writes to the response body a message telling which scopes are expected in the token. /// </summary> /// <param name="context">HttpContext (from the controller).</param> /// <param name="acceptedScopes">Scopes accepted by this web API.</param> /// <remarks>When the scopes don't match, the response is a 403 (Forbidden), /// because the user is authenticated (hence not 401), but not authorized.</remarks> public static void VerifyUserHasAnyAcceptedScope(this HttpContext context, params string[] acceptedScopes) { if (acceptedScopes == null) { throw new ArgumentNullException(nameof(acceptedScopes)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } else if (context.User == null || context.User.Claims == null || !context.User.Claims.Any()) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; } else { // Attempt with Scp claim Claim?scopeClaim = context.User.FindFirst(ClaimConstants.Scp); // Fallback to Scope claim name if (scopeClaim == null) { scopeClaim = context.User.FindFirst(ClaimConstants.Scope); } if (scopeClaim == null || !scopeClaim.Value.Split(' ').Intersect(acceptedScopes).Any()) { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; string message = string.Format(CultureInfo.InvariantCulture, IDWebErrorMessage.MissingScopes, string.Join(",", acceptedScopes)); context.Response.WriteAsync(message); } } }
/// <summary> /// When applied to an <see cref="HttpContext"/>, verifies that the application /// has the expected roles. /// </summary> /// <param name="context">HttpContext (from the controller).</param> /// <param name="acceptedRoles">Roles accepted by this web API.</param> /// <remarks>When the roles don't match, the response is a 403 (Forbidden), /// because the app does not have the expected roles.</remarks> public static void ValidateAppRole(this HttpContext context, params string[] acceptedRoles) { if (acceptedRoles == null) { throw new ArgumentNullException(nameof(acceptedRoles)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } else if (context.User == null || context.User.Claims == null || !context.User.Claims.Any()) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; } else { // Attempt with Roles claim Claim?rolesClaim = context.User.FindFirst(ClaimConstants.Roles); // Fallback to Role claim name if (rolesClaim == null) { rolesClaim = context.User.FindFirst(ClaimConstants.Role); } if (rolesClaim == null || !rolesClaim.Value.Split(' ').Intersect(acceptedRoles).Any()) { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; string message = string.Format(CultureInfo.InvariantCulture, LogMessages.MissingRoles, string.Join(",", acceptedRoles)); context.Response.WriteAsync(message); } } }
private static void ThrowIfValidationFailed( IReadOnlyCollection <AddClaimForbideReason> validation, Claim?claim) { if (validation.Any()) { ThrowForReason(validation.First(), claim); } }
/// <inheritdoc /> public bool Equals(Claim?x, Claim?y) { if (x == null) { return(y == null); } return(y != null && x.ToString().Equals(y.ToString())); }
/// <summary> /// When applied to an <see cref="HttpContext"/>, verifies that the user authenticated in the /// web API has any of the accepted scopes. /// If there is no authenticated user, the response is a 401 (Unauthenticated). /// If the authenticated user does not have any of these <paramref name="acceptedScopes"/>, the /// method updates the HTTP response providing a status code 403 (Forbidden) /// and writes to the response body a message telling which scopes are expected in the token. /// We recommend using instead the RequiredScope Attribute on the controller, the page or the action. /// See https://aka.ms/ms-id-web/required-scope-attribute. /// </summary> /// <param name="context">HttpContext (from the controller).</param> /// <param name="acceptedScopes">Scopes accepted by this web API.</param> public static void VerifyUserHasAnyAcceptedScope(this HttpContext context, params string[] acceptedScopes) { if (acceptedScopes == null) { throw new ArgumentNullException(nameof(acceptedScopes)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } IEnumerable <Claim> userClaims; ClaimsPrincipal user; // Need to lock due to https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?#do-not-access-httpcontext-from-multiple-threads lock (context) { user = context.User; userClaims = user.Claims; } if (user == null || userClaims == null || !userClaims.Any()) { lock (context) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; } throw new UnauthorizedAccessException(IDWebErrorMessage.UnauthenticatedUser); } else { // Attempt with Scp claim Claim?scopeClaim = user.FindFirst(ClaimConstants.Scp); // Fallback to Scope claim name if (scopeClaim == null) { scopeClaim = user.FindFirst(ClaimConstants.Scope); } if (scopeClaim == null || !scopeClaim.Value.Split(' ').Intersect(acceptedScopes).Any()) { string message = string.Format(CultureInfo.InvariantCulture, IDWebErrorMessage.MissingScopes, string.Join(",", acceptedScopes)); lock (context) { context.Response.StatusCode = (int)HttpStatusCode.Forbidden; context.Response.WriteAsync(message); context.Response.CompleteAsync(); } throw new UnauthorizedAccessException(message); } } }
private void ValidateEffectiveScopes(AuthorizationFilterContext context) { if (_effectiveAcceptedScopes == null || _effectiveAcceptedScopes.Length == 0) { throw new InvalidOperationException(IDWebErrorMessage.MissingRequiredScopesForAuthorizationFilter); } IEnumerable <Claim> userClaims; ClaimsPrincipal user; HttpContext httpContext = context.HttpContext; // Need to lock due to https://docs.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?#do-not-access-httpcontext-from-multiple-threads lock (httpContext) { user = httpContext.User; userClaims = user.Claims; } if (user == null || userClaims == null || !userClaims.Any()) { lock (httpContext) { httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; } throw new UnauthorizedAccessException(IDWebErrorMessage.UnauthenticatedUser); } else { // Attempt with Scp claim Claim?scopeClaim = user.FindFirst(ClaimConstants.Scp); // Fallback to Scope claim name if (scopeClaim == null) { scopeClaim = user.FindFirst(ClaimConstants.Scope); } if (scopeClaim == null || !scopeClaim.Value.Split(' ').Intersect(_effectiveAcceptedScopes).Any()) { string message = string.Format( CultureInfo.InvariantCulture, IDWebErrorMessage.MissingScopes, string.Join(",", _effectiveAcceptedScopes)); lock (httpContext) { httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; httpContext.Response.WriteAsync(message); httpContext.Response.CompleteAsync(); } throw new UnauthorizedAccessException(message); } } }
public override Claim ReadJson( JsonReader reader, Type objectType, Claim?existingValue, bool hasExistingValue, JsonSerializer serializer) { var info = serializer.Deserialize <ClaimInfo>(reader); return(new Claim(info.Type, info.Value)); }
public override void WriteJson(JsonWriter writer, Claim?value, JsonSerializer serializer) { if (value == null) { return; } var info = new ClaimInfo(value.Type, value.Value); serializer.Serialize(writer, info); }
private static string GetClaimValue(this ClaimsPrincipal claimsPrincipal, string type) { Claim?claim = claimsPrincipal.Claims.SingleOrDefault(predicate: c => c.Type == type); if (claim == null) { throw new ArgumentOutOfRangeException(nameof(type), $"Claim {type} does not exist in JWT"); } return(claim.Value); }
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement) { Claim?userIdClaim = context.User?.FindFirst(_ => _.Type == ClaimTypes.NameIdentifier); if (userIdClaim != null) { if (await _permissionService.CheckPermissionAsync(requirement.Name)) { context.Succeed(requirement); } } }
protected FieldSaveStrategyBase(Claim?claim, Character?character, int currentUserId, IFieldDefaultValueGenerator generator) { Claim = claim; Character = character; CurrentUserId = currentUserId; Generator = generator; Project = character?.Project ?? claim?.Project ?? throw new ArgumentNullException("", "Either character or claim should be not null"); }
private void _init(string[] input) { _claims = new List <Claim>(); foreach (var i in input) { Claim?c = Parse(i); if (c.HasValue) { _claims.Add(c.Value); } } }
protected override async Task OnInitializedAsync() { var authState = await AuthStateProvider.GetAuthenticationStateAsync(); _claimsPrincipal = authState.User; _identityUser = await UserManager.GetUserAsync(_claimsPrincipal); if (_identityUser != null) { _permClaim = new Claim(IPermissionSet.PermissionClaimType, ApplicationPermissions.MyPermission1); await RefreshClaims(); } }
/// <inheritdoc /> public void PopulateWithHttpContext(HttpContext context, AuditEvent auditEvent) { ClaimsIdentity?claimsIdentity = context.User.Identity as ClaimsIdentity; Claim? hdidClaim = claimsIdentity?.Claims.Where(c => c.Type == "hdid").FirstOrDefault(); string? hdid = hdidClaim?.Value; auditEvent.ApplicationType = GetApplicationType(); auditEvent.TransactionResultCode = GetTransactionResultType(context.Response.StatusCode); auditEvent.ApplicationSubject = hdid; RouteValueDictionary routeValues = context.Request.RouteValues; auditEvent.TransactionName = @$ "{routeValues[" controller "]}\{routeValues[" action "]}";
/// <summary> /// Adds or updates and existing claim. /// </summary> public static void AddOrUpdateClaim(this ClaimsIdentity identity, Claim?claim) { if (identity == null) { throw new ArgumentNullException(nameof(identity)); } if (claim is not null) { Claim?existingClaim = identity.Claims.FirstOrDefault(x => x.Type == claim.Type); identity.TryRemoveClaim(existingClaim); identity.AddClaim(claim); } }
/// <summary> /// Adds claim to internal list. Calling Claim.Clone if Claim.Subject != this. /// </summary> /// <remarks>private only call from constructor, adds to internal list.</remarks> private void SafeAddClaim(Claim?claim) { if (claim == null) { return; } if (object.ReferenceEquals(claim.Subject, this)) { _instanceClaims.Add(claim); } else { _instanceClaims.Add(claim.Clone(this)); } }
private FieldsChangedEmail( Character?character, Claim?claim, User initiator, ICollection <User> recipients, [NotNull] IReadOnlyCollection <FieldWithPreviousAndNewValue> updatedFields, [CanBeNull] IReadOnlyDictionary <string, PreviousAndNewValue>?otherChangedAttributes) { if (character != null && claim != null) { throw new ArgumentException( $"Both {nameof(character)} and {nameof(claim)} were provided"); } else if (claim != null) { FieldsContainer = claim; Linkable = claim; ProjectName = claim.Project.ProjectName; Claim = claim; Name = claim.Name; } else if (character != null) { FieldsContainer = character; Linkable = character; ProjectName = character.Project.ProjectName; Claim = character.ApprovedClaim; Name = character.CharacterName; IsCharacterMail = true; } else { throw new ArgumentException( $"Neither {nameof(character)} nor {nameof(claim)} were provided"); } Initiator = initiator; Text = new MarkdownString(); Recipients = recipients; UpdatedFields = updatedFields ?? throw new ArgumentNullException(nameof(updatedFields)); OtherChangedAttributes = otherChangedAttributes ?? new Dictionary <string, PreviousAndNewValue>(); }
/// <summary> /// Attempts to remove a <see cref="Claim"/> the internal list. /// </summary> /// <param name="claim">the <see cref="Claim"/> to match.</param> /// <remarks> It is possible that a <see cref="Claim"/> returned from <see cref="Claims"/> cannot be removed. This would be the case for 'External' claims that are provided by reference. /// <para>object.ReferenceEquals is used to 'match'.</para> /// </remarks> public virtual bool TryRemoveClaim(Claim?claim) { if (claim == null) { return(false); } bool removed = false; for (int i = 0; i < _instanceClaims.Count; i++) { if (object.ReferenceEquals(_instanceClaims[i], claim)) { _instanceClaims.RemoveAt(i); removed = true; break; } } return(removed); }
/// <summary> /// Retrieves the first <see cref="Claim"/> where the Claim.Type equals <paramref name="type"/>. /// </summary> /// <param name="type">The type of the claim to match.</param> /// <returns>A <see cref="Claim"/>, null if nothing matches.</returns> /// <remarks>Each <see cref="ClaimsIdentity"/> is called. <seealso cref="ClaimsIdentity.FindFirst(Predicate{Claim})"/>.</remarks> /// <exception cref="ArgumentNullException">if 'type' is null.</exception> public virtual Claim? FindFirst(string type) { ArgumentNullException.ThrowIfNull(type); Claim? claim = null; for (int i = 0; i < _identities.Count; i++) { if (_identities[i] != null) { claim = _identities[i].FindFirst(type); if (claim != null) { return claim; } } } return claim; }