public override void OnException(ExceptionContext context) { LocalizationService localizationService = context.HttpContext.RequestServices.GetService <LocalizationService>(); CultureInfo culture = context.HttpContext.GetRequestCulture(); ApiError apiError = null; if (context.Exception is SecurityTokenExpiredException) { SecurityTokenExpiredException securityTokenExpiredException = context.Exception as SecurityTokenExpiredException; context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; apiError = new ApiError(localizationService.GetLocalizedStatusCode(ResponseCode.SecurityTokenExpired)); } else if (context.Exception is SecurityTokenException) { apiError = new ApiError(localizationService.GetLocalizedStatusCode(ResponseCode.InvalidSecurityToken)); context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; } else if (context.Exception is UnauthorizedAccessException) { apiError = new ApiError(localizationService.GetLocalizedStatusCode(ResponseCode.UnauthorizedAccess)); context.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; } else { string message = string.Empty; string stack = null; #if DEBUG message = context.Exception.GetBaseException().Message; stack = context.Exception.StackTrace; #endif apiError = new ApiError(message, stack); context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; } context.Result = new JsonResult(apiError); base.OnException(context); }
public void ValidateToken_ThrowsSecurityTokenValidationException_WhenTokenExpired() { // Arrange TimeSpan lifetime = new TimeSpan(0, 0, 1); DateTime tokenCreationDate = DateTime.UtcNow + new TimeSpan(-1, 0, 0); DateTime tokenExpiryDate = tokenCreationDate + lifetime; SecurityTokenDescriptor tokenDescriptor = this.GetTestSecurityTokenDescriptor(tokenCreationDate, tokenExpiryDate); JwtSecurityTokenHandler securityTokenHandler = new JwtSecurityTokenHandler(); JwtSecurityToken token = securityTokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken; // Act System.Threading.Thread.Sleep(1000); SecurityTokenExpiredException ex = Assert.Throws <SecurityTokenExpiredException>(() => MobileAppTokenHandler.ValidateToken(token.RawData, TestSecretKey)); // Assert Assert.Contains("IDX10223: Lifetime validation failed. The token is expired", ex.Message, StringComparison.Ordinal); }
/// <summary> /// Predefined setup of the first-party authentication middleware /// </summary> /// <param name="services">The service collection the validator attaches to</param> public static void AddAuthentication(this IServiceCollection services) { var tokenService = services.BuildServiceProvider() .GetRequiredService <ITokenService>(); var authenticationScheme = JwtBearerDefaults.AuthenticationScheme; var authentication = services.AddAuthentication(options => { options.DefaultChallengeScheme = authenticationScheme; options.DefaultAuthenticateScheme = authenticationScheme; }); authentication.AddJwtBearer(authenticationScheme, async options => { options.SaveToken = true; options.Events = new JwtBearerEvents { OnChallenge = context => { var message = context.AuthenticateFailure switch { SecurityTokenExpiredException ex => $"Provided JWT bearer has expired on '{ex.Expires}'.", _ => "Missing, or invalid 'Authorization' header not following the JWT bearer scheme." }; throw new StatusException(StatusCodes.Status401Unauthorized, message); } }; var validationParameters = await tokenService.RetrieveTokenValidationParametersAsync(); options.TokenValidationParameters = validationParameters; }); // Generate a valid token in development mode Task.Run(async() => await tokenService .GenerateDevelopmentTokenAsync().ConfigureAwait(false)); }
private void ConfigureAuthentication(IServiceCollection services) { services.AddAuthentication(authOptions => { authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(jwtOptions => { jwtOptions.Authority = Configuration["Authentication:Authority"]; jwtOptions.Audience = Configuration["Authentication:Audience"]; jwtOptions.SaveToken = false; jwtOptions.IncludeErrorDetails = true; if (Environment.IsDevelopment()) { jwtOptions.RequireHttpsMetadata = false; } jwtOptions.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = true, ValidateIssuerSigningKey = true, ValidateIssuer = true, ValidIssuer = Configuration["Authentication:Authority"], ValidateLifetime = true, }; jwtOptions.Events = new JwtBearerEvents { OnAuthenticationFailed = failedAuthContext => { failedAuthContext.NoResult(); failedAuthContext.Response.StatusCode = 500; failedAuthContext.Response.ContentType = "text/plain"; var errorMessage = failedAuthContext.Exception switch { SecurityTokenExpiredException _ => "Expired token.", SecurityTokenNotYetValidException _ => "Token not yet valid.", SecurityTokenInvalidLifetimeException _ => "Invalid token lifetime.", SecurityTokenNoExpirationException _ => "Missing token expiration.", SecurityTokenSignatureKeyNotFoundException _ => "Invalid token. Key not found.", _ => "An error occured processing your authentication." }; return(failedAuthContext.Response.WriteAsync(errorMessage)); }, // OnMessageReceived = debugContext => // { // var response = debugContext.Response; // return Task.CompletedTask; // } }; }); // services.AddAuthorization(policyOptions => // { // policyOptions.AddPolicy("Keycloak", new AuthorizationPolicyBuilder() // .RequireAuthenticatedUser() // .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) // .Build()); // }); }
private static string CreateErrorDescription(Exception authFailure) { AggregateException ex = authFailure as AggregateException; IEnumerable <Exception> enumerable = (IEnumerable <Exception>)((ex == null) ? ((object)new Exception[1] { authFailure }) : ((object)ex.InnerExceptions)); List <string> list = new List <string>(); foreach (Exception item in enumerable) { SecurityTokenInvalidAudienceException ex2 = item as SecurityTokenInvalidAudienceException; if (ex2 == null) { SecurityTokenInvalidIssuerException ex3 = item as SecurityTokenInvalidIssuerException; if (ex3 == null) { if (!(item is SecurityTokenNoExpirationException)) { SecurityTokenInvalidLifetimeException ex4 = item as SecurityTokenInvalidLifetimeException; if (ex4 == null) { SecurityTokenNotYetValidException ex5 = item as SecurityTokenNotYetValidException; if (ex5 == null) { SecurityTokenExpiredException ex6 = item as SecurityTokenExpiredException; if (ex6 == null) { if (!(item is SecurityTokenSignatureKeyNotFoundException)) { if (item is SecurityTokenInvalidSignatureException) { list.Add("The signature is invalid"); } } else { list.Add("The signature key was not found"); } } else { list.Add("The token expired at '" + ex6.Expires.ToString(CultureInfo.InvariantCulture) + "'"); } } else { list.Add("The token is not valid before '" + ex5.NotBefore.ToString(CultureInfo.InvariantCulture) + "'"); } } else { list.Add("The token lifetime is invalid; NotBefore: '" + (ex4.NotBefore?.ToString(CultureInfo.InvariantCulture) ?? "(null)") + "', Expires: '" + (ex4.Expires?.ToString(CultureInfo.InvariantCulture) ?? "(null)") + "'"); } } else { list.Add("The token has no expiration"); } } else { list.Add("The issuer '" + (ex3.InvalidIssuer ?? "(null)") + "' is invalid"); } } else { list.Add("The audience '" + (ex2.InvalidAudience ?? "(null)") + "' is invalid"); } } return(string.Join("; ", list)); }
private void ConfigureAuthentication(IServiceCollection services) { services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(bearerOptions => { bearerOptions.Authority = Configuration["Jwt:Authority"]; bearerOptions.Audience = Configuration["Jwt:Audience"]; bearerOptions.SaveToken = true; bearerOptions.IncludeErrorDetails = true; if (Environment.IsDevelopment()) { bearerOptions.RequireHttpsMetadata = false; } var listAudiences = new List <string>(); listAudiences.Add(Configuration["Jwt:Audience"]); bearerOptions.TokenValidationParameters = new TokenValidationParameters { SaveSigninToken = true, ValidateIssuerSigningKey = true, ValidateIssuer = true, ValidIssuer = Configuration["Jwt:Authority"], ValidateAudience = true, ValidAudiences = listAudiences, ValidateLifetime = true }; bearerOptions.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { context.NoResult(); context.Response.StatusCode = 401; context.Response.ContentType = "text/plain"; var errorMessage = context.Exception switch { SecurityTokenExpiredException _ => "Expired token.", SecurityTokenNotYetValidException _ => "Token not yet valid.", SecurityTokenInvalidLifetimeException _ => "Invalid token lifetime.", SecurityTokenNoExpirationException _ => "Missing token expiration.", SecurityTokenSignatureKeyNotFoundException _ => "Invalid token. Key not found.", _ => "An error occured processing your authentication." }; if (Environment.IsDevelopment()) { errorMessage += " - " + context.Exception.ToString(); } return(context.Response.WriteAsync(errorMessage)); }, OnTokenValidated = context => { var resourceAccess = JObject.Parse(context.Principal.FindFirstValue("resource_access")); var clientRoles = resourceAccess[Configuration["Jwt:Audience"]]["roles"]; var claimsIdentity = context.Principal.Identity as ClaimsIdentity; if (claimsIdentity != null) { foreach (var clientRole in clientRoles) { claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, clientRole.ToString())); } } return(Task.CompletedTask); } }; }); }