InvalidOperationException: The AuthorizationPolicy named: 'Bearer' was not found

Conor Shannon picture Conor Shannon · Apr 8, 2018 · Viewed 10k times · Source

I am currently trying to learn how to build a secure api using bearer token, I keep getting this error (InvalidOperationException: The AuthorizationPolicy named: 'Bearer' was not found.) and I am not sure why. I am using asp.net-core 2.0 and trying to use the jwt auth middleware. Here is my startup class, any help would be greatly appreciated!

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    const string TokenAudience = "ExampleAudience";
    const string TokenIssuer = "ExampleIssuer";
    private RsaSecurityKey key;
    private TokenAuthOptions tokenOptions;

    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 keyParams = RSAKeyUtils.GetRandomKey();
        key = new RsaSecurityKey(keyParams);

        tokenOptions = new TokenAuthOptions()
        {
            Audience = TokenAudience,
            Issuer = TokenIssuer,
            SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature)
        };

        services.AddDbContext<VulnerabilityContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddScoped<LoggingActionFilter>();
        services.AddScoped<VulnsService>();

        services.AddAuthentication(o =>
        {
            o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(o =>
        {
            o.Authority = "https://localhost:54302";
            o.Audience = tokenOptions.Audience;
            o.RequireHttpsMetadata = false;
        });

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        //app.UseSession();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseAuthentication();

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

Answer

Micka&#235;l Derriey picture Mickaël Derriey · Apr 10, 2018

You get this error because authentication schemes and authorization policies are not the same thing. Let's see what each of them are.

Authentication schemes

They are the different methods of authentication in your application. In the code you posted, you have one authentication scheme which is identified by the name Bearer and the options you specified.

It is possible to have several authentications schemes set up in one single application:

  • You could authenticate users with cookies or JWT bearer tokens authentication
  • You could even accept JWT tokens from different sources; in this case, you would need to call the AddJwtBearer method twice. It is also important to note that the name of the authentication scheme is supposed to be unique, so you'd need to use the overload that takes the name and the options configuration delegate

Authorization policies

When a user is authenticated in your application, it doesn't mean it can access every single feature in it. You might have different access levels where administrators have special rights that no one else does; this is expressed in ASP.NET Core using authorization policies. I highly suggest that you read the official documentation on authorization as I think it's great.

An authorization policy is made of two things:

  • a unique name
  • a set of requirements

Taking the example of administrators mentioned above, we can create a fictional authorization policy:

  • Name: Administrators
  • Requirements: Must be authenticated and have a role claim with the Administrators value

This would be expressed this way in code:

services.AddAuthorization(options =>
{
    options.AddPolicy("Administrators", new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireClaim("role", "Administrators")
        .Build());
});

You could then apply this policy on some specific controllers or actions in your application by decorating them with an [Authorize(Policy = "Administrators")] attribute. MVC would then, during the request, run the requirements against the current user and determine whether they can access the specific feature.

My guess is that you added such an attribute on one of your actions/controllers, but you didn't register an authorization policy names Bearer in the authorization system.

If your goal is to prevent non-authenticated users to access some actions, you could apply an [Authorize] attribute. Doing so would run the default policy which, by default, only requires the user to be authenticated.