Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No authenticationScheme was specified, and there was no DefaultForbidScheme found with custom policy based authorization

I have a custom policy based authorization handler as defined below. Authentication is handled before the user hit this application so I only need authorization. I am getting the error:

No authenticationScheme was specified, and there was no DefaultForbidScheme.

If the authorization check succeeds then I do not get the error and all is well. This error only happens when the authorization check fails. I would expect that a 401 is returned on failure.

public class EasRequirement : IAuthorizationRequirement
{
    public EasRequirement(string easBaseAddress, string applicationName, bool bypassAuthorization)
    {
        _client = GetConfiguredClient(easBaseAddress);
        _applicationName = applicationName;
        _bypassAuthorization = bypassAuthorization;
    }

    public async Task<bool> IsAuthorized(ActionContext actionContext)
    {
        ...
    }
}
public class EasHandler : AuthorizationHandler<EasRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, EasRequirement requirement)
    {
        var mvcContext = context.Resource as ActionContext;

        bool isAuthorized;

        try
        {
            isAuthorized = requirement.IsAuthorized(mvcContext).Result;
        }
        catch (Exception)
        {
            // TODO: log the error?
            isAuthorized = false;
        }

        if (isAuthorized)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        context.Fail();
        return Task.FromResult(0);
    }
}
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var easBaseAddress = Configuration.GetSection("EasBaseAddress").Value;
        var applicationName = Configuration.GetSection("ApplicationName").Value;
        var bypassAuthorization = bool.Parse(Configuration.GetSection("BypassEasAuthorization").Value);

        var policy = new AuthorizationPolicyBuilder()
            .AddRequirements(new EasRequirement(easBaseAddress, applicationName, bypassAuthorization))
            .Build();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("EAS", policy);
        });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddSingleton<IAuthorizationHandler, EasHandler>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();

        app.UseMvc();
    }
}
like image 623
Dennis Kiesel Avatar asked Jul 02 '18 19:07

Dennis Kiesel


People also ask

What is authentication and authorization in. net Core?

Authentication is the process of determining a user's identity. Authorization is the process of determining whether a user has access to a resource. In ASP.NET Core, authentication is handled by the authentication service, IAuthenticationService, which is used by authentication middleware.

What is authorization in ASP net Core?

Authorization refers to the process that determines what a user is able to do. For example, an administrative user is allowed to create a document library, add documents, edit documents, and delete them. A non-administrative user working with the library is only authorized to read the documents.

What is authentication scheme?

An authentication scheme is a module that implements a way for a user to authenticate itself to SimpleID. In particular, an authentication scheme checks credentials presented by the user against some data store containing user information, and determines whether the credentials match those stored in the data store.


1 Answers

Authorization and authentication are closely linked in ASP.NET Core. When authorization fails, this will be passed to an authentication handler to handle the authorization failure.

So even if you don’t need actual authentication to identify your users, you will still need to set up some authentication scheme that is able to handle forbid and challenge results (403 and 401).

To do that, you need to call AddAuthentication() and configure a default forbid/challenge scheme:

services.AddAuthentication(options =>
{
    options.DefaultChallengeScheme = "scheme name";

    // you can also skip this to make the challenge scheme handle the forbid as well
    options.DefaultForbidScheme = "scheme name";

    // of course you also need to register that scheme, e.g. using
    options.AddScheme<MySchemeHandler>("scheme name", "scheme display name");
});

MySchemeHandler needs to implement IAuthenticationHandler and in your case, you especially need to implement ChallengeAsync and ForbidAsync:

public class MySchemeHandler : IAuthenticationHandler
{
    private HttpContext _context;

    public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    {
        _context = context;
        return Task.CompletedTask;
    }

    public Task<AuthenticateResult> AuthenticateAsync()
        => Task.FromResult(AuthenticateResult.NoResult());

    public Task ChallengeAsync(AuthenticationProperties properties)
    {
        // do something
    }

    public Task ForbidAsync(AuthenticationProperties properties)
    {
        // do something
    }
}
like image 100
poke Avatar answered Nov 09 '22 14:11

poke