public void ShouldCreateParameters() { var authOptions = new AuthOptions { JwtIssuer = "jwtIssuer" }; var devPermissionsOptions = new DevPermissionsOptions(); var jwtSigningKeyProviderMock = new Mock <IJwtSigningKeyResolver>(); var hostingEnvironmentMock = new Mock <IHostingEnvironment>(); var tokenValidationParametersFactory = new TokenValidationParametersFactory(Options.Create(authOptions), jwtSigningKeyProviderMock.Object, Options.Create(devPermissionsOptions), hostingEnvironmentMock.Object); var tokenValidationParameters = tokenValidationParametersFactory.Create(); Assert.False(tokenValidationParameters.ValidateIssuer); Assert.Equal(authOptions.JwtIssuer, tokenValidationParameters.ValidIssuer); Assert.False(tokenValidationParameters.ValidateAudience); Assert.Equal(authOptions.JwtAudience, tokenValidationParameters.ValidAudience); Assert.True(tokenValidationParameters.ValidateLifetime); Assert.True(tokenValidationParameters.RequireSignedTokens); }
public static Action <JwtBearerOptions> ConfigureJwtOptions(JwtConfig jwtConfig) { return(bearerOptions => { JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); bearerOptions.RequireHttpsMetadata = false; bearerOptions.SaveToken = true; bearerOptions.TokenValidationParameters = TokenValidationParametersFactory.Create(jwtConfig); }); }
private bool IsJwtValid(string jwtTokenString, string clientId, string audience) { var trustedKeys = _keysExtractor.ExtractSecurityKeys(jwtTokenString); if (!trustedKeys.Any()) { return(FromError("Trusted keys not found.")); } var tokenValidationParameters = TokenValidationParametersFactory.Create(clientId, audience, trustedKeys); try { var handler = new JwtSecurityTokenHandler(); handler.ValidateToken(jwtTokenString, tokenValidationParameters, out var token); var jwtToken = (JwtSecurityToken)token; if (IsHeaderAlgInvalid(jwtToken.Header.Alg)) { return(FromError("Header alg value must be RS256.")); } if (IsSubInvalid(jwtToken)) { return(FromError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id.")); } if (string.IsNullOrEmpty(jwtToken.Payload.Jti)) { return(FromError("The 'jti' claim is missing from the client assertion.")); } if (IsUnixTimestampGreaterThanUtcNow(jwtToken.Payload.Iat)) { return(FromError("The 'iat' claim cannot have higher value than UtcNow.")); } if (IsExpired(jwtToken.Payload.Exp)) { return(FromError("The 'exp' claim states that token is expired.")); } return(true); } catch (Exception e) { _logger.LogError(e, "JWT token validation error."); return(false); } }
public void ValidateTokenLifetimeShouldBeTrue() { var authOptions = new AuthOptions(); var devPermissionsOptions = new DevPermissionsOptions { Environment = "Testing", }; var jwtSigningKeyProviderMock = new Mock <IJwtSigningKeyResolver>(); var hostingEnvironmentMock = new Mock <IHostingEnvironment>(); hostingEnvironmentMock.SetupGet(h => h.EnvironmentName) .Returns(devPermissionsOptions.Environment); var tokenValidationParametersFactory = new TokenValidationParametersFactory(Options.Create(authOptions), jwtSigningKeyProviderMock.Object, Options.Create(devPermissionsOptions), hostingEnvironmentMock.Object); var tokenValidationParameters = tokenValidationParametersFactory.Create(); Assert.True(tokenValidationParameters.ValidateLifetime); }
public async Task <FinishSsoResult> FinishSsoAsync(HttpContext context) { if (!TryGetSamlResponse(context, out var response, out var binding)) { throw new InvalidOperationException("Bad request."); } Logger.LogInformation("Finishing SAML2P authentication (SP flow)."); Trace($"Received SAMLResponse using {binding} binding.", response); var partnerId = response.Issuer; var partner = await Partners.GetIdentityProviderAsync(partnerId); if (partner == null) { throw new SecurityException($"Partner idp '{partnerId}' not found."); } if (!partner.Enabled) { throw new SecurityException($"Partner idp '{partnerId}' is disabled."); } var request = null as AuthnRequest; if (response.InResponseTo != null) { request = await Cache.FetchRequestAsync(response.InResponseTo); await Cache.RemoveAsync(response.InResponseTo); } if (request == null && !partner.CanInitiateSso) { throw new SecurityException($"Partner idp '{partnerId}' is is not allowed to initiate SSO."); } if (request != null) { Trace("Found cached SAMLRequest.", request); if (request.RelayState != response.RelayState) { throw new SecurityException($"Mismatching relay state."); } } var ssoContext = new FinishSsoContext { PartnerId = partner.Id, Partner = partner, Request = request, Response = response }; await Events.InvokeAsync(Options, partner, e => e.OnFinishSso(context.RequestServices, ssoContext)); if (response.Status.StatusCode.Value != Saml2pConstants.Statuses.Success) { return(FinishSsoResult.Fail(partner.Id, response.Status.StatusCode.Value, response.Status.StatusCode?.SubCode.Value)); } var parameters = _factory.Create(partner); var validateContext = new ValidateTokenContext { PartnerId = partner.Id, Partner = partner, Request = request, Response = response, TokenValidationParameters = parameters, Handler = _handler }; await Events.InvokeAsync(Options, partner, e => e.OnValidatingToken(context.RequestServices, validateContext)); if (validateContext.Subject != null && validateContext.SecurityToken == null || validateContext.Subject == null && validateContext.SecurityToken != null) { Logger.LogWarning($"When manually populating '{nameof(ValidateTokenContext.Subject)}' or '{nameof(ValidateTokenContext.SecurityToken)}' properties of '{nameof(ValidateTokenContext)}', then both must be populated. Otherwise they will be ignored. Clearing values..."); validateContext.SecurityToken = null; validateContext.Subject = null; } if (validateContext.Subject == null) { Logger.LogInformation("Validating incoming token."); var subject = validateContext.Handler.ValidateToken(validateContext.Response.XmlSecurityToken, validateContext.TokenValidationParameters, out var token); var saml2 = token as Saml2SecurityToken; var now = _clock.UtcNow.DateTime; saml2.ValidateResponseToken(validateContext.Request.Id, now); validateContext.Subject = subject; validateContext.SecurityToken = saml2; } await Events.InvokeAsync(Options, partner, e => e.OnValidatedToken(context.RequestServices, validateContext)); context.User = validateContext.Subject; return(FinishSsoResult.Success(partner.Id, validateContext.SecurityToken, validateContext.Subject)); }