Esempio n. 1
0
    /// <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);
    }
Esempio n. 2
0
        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());
        }
Esempio n. 3
0
 /// <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));
     }
 }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        /// <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);
                }
            }
        }
Esempio n. 7
0
        /// <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);
                }
            }
        }
Esempio n. 8
0

        
Esempio n. 10
0
 private static void ThrowIfValidationFailed(
     IReadOnlyCollection <AddClaimForbideReason> validation,
     Claim?claim)
 {
     if (validation.Any())
     {
         ThrowForReason(validation.First(), claim);
     }
 }
Esempio n. 11
0
        /// <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);
                }
            }
        }
Esempio n. 15
0
            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));
            }
Esempio n. 16
0
            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);
            }
Esempio n. 17
0
        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);
        }
Esempio n. 18
0

        
Esempio n. 19
0
        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);
                }
            }
        }
Esempio n. 20
0
 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");
 }
Esempio n. 21
0
 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);
         }
     }
 }
Esempio n. 22
0
        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();
            }
        }
Esempio n. 23
0
        /// <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);
            }
        }
Esempio n. 25
0
        /// <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));
            }
        }
Esempio n. 27
0
        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>();
        }
Esempio n. 28
0

        
Esempio n. 29
0
        /// <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);
        }
Esempio n. 30
0
        /// <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;
        }