public virtual async Task ValidatePrincipal(AuthorizeUserContext valiationContext)
 {
     if (OnValidatePrincipal != null)
     {
         await OnValidatePrincipal.Invoke(valiationContext);
     }
 }
Ejemplo n.º 2
0
        public static async Task BuildUserWithRequestServices(this AuthorizeUserContext context)
        {
            var userBuilder = context.HttpContext.RequestServices.GetService <IUserBuilder>();

            if (!await userBuilder.ValidateAndBuildUser(context.ClaimsPrincipal))
            {
                context.Reject();
            }
        }
        public async Task TokenValidated(TokenValidatedContext context)
        {
            //Add the access token to the claims
            var claimsId = context.Principal.Identity as ClaimsIdentity;

            if (claimsId != null)
            {
                claimsId.AddClaim(new Claim(AuthCore.ClaimTypes.AccessToken, (context.SecurityToken as JwtSecurityToken).RawData));
            }

            var jwt = context.SecurityToken as JwtSecurityToken;

            //This algorithm check NEEDS to stay, we have to make sure it is not set to none
            //If this were to be set to none, the signature check would pass since it
            //would be set to none, this would make it trivial to forge jwts.
            if (!jwt.Header.Alg.Equals(securityTokenAlgo, StringComparison.Ordinal))
            {
                throw new InvalidOperationException($"Algorithm must be '{securityTokenAlgo}'");
            }

            var now = DateTime.UtcNow;

            if (now < (jwt.ValidFrom - clockSkew) || now > (jwt.ValidTo + clockSkew))
            {
                //Check dates, return unauthorized if they do not match
                context.Fail($"Dates not valid. Time is {now} token valid from: {jwt.ValidFrom} to: {jwt.ValidTo}");
                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }

            var authContext = new AuthorizeUserContext(context.Principal, context.HttpContext);

            if (OnAuthorizeUser != null)
            {
                await OnAuthorizeUser.Invoke(authContext);
            }

            if (authContext.IsRejected)
            {
                //Check that the rejected claim was not set somewhere, keep this last to ensure its picked up
                context.Fail("Principal was rejected.");
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            String accessTokenString = cookieManager.GetRequestCookie(Context, BearerCookieName);

            if (accessTokenString == null)
            {
                return(AuthenticateResult.NoResult());
            }

            //Parse the access token and see if we should refresh it
            var             handler   = new JwtSecurityTokenHandler();
            ClaimsPrincipal principal = null;
            SecurityToken   token     = null;

            var accessTokenValidationParameters = await this.tokenValidationParametersProvider.GetTokenValidationParameters(Options);

            bool setupUserClaims = true;
            bool expired         = false;

            try
            {
                principal = ValidateAndGetAccessToken(accessTokenString, handler, accessTokenValidationParameters, out token);

                //If not already expired and if we are beyond halfway through the refresh period, refresh the token from the id server.
                var timeSpan = token.ValidTo - token.ValidFrom;
                timeSpan = new TimeSpan(timeSpan.Ticks / 2);
                var endTime = token.ValidFrom + timeSpan;
                expired = DateTime.UtcNow > endTime;
            }
            catch (SecurityTokenExpiredException ex)
            {
                Logger.LogInformation($"SecurityTokenExpiredException: Will attempt to refresh. Exception Message: '{ex.Message}'");
                expired = true;
            }

            if (expired)
            {
                //Refresh from id server
                String refreshToken = cookieManager.GetRequestCookie(Context, RefreshCookieName);
                if (refreshToken == null)
                {
                    EraseCookies();
                    responseRedirectPath = Context.Request.GetDisplayUrl();
                    Logger.LogInformation($"No refresh token found. Cannot refresh credentials.");
                    return(AuthenticateResult.Fail("No refresh token."));
                }

                var connectUri = new Uri(new Uri(Options.Authority), "/connect/token");
                var client     = new TokenClient(sharedHttpClient.Client, new TokenClientOptions()
                {
                    Address      = connectUri.AbsoluteUri,
                    ClientId     = Options.ClientId,
                    ClientSecret = Options.ClientSecret
                });
                var response = await client.RequestRefreshTokenAsync(refreshToken);

                if (response.IsError)
                {
                    setupUserClaims = false;
                    EraseCookies();
                    responseRedirectPath = Context.Request.GetDisplayUrl();
                    Logger.LogInformation($"Error refreshing token. Erasing Cookies and Redirecting to '{responseRedirectPath}'. Error Info: '{response.Error}' '{response.ErrorDescription}' '{response.ErrorType}'");
                    return(AuthenticateResult.Fail($"Could not refresh access token from {connectUri.AbsoluteUri}. Http Status Code: {response.HttpStatusCode} Message: {response.Error}"));
                }
                else
                {
                    accessTokenString = response.AccessToken;
                    principal         = ValidateAndGetAccessToken(accessTokenString, handler, accessTokenValidationParameters, out token);
                    SetTokenCookies(accessTokenString, token, response.RefreshToken);

                    Logger.LogInformation($"Sucessfully refreshed access token.");
                }
            }

            var authUserContext = new AuthorizeUserContext(principal, Context);

            if (setupUserClaims)
            {
                //Add the access token to the claims for the user so we can pass it on easily
                var claimsId = principal.Identity as ClaimsIdentity;
                if (claimsId != null)
                {
                    //Be sure to remove the old access tokens, this is a list not a dictionary and they will leak if not removed.
                    var oldAccessTokenClaim = claimsId.Claims.FirstOrDefault(i => i.Type == AuthCore.ClaimTypes.AccessToken);
                    if (oldAccessTokenClaim != null)
                    {
                        claimsId.RemoveClaim(oldAccessTokenClaim);
                    }
                    claimsId.AddClaim(new Claim(AuthCore.ClaimTypes.AccessToken, accessTokenString));
                }

                //Call client customizations, only done if we got a valid user up to this point.
                if (Options.Events != null)
                {
                    await Options.Events.ValidatePrincipal(authUserContext);
                }
            }

            if (authUserContext.IsRejected)
            {
                return(AuthenticateResult.Fail("User was rejected."));
            }

            var authTicket = new AuthenticationTicket(principal, null, Scheme.Name);

            return(AuthenticateResult.Success(authTicket));
        }