Swagger UI and Authentication in Asp.Net Core 2.2

This is a recipe for setting up SwaggerUI for a secure Asp.Net Core 2.2 WebApi.

In this recipe we will use the ClientCredentials flow. This means that you must get the token from somewhere, or generate it programmatically.

Later I’ll create a recipe using the Implicit flow. Unfortunately, I don’t think OpenIDConnect is supported yet so for now we have to do with OAuth2.

I think OpenIDConnect will be supported in Swashbuckle.AspNetCore version 5 (which is in rc2 now).

Open VS 2019 and create a new project: ASP.NET Core Web Application

Create a new ASP.NET Core Web Application
Create a new ASP.NET Core Web Application

Create a new secure controller

using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace TestingSwaggerUI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class SecureController : ControllerBase
    {
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new [] { "secure1", "secure2" };
        }

    }
}

Setup the token validation middleware

I use IdentityServer4 as my identity provider. The setup of clients and scopes in IdentityServer4 is beyond the scope of this Swagger recipe.

First include the NuGet package: IdentityServer4.AccessTokenValidation

Then add the following to the ConfigureServices method in Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "https://localhost:44300/identity";
            options.ApiName = "testswaggerapi";
        });
}

And add the following to the Configure method in Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

    app.UseAuthentication();

    app.UseHttpsRedirection();
    app.UseMvc();
}

Add a client and scope in IdentityServer4

The name of the scope I used was testswaggerapi. I also created a ClientCredentials client (machine-to-machine) that I can use to test the access to my WebApi.

Use Postman to verify access to the secure page

I set Authorization to OAuth 2.0. Request a token, and send the request

Setup the Swagger middleware

Include the NuGet package: Swashbuckle.AspNetCore

The current version is 4. When version 5 is out, the configuration of this middleware will change. We will also get support for OpenIdConnect.

Add the following to the ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "https://localhost:44300/identity";
            options.ApiName = "testswaggerapi";
            options.LegacyAudienceValidation = false;
        });

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo
        {
            Title = "My API", Version = "v1"
        });
        c.AddSecurityDefinition("Bearer", new ApiKeyScheme
        {
            In = "header",
            Description = "Please enter 'Bearer' space and JWT",
            Name = "Authorization",
            Type = "apiKey"
        });
        c.AddSecurityRequirement(
            new Dictionary<string, IEnumerable<string>>
        {
            { "Bearer", new string[]{}}
        });
    });
}

Add the following to the Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseHsts();
    }

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

    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });

    app.UseMvc();
}

Try it out

Start up your app and go to https://localhost:port/swagger

Request a token using Postman (see above)

Click the Authorize button and enter the bearer token:

You should now be able to see the secure values: