Search code examples
oauth-2.0identityserver4asp.net-core-webapi

Cannot get user identity set in Web Core API v1


I have a Web Core API version 1 project, where when I call a method via Postman I find the [Authorize] tag does not work. In my Web API my startup looks like this (edited for readability)

    public void ConfigureServices(IServiceCollection services)
    {
        var manager = new ApplicationPartManager();
        manager.ApplicationParts.Add(new AssemblyPart(typeof(Startup).Assembly));
        services.AddSingleton(manager);
        services.AddCors();
        services.AddMvcCore().AddJsonFormatters();

        services.Configure<IISOptions>(options => new IISOptions
        {
            AutomaticAuthentication = true,
            ForwardClientCertificate = false,
            ForwardWindowsAuthentication = false
        });

    }

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

        app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            RequireHttpsMetadata = false,
            Authority = Settings.AuthorityUrl,
            ApiName = Settings.ApiName
        });

        app.UseStaticFiles();
        var url = Configuration["originUrl"];
        app.UseCors(
            options => options.WithOrigins(url).AllowAnyHeader().AllowAnyMethod().AllowCredentials()
        );

        app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
        app.UseMvc();
    }

In my OAuth server I am using the Quickstart for IdentityServer4

  public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                .AddSigningCredential(new X509Certificate2(Settings.CertPath, Settings.Password))
                .AddTestUsers(InMemoryConfiguration.Users().ToList())
                .AddInMemoryClients(InMemoryConfiguration.Clients())
                .AddInMemoryApiResources(InMemoryConfiguration.ApiResources());

            services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
                {
                    options.RequireHttpsMetadata = false;
                    options.Authority = Settings.AuthorityUrl;
                    options.ApiName = Settings.ApiName;
                });
            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, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
            loggerFactory.AddDebug();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMiddleware<StackifyMiddleware.RequestTracerMiddleware>();
            app.UseIdentityServer();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }
    }

And this is the method I am calling in Postman;

[HttpGet("get")]
public async Task<IActionResult> Get()
{
    var claims = User.Claims;
    var username = User.Identity.Name;
    this.NLogger.Info("api/comboboxdata/get".ToPrefix());
    try
    {
        var container = new ComboBoxData(this.SirUoW);
        return Ok(container);
    }
    catch (Exception e)
    {
        var message = "Error getting combo box data";
        await ReportException(e, message);
        var status = OperationStatus.CreateFromException(message, e);
        return BadRequest(status);
    }
}

In Postman I get the bearer token and put it in the header. The method is successfully called and returns the data. The claims are also set as expected, and when the token expires the claims are empty. However [Authorize] does not block the request if the token is invalid or is not sent. The Authorize attribute is at the beginning of the controller;

 [Authorize]
    [Route("api/comboboxdata")]
    public class ComboBoxDataController : BaseSirController
    {

How do I put this right?


Solution

  • You should add AddAuthorizationmethod to enable authorization services in your web api :

    services.AddMvcCore()
                    .AddAuthorization()
                    .AddJsonFormatters();