public virtual async Task ValidatePrincipal(AuthorizeUserContext valiationContext) { if (OnValidatePrincipal != null) { await OnValidatePrincipal.Invoke(valiationContext); } }
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)); }