简体   繁体   中英

Token Authentication (Identity Server 4) from different server thru middleware, but it checks for all endpoints which doesn't needed to be authorized

I am using token validation middleware to authenticate user, which hits another server for this. But the issue is, it will always checks the token even if not required, ie while using Register API or any other which doesn't need any validation.

This is my TokenValidationMiddleware.cs file.

public async Task Invoke(HttpContext httpContext, UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;

        // **>>>>>BELOW CHECK IS MANUAL, WHICH IS ALSO NOT CORRECT.<<<<<**
        if (!httpContext.Request.Path.StartsWithSegments("/api/Authentication/Login") && !httpContext.Request.Path.StartsWithSegments("/api/Authentication/Refresh"))
        {
            var headerKeys = httpContext.Request.Headers.Keys;

            // **issue comes here**
            // **it always discard the request which does not have any token.**
            if (headerKeys.Contains("Authorization"))
            {
                // validation code, which hits another server.                       
            }
            else
            {
                httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                await httpContext.Response.WriteAsync("Unauthorized Access");
                return;
            }
        }

        await _next.Invoke(httpContext);
    }

This middleware always checks token validation for every request raised.

I want to bypass this middleware for the anonymous requests, or the requests which does not have any [Authorize] attribute above controller or specific endpoint.

One solution is to store all the anonymous endpoints somewhere and put a check on middleware, which is not correct at all.

Other is to modify the routes of all the secure endpoints as 'api/secure/[controller]', but for that I have to modify all the endpoints in backend as well as frontend. Which is also not a good approach.

Kindly suggest a solution for this.

Thanks in advance.

You could check endpoint against IAuthorizeData in your middleware:

public async Task Invoke(HttpContext httpContext, UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;


    // Check if endpoint has any authorize data, like [Authorize] attribute
    var endpoint = httpContext.GetEndpoint();
    var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>();
    if (authorizeData != null && authorizeData.Any())
    {

        // If you need to depend on particular scheme ("Bearer" in my example):
        var scheme = authorizeData[0].AuthenticationSchemes;
        if (scheme == JwtBearerDefaults.AuthenticationScheme)
        {
            // Code only for "Bearer" auth scheme
        }


        var headerKeys = httpContext.Request.Headers.Keys;

        // **issue comes here**
        // **it always discard the request which does not have any token.**
        if (headerKeys.Contains("Authorization"))
        {
            // validation code, which hits another server.                       
        }
        else
        {
            httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            await httpContext.Response.WriteAsync("Unauthorized Access");
            return;
        }
    }

    await _next.Invoke(httpContext);
}

You could also check the opposite: against IAllowAnonymous , if endpoint has [AllowAnonymous] attribute.

if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)

Ps

You may check the ASP.NET Core Authorization MiddleWare source code for the inspiration.

Middlewares are like .net Handlers. They are to be used when you don't need Controller specific data: asp.net core middleware vs filters

On the other hand, you can use custom policy providers like this: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-3.1

Using an external service to provide policy evaluation.

Using a large range of policies (for different room numbers or ages, for example), so it doesn't make sense to add each individual authorization policy with an AuthorizationOptions.AddPolicy call.

Creating policies at runtime based on information in an external data source (like a database) or determining authorization requirements dynamically through another mechanism.

Thus, you can use an attribute like BypassAuth which will invoke the non authorization for specific actions and let all the rest go through another which will be set as default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM