Implement Scalar UI in .NET API with Authorization Option

Introduction

With the release of .NET 9, Microsoft announced that they will no longer provide the default Swagger gen UI with any .NET API project. Previously, when we created a .NET API project, Microsoft automatically added the Swagger Swashbuckle package, which provided methods like apps.UseSwagger() and app.UseSwaggerUI(). These methods showed API documentation with a predefined UI for testing directly in the browser without using any third-party apps like Postman. However, Swagger is no longer integrated with .NET 9 web API projects. This decision was made because the package hasn't been maintained properly recently, and many user-reported issues remain unresolved.

The Microsoft team has created a new package called Microsoft.AspNetCore.OpenApi, which provides built-in OpenAPI documentation generation similar to Swagger. However, this only provides JSON documentation of all endpoints and schema definitions without any UI showing in the browser. The main goal of this change is to let users implement their preferred UI library, whether it's Swagger or any other alternative. Microsoft removing the default Swagger package doesn't mean you can't install Swagger again in your project - you can add it and perform all the same operations as before.

There are many alternatives to Swagger available currently, but in this article, we're going to discuss and implement Scalar in our API project. After Swagger, Scalar has become increasingly popular among developers.

Creating New Project

When you create new projects with .NET 9, it will ask if you want to configure OpenAPI support. If you check this checkbox, it will add the Microsoft.AspNetCore.OpenApi package to your project and register the OpenAPI service in the program.cs file like this.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

OpenApi Package

Now, when you run your API and navigate to /OpenApi/v1.json, it will show the documentation generated by default, which contains information about your endpoints and all the schemas you have used, as shown in the image below.

API

Configure Scalar.NET

First, open your package manager and install Scalar.AspNetCore.

Scalar.NET

Then, just add the app.MapScalarApiReference(); in your program.cs file to map all the API references and routes of Scalar UI.

Now, if you go to /Scalar/V1, you will see a beautiful UI for your endpoints. Here, I only have one endpoint, so it looks like this.

Scalar/V1

Configure Options of Scalar

You can configure multiple options and change the settings of your UI. Some configurations include.

  • Title: Set the document title which shows on top of the browser tab
  • DarkMode: true/false to enable and disable dark mode
  • Favicon: Set the favicon of the document
  • DefaultHttpClient: Show the default HTTP client when UI loads in the browser. It shows the code implementation for the respective programming language.
  • HideModels: true/false to set whether to show model definitions
  • Layout: Set the layout/theme of Scalar UI
  • ShowSidebar: true/false to set whether to show sidebar. This only works when you have chosen the modern layout.

And many more.

Open Scalar UI by Default

You might have noticed that we have to type scalar/v1 every time in the URL to see the Scalar UI. We can change the launch URL so we don't have to do this repeatedly. Open the launchsettings.json file and add the launch URL to your profile. I have added it for both HTTP and HTTPS. You can configure it as per your requirements.

Open Scalar UI

Working with Authorization and JWT Token

In most APIs, we implement JWT tokens or other types of token authentication. So, I have added a few lines of code to implement authorization using the JWT token. I have also installed Microsoft.AspNetCore.Authentication.JwtBearer package for this.

builder.Services
    .AddAuthorization()
    .AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = false,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("your_jwt_key")),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/test1", () => "This is test 1 endpoint")
    .WithName("Test1")
    .RequireAuthorization();

When I call this test1 endpoint, it gives me a 401 error (unauthorized). So, how can we resolve this? We can simply pass an auth token, but if you look at Scalar, there's no option to add an auth/bearer token on their UI. There's no option for Auth type even if I have added PreferredSecurityScheme as Bearer in MapScalarApiReference.

options.Authentication = new ScalarAuthenticationOptions
{
    PreferredSecurityScheme = "Bearer"
};

Authentication

If you pass your auth token in headers with the Authorization key, it works, but that's not what we want, right? We want a similar interface to Swagger, which shows options to add tokens on the home page or in individual endpoints. This is an issue with Scalar and has been reported on their GitHub repo: https://github.com/scalar/scalar/issues/4055.

Authorization key

However, there is a way to achieve what we want and resolve this issue. We can use the functionality of document transformers in OpenAPI, about which Microsoft provides detailed documentation here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi?view=aspnetcore-9.0.

Using this Transformer, we can inform Scalar that we want to show the Authentication option on our UI so that Scalar can add it on the home page and also in individual endpoints.

Here's the transformer class.

internal sealed class BearerSecuritySchemeTransformer : IOpenApiDocumentTransformer
{
    private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;

    public BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider)
    {
        _authenticationSchemeProvider = authenticationSchemeProvider;
    }

    public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
    {
        var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();

        if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
        {
            var requirements = new Dictionary<string, OpenApiSecurityScheme>
            {
                ["Bearer"] = new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer",
                    In = ParameterLocation.Header,
                    BearerFormat = "JWT"
                }
            };

            document.Components ??= new OpenApiComponents();
            document.Components.SecuritySchemes = requirements;

            foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
            {
                operation.Value.Security.Add(new OpenApiSecurityRequirement
                {
                    [new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                        }
                    }] = Array.Empty<string>()
                });
            }
        }
    }
}

This code will add an Authentication option on the Home page and in all request endpoints where you can pass your token to send requests.

 Authentication option

Bearer Token

This code modifies OpenAPI/Scalar documentation to show that the API supports Bearer token authentication.

  1. It first checks if the API has "Bearer" authentication enabled
  2. If Bearer authentication exists, it adds a security scheme in OpenAPI/Scalar
  3. This security scheme tells OpenAPI/Scalar that requests should include a JWT (JSON Web Token) in the Authorization header
  4. By default, this only adds support for authentication but does not require it in OpenAPI/Scalar UI
  5. To make authentication look required in the UI, the code loops through all API endpoints and marks them as needing a Bearer token

Scalar DOTNET

The following loop does that,

foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
{
    operation.Value.Security.Add(new OpenApiSecurityRequirement
    {
        [new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Id = "Bearer",
                Type = ReferenceType.SecurityScheme
            }
        }] = Array.Empty<string>()
    });
}

This only affects the OpenAPI/Scalar UI and does not actually enforce authentication in the API. Even if the UI shows authentication as required, the API will still accept requests without a token unless it has [Authorize] or RequireAuthorization().

RequireAuthorization

To apply this transformation in OpenAPI/Scalar, use the following line.

builder.Services.AddOpenApi(options =>
{
    options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

This ensures the security scheme and requirements are added whenever OpenAPI/Scalar documentation is generated.

If you want to actually enforce authentication, you need to add [Authorize] to controllers or RequireAuthorization() in Minimal API.

Now you can pass your token in this input, and it will be passed to the server without any issue, and you won't get a 401 error anymore.

401 error

I hope you like this article. If you have any questions, you can ask them in the comments, and don't forget to like and follow.

You can access or download this project from my GitHub.


Recommended Free Ebook
Similar Articles