ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.28k stars 1.63k forks source link

Use Ocelot / Identity Server4 JwtBearerEvents.OnAuthenticationFailed addHeaders not work #1913

Closed lei-9 closed 2 months ago

lei-9 commented 7 months ago

        builder.AddIdentityServerAuthentication(authenticationScheme, GetIdentityServerAuthenticationOptions(configuration, allowedScopes));

... 

 options.JwtBearerEvents = new JwtBearerEvents
            {

                OnAuthenticationFailed = authenticationFailedContext =>
                {
                    var token = authenticationFailedContext.Request.Headers["Authorization"]
                        .ToString()
                        .Replace("Bearer ", "")
                        .Trim();

                    if (!string.IsNullOrEmpty(token))
                    {
                        var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);

                        if (jwtToken.Issuer != identityServerTokenConfig.IdentityServerUrl)
                        {
                            authenticationFailedContext.Response.Headers.Add("Token-Error-Iss", "Issuer is wrong!");
                        }

                        if (jwtToken.Audiences.FirstOrDefault() != identityServerTokenConfig.ApiName)
                        {
                            authenticationFailedContext.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
                        }

                        List<string> scopeList = allowedScopes != null!
                            ? allowedScopes
                            : jwtToken.Claims
                                .Where(s => s.Type == "scope")
                                .Select(s => s.Value)
                                .ToList();

                        if (scopeList?.Any() ?? false)
                        {
                            if (allowedScopes!.Any(scope => !scopeList.Contains(scope)))
                            {
                                authenticationFailedContext.Response.Headers.Add("Token-Error-Scope", "true");
                            }
                        }

                        if (authenticationFailedContext.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            authenticationFailedContext.Response.Headers.Add("Token-Expired", "true");
                        }
                    }
                    else
                    {
                        authenticationFailedContext.Response.StatusCode = StatusCodes.Status401Unauthorized; //没有token则抛出401
                    }

                    return Task.CompletedTask;
                },

                OnChallenge = jwtBearerChallengeContext =>
                {
                    jwtBearerChallengeContext.Response.Headers.Add("Token-Error", jwtBearerChallengeContext.ErrorDescription);
                    jwtBearerChallengeContext.Response.StatusCode = StatusCodes.Status401Unauthorized; //没有token则抛出401
                    return Task.CompletedTask;
                },

                OnTokenValidated = tokenValidatedContext => Task.CompletedTask,
                OnForbidden = forbiddenContext => Task.CompletedTask
            };

ocelot app :http://localhost:5500 ocelot1

ocelot2

ocelot full log

时间:2024-01-09 17:38:02.003
等级:Debug
类:Ocelot.Errors.Middleware.ExceptionHandlerMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'ocelot pipelin
e started'
[17:38:02 DBG] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'ocel
ot pipeline started'

时间:2024-01-09 17:38:02.009
等级:Debug
类:Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Upstream url p
ath is /twms/api/SysUser/LoginUserDetail'
[17:38:02 DBG] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Upst
ream url path is /twms/api/SysUser/LoginUserDetail'

时间:2024-01-09 17:38:02.017
等级:Debug
类:Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'downstream tem
plates are /{resource}'
[17:38:02 DBG] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'down
stream templates are /{resource}'

时间:2024-01-09 17:38:02.045
等级:Information
类:Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'EndpointRateLi
miting is not enabled for /{resource}'
[17:38:02 INF] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Endp
ointRateLimiting is not enabled for /{resource}'

时间:2024-01-09 17:38:02.050
等级:Information
类:Ocelot.Authentication.Middleware.AuthenticationMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: '/twms/api/SysU
ser/LoginUserDetail is an authenticated route. AuthenticationMiddleware checking if client is authenticat
ed'
[17:38:02 INF] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: '/twm
s/api/SysUser/LoginUserDetail is an authenticated route. AuthenticationMiddleware checking if client is a
uthenticated'

时间:2024-01-09 17:38:39.906
等级:Information
类:IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
信息:"TWMSAuth" was not authenticated. Failure message: "IDX10223: Lifetime validation failed. The token 
is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'."
[17:38:39 INF] TWMSAuth was not authenticated. Failure message: IDX10223: Lifetime validation failed. The
 token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.

时间:2024-01-09 17:38:39.910
等级:Warning
类:Ocelot.Authentication.Middleware.AuthenticationMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Client has NOT
 been authenticated for /twms/api/SysUser/LoginUserDetail and pipeline error set. Request for authenticat
ed route /twms/api/SysUser/LoginUserDetail by  was unauthenticated'
[17:38:39 WRN] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Clie
nt has NOT been authenticated for /twms/api/SysUser/LoginUserDetail and pipeline error set. Request for a
uthenticated route /twms/api/SysUser/LoginUserDetail by  was unauthenticated'

时间:2024-01-09 17:38:39.916
等级:Warning
类:Ocelot.Responder.Middleware.ResponderMiddleware
信息:requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Error Code: Un
authenticatedError Message: Request for authenticated route /twms/api/SysUser/LoginUserDetail by  was una
uthenticated errors found in ResponderMiddleware. Setting error response for request path:/twms/api/SysUs
er/LoginUserDetail, request method: GET'
[17:38:39 WRN] requestId: 0HN0GUQM5DR1R:00000002, previousRequestId: No PreviousRequestId, message: 'Erro
r Code: UnauthenticatedError Message: Request for authenticated route /twms/api/SysUser/LoginUserDetail b
y  was unauthenticated errors found in ResponderMiddleware. Setting error response for request path:/twms
/api/SysUser/LoginUserDetail, request method: GET'
raman-m commented 7 months ago

What's the question? 😉

[17:38:39 INF] TWMSAuth was not authenticated. Failure message: IDX10223: Lifetime validation failed. The
 token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.

The root cause is "The token is expired."

Leo, if you use expired tokens why do you create issues in the repo? I recommend you to design your application without Ocelot first! After that start integration of Ocelot!!!

raman-m commented 7 months ago

Also, if you use .NET 8 then keep in mind #1876 !!!

lei-9 commented 7 months ago

What's the question? 😉

[17:38:39 INF] TWMSAuth was not authenticated. Failure message: IDX10223: Lifetime validation failed. The
 token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.

The root cause is "The token is expired."

Leo, if you use expired tokens why do you create issues in the repo? I recommend you to design your application without Ocelot first! After that start integration of Ocelot!!!

I know "The token is expired.". I dog this error, and set error code to http response header.but no response

lei-9 commented 7 months ago

What's the question? 😉

[17:38:39 INF] TWMSAuth was not authenticated. Failure message: IDX10223: Lifetime validation failed. The
 token is expired. ValidTo: 'System.DateTime', Current time: 'System.DateTime'.

The root cause is "The token is expired." Leo, if you use expired tokens why do you create issues in the repo? I recommend you to design your application without Ocelot first! After that start integration of Ocelot!!!

I know "The token is expired.". I dog this error, and set error code to http response header.but no response

I can return the http response header added in OnAuthenticationFailed in my application Integrating ocelot into OnAuthenticationFailed, I also added httpresponse header. But no return

lei-9 commented 7 months ago

I found out, normally it is JwtBearerEvents.OnAuthenticationFailed You will then enter OnChallenge. But now when using ocelot, the OnChallenge event is not entered.

lei-9 commented 7 months ago

I found out, normally it is JwtBearerEvents.OnAuthenticationFailed You will then enter OnChallenge. But now when using ocelot, the OnChallenge event is not entered.

@raman-m please help me...

raman-m commented 7 months ago

@lei-9 commented 3 hours ago But now when using ocelot, the OnChallenge event is not entered.

OK. What .NET SDK do you use? .NET 8 or lower?

Again, my recommendation is 👇

Have you designed your infrastructure and services apps including identity management without Ocelot?

lei-9 commented 7 months ago

@lei-9 commented 3 hours ago But now when using ocelot, the OnChallenge event is not entered.

OK. What .NET SDK do you use? .NET 8 or lower?

Again, my recommendation is 👇

Have you designed your infrastructure and services apps including identity management without Ocelot?

SDK:Net 6

It is normal to use it in a service application

raman-m commented 7 months ago

Well... If it doesn't work in .NET 6 then we have to fix after verification. Also, could you tests the same app for .NET 7 and .NET 8 please?

Please, upload complete solution to GitHub for verification!