Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET core Web API Authorize Attribute return 404 Error & force redirect

I have asp.net core 2.0 solution which contains following projects:

  • Data: a class library for EF code
  • OAuth: as web application project for IdentityServer4 code
  • Api: for my API created as empty web project

Now the OAuth project is configured with aspnetidentity and its working fine, I able to get the token after authentication, and this is the startup code for it:

public void ConfigureServices(IServiceCollection services)
{
    // connect with normal database
    services.AddDbContext<MCareContext>(options => options.UseSqlServer(Configuration
              .GetConnectionString("MCareConnection")));

    services.AddIdentity<User, IdentityRole>()
        .AddEntityFrameworkStores<MCareContext>()
        .AddDefaultTokenProviders();


    services.AddMvc();

    // IS configurations database
    var dbConnectionString = Configuration.GetConnectionString("MCareConnection.OAuth");
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    services.AddIdentityServer()
         .AddConfigurationStore(options =>
         {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(dbConnectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
         })

        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(dbConnectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
        })

        .AddAspNetIdentity<User>()
        .AddDeveloperSigningCredential(); 
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    DatabaseInitializer.InitializeDatabase(app);

    loggerFactory.AddConsole();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseIdentityServer();

    app.UseStaticFiles();
    app.UseMvcWithDefaultRoute();
}

Now the problem on the API project, whenever I open any authorized controller/action its give me 404 error, and this the startup code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MCareContext>(options => options.UseSqlServer(Configuration
      .GetConnectionString("MCareConnection")));

    services.AddIdentity<User, IdentityRole>()
        .AddEntityFrameworkStores<MCareContext>()
        .AddDefaultTokenProviders();

    services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
     .AddIdentityServerAuthentication(options =>
     {
         options.Authority = "http://localhost:60415";
         options.ApiName = "mCareApi";
         options.RequireHttpsMetadata = false;
     });

    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

    app.UseAuthentication();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDefaultFiles();
    app.UseStaticFiles();            

    app.UseMvcWithDefaultRoute();
}

If I close this part on the above code:

//services.AddIdentity<User, IdentityRole>()
    //.AddEntityFrameworkStores<MCareContext>()
    //.AddDefaultTokenProviders();

Then the Authorize attribute work as expected, but another new problem, it shows 500 internal server error, whenever I opened any controller like AccountController which expect UserManager userManager on its constructor

InvalidOperationException: Unable to resolve service for type Microsoft.AspNetCore.Identity.UserManager`1[MCare.Data.Entities.User] while attempting to activate MCare.Api.Controllers.AccountsController

I want to know why this is happening and how to solve this problem, without mixing IdentityServer4 project with the API project, because all the projects I have seen they mix both of them on one project.

like image 461
Wajdy Essam Avatar asked Oct 10 '17 14:10

Wajdy Essam


2 Answers

Is it possible that DefaultChallengeScheme is redirecting to a page that does not exist such as a login page when it encounters the authorize attribute which could cause the 404?

Try setting the default challenge to the Jwt schema which returns not authorized.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddIdentityServerAuthentication(options =>
{
    options.Authority = "http://localhost:60415";
    options.ApiName = "mCareApi";
    options.RequireHttpsMetadata = false;
});

Or you could try the method I mentioned in the article below by providing a handler for the event.

services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
    options.JwtBearerEvents = new JwtBearerEvents
    {
        OnChallenge = context =>
        {
            context.Response.StatusCode = 401;
            return Task.CompletedTask;
        }
    };
    options.Authority = "http://localhost:60415";
    options.ApiName = "mCareApi";
    options.RequireHttpsMetadata = false;
});
like image 200
Geekn Avatar answered Nov 14 '22 09:11

Geekn


maybe you have to add the AddAuthentication line after the AddControllers() line

like image 35
dkokkinos Avatar answered Nov 14 '22 09:11

dkokkinos