Home > Software engineering >  How to allow multiple authorize options
How to allow multiple authorize options

Time:10-12

I have a core 3.1 api running currently with JWT Bear Tokens. To use, I simple supply the token from an OAuth2 provider and this working fine.

The defaultPolicy is setup and uses RequireAuthenticatedUser();

However I have a require to allow for end-point that needs to use another authorization process.

So I created a custom AuthorizationHandler and added this as a policy. Then add this policy against the end point. When I hit that end point the custom AuthorizationHandler gets triggered and everything seems to work and the context.Succeed(requirement) is called and then returns Task.CompletedTask.

The problem is that I am still getting a 401 Unauthorize.

Can anyone help?

Below is the custom Handler:

 public class MyCustomAuthorizeRequirement : IAuthorizationRequirement
{ }

public class MyCustomAuthorizeRequirementHandler : AuthorizationHandler<MyCustomAuthorizeRequirement>, IAuthorizationRequirement
{
    private readonly MyCustomSettings _MyCustomSettings;
    public MyCustomAuthorizeRequirementHandler(MyCustomSettings MyCustomSettings)
    {
        _MyCustomSettings = MyCustomSettings;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyCustomAuthorizeRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;


        string authHeader = httpContext.Request.Headers["Authorization"];

        if (authHeader != null && authHeader.StartsWith("x-auth-"))
        {
            if(authHeader != _MyCustomSettings.MyCustomAuthKey)
            {
                context.Fail();
                return Task.CompletedTask;
            }
        }

        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

Below is the extract from the program.cs

 builder.Services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer();

        // Configure policies
        builder.Services
            .AddAuthorization(options =>
            {
                var userAuthPolicyBuilder = new AuthorizationPolicyBuilder();
                options.DefaultPolicy = userAuthPolicyBuilder
                    .RequireAuthenticatedUser()
                    .Build();

                
                options.AddPolicy("MyCustomAuthorize", policy => policy.Requirements.Add(new MyCustomAuthorizeRequirement()));
            });

        MyCustomSettings localMyCustomSettings = new MyCustomSettings();
        configuration.GetSection("MyCustomSettings").Bind(localMyCustomSettings);
        builder.Services.AddSingleton<IAuthorizationHandler>(new MyCustomAuthorizeRequirementHandler(localMyCustomSettings));

CodePudding user response:

Remember, there are two "auth" related HTTP status codes: 401 and 403.

  • 401 means "you don't have the right papers"
  • 403 means "yes, these papers are legit, but I'm not allowed to let you in the door".

Your default policy has .RequireAuthenticatedUser(). Keyword here is "Authenticated". Your application only has one authentication strategy - JWTs. If you don't provide a JWT, you are not authenticated, and thus not authorized.

Here's what you can do:

  1. Create another AuthenticationHandler that will read the Authorization header, ensure the value starts with "x-key-", and if so save it as a claim.
  2. Modify your AuthorizationHandler to read from the claim (not directly from the HTTP request).
  3. Modify the AuthorizationPolicyBuilder to have .AddAuthenticationSchemes(), listing both schemes.
  • Related