Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rkd.Scalar - API Documentation Platform for ASP.NET

Rkd.Scalar logo

NuGet Build & Publish License: MIT

Rkd.Scalar adds a production-ready API documentation platform. It combines documentation, authentication helpers and security protections into a single fluent configuration layer.


Core Features

Rkd.Scalar integrates:

  • Scalar UI
  • OpenAPI generation
  • JWT Bearer authentication
  • API Key authentication
  • Basic authentication
  • API versioning integration
  • Scalar UI protection
  • Default JWT login endpoint with built-in rate limiting (development / testing convenience)

All features are enabled through a simple fluent builder API.


Why Rkd.Scalar

Rkd.Scalar focuses on three principles:

  • Simplicity – drastically reduce OpenAPI setup code
  • Security – protect documentation and test endpoints safely
  • Extensibility – modular feature-based architecture

Key Capabilities

  • Minimal configuration
  • Built-in Basic Authentication support
  • Built-in JWT Bearer Authentication support
  • Built-in API Key Authentication support
  • Optional default JWT login endpoint for development and testing
  • Scalar UI protection via Basic Auth
  • Built-in API versioning integration
  • Feature-based modular architecture

Who is this for?

  • Teams building internal APIs
  • SaaS platforms exposing partner APIs
  • Developers who want production-ready documentation fast
  • Teams tired of complex Swagger configuration

Installation

Install via .NET CLI:

dotnet add package Rkd.Scalar

Or via Package Manager:

Install-Package Rkd.Scalar

30‑Second Setup

Most APIs can enable Scalar with only a few lines:

// JWT validation only (recommended baseline)
builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1")
    .WithBearerAuth(jwtOptions);
// JWT + default login endpoint (development / testing only)
builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1")
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
    .WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1));

Run the application and open:

/scalar/v1

You now have:

  • OpenAPI documentation
  • Scalar UI
  • JWT authentication
  • A login endpoint for local testing (when using WithDefaultJwtLogin)

For production, prefer exposing your own login endpoint using the services registered by Rkd.Scalar. See JWT in Production.


Quick Start

Without Rkd.Scalar

200+ lines of configuration
OpenAPI
JWT
Auth schemes
Versioning
Security definitions

With Rkd.Scalar

Minimal setup example (development):

using Rkd.Scalar.Extensions;
using Rkd.Scalar.Security.Jwt;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddAuthorization();

var jwtOptions = new JwtOptions
{
    Secret = "SUPER_SECRET_KEY_MINIMUM_32_CHARACTERS",
    Issuer = "MyApi",
    Audience = "MyApiClient",
    Expiration = TimeSpan.FromHours(2),
    ValidateNotBefore = true
};

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1")
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
    .WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1));

var app = builder.Build();

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

app.MapControllers();

app.UseRkdScalar(new RkdScalarConfiguration
{
    Title = "My API"
});

app.Run();

Note: hardcoding the JWT secret is shown here only for brevity. In real applications, load it from environment variables, user secrets or a secret manager — never commit secrets to source control.


Customizing the Scalar UI

Rkd.Scalar allows full customization of Scalar through ConfigureScalar.

Simple UI configuration:

app.UseRkdScalar(new RkdScalarConfiguration
{
    Title = "My API",
    Theme = ScalarTheme.BluePlanet
});

Advanced Scalar customization:

app.UseRkdScalar(new RkdScalarConfiguration
{
    Title = "My API",
    ConfigureScalar = opt =>
    {
        opt.DarkMode = true;
        opt.Theme = ScalarTheme.BluePlanet;
    }
});

This gives direct access to ScalarOptions while still keeping Rkd.Scalar's simplified configuration.


Why not Swashbuckle?

Feature Swashbuckle Rkd.Scalar
OpenAPI generation
Scalar UI
JWT login endpoint ✔ (dev)
API Key auth manual built-in
UI protection
Versioning integration manual built-in

Configuration via appsettings.json

Rkd.Scalar can also be configured using appsettings.json.

Example configuration:

{
  "RkdScalar": {
    "Title": "My API",
    "OpenApiRoutePattern": "/openapi/{documentName}.json",
    "Theme": "BluePlanet"
  }
}

Program.cs:

...
app.MapControllers();

var scalarOptions =
    builder.Configuration
           .GetSection("RkdScalar")
           .Get<RkdScalarConfiguration>()!;

scalarOptions.ConfigureScalar = opt =>
{
    opt.DarkMode = true;
};

app.UseRkdScalar(scalarOptions);

app.Run();

This approach is useful for:

  • environment‑based configuration
  • DevOps pipelines
  • centralized configuration

JWT Options via appsettings.json

Instead of building JwtOptions manually, you can bind it directly from a configuration section using the section-name overloads:

appsettings.json:

{
  "JwtOptions": {
    "Secret": "SUPER_SECRET_KEY_MINIMUM_32_CHARACTERS",
    "Issuer": "MyApi",
    "Audience": "MyApiClient",
    "Expiration": 2,
    "ValidateNotBefore": true
  }
}

Expiration is expressed in hours.

Program.cs:

// Validation-only mode, bound from the "JwtOptions" section (default name)
builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithBearerAuth();

// Or with credential validation, using a custom section name
builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithBearerAuth<AuthCredential, LoginValidator>("Auth:Jwt");

If the section is missing or invalid (empty Secret, non-positive Expiration), the application fails fast at startup with a descriptive error.


JWT Authentication

Rkd.Scalar supports two JWT modes:

1) Validation-only (no login endpoint)

Use this mode when your API only validates bearer tokens issued elsewhere (an identity provider, an auth microservice, another API).

var jwtOptions = new JwtOptions
{
    Secret = "SUPER_SECRET_KEY_MINIMUM_32_CHARACTERS",
    Issuer = "MyApi",
    Audience = "MyApiClient",
    Expiration = TimeSpan.FromHours(2),
    ValidateNotBefore = true
};

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithBearerAuth(jwtOptions);

This configures JWT validation and OpenAPI Bearer security without requiring a credential model or validator.

2) JWT with credential validation (token issuing)

Use this mode when your API itself issues tokens. It registers:

  • ICredentialValidator<TCredential> (your implementation)
  • IJwtTokenService (token generation)
builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions);

From here you have two options for the login endpoint:

  • Production: implement your own login endpoint (recommended — see below)
  • Development / testing: use WithDefaultJwtLogin for a zero-code endpoint

Example credential model:

public class AuthCredential
{
    public required string Username { get; set; }
    public required string Password { get; set; }
}

JWT in Production — Custom Login Endpoint

This is the recommended approach for production.

WithBearerAuth<TCredential, TValidator>() registers everything you need to issue tokens from your own endpoint: your ICredentialValidator<TCredential> and the IJwtTokenService. You keep full control over the route, versioning, rate limiting policy, logging, auditing and response shape.

Program.cs

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1")
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions);

Login endpoint (Controller)

using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Rkd.Scalar.Security.Contracts;
using Rkd.Scalar.Security.Jwt;

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/auth")]
public sealed class AuthController : ControllerBase
{
    private readonly ICredentialValidator<AuthCredential> _validator;
    private readonly IJwtTokenService _jwtService;

    public AuthController(
        ICredentialValidator<AuthCredential> validator,
        IJwtTokenService jwtService)
    {
        _validator = validator;
        _jwtService = jwtService;
    }

    [HttpPost("login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login(
        [FromBody] AuthCredential credential,
        CancellationToken cancellationToken)
    {
        var identity = await _validator.ValidateAsync(credential, cancellationToken);

        if (identity is null)
            return Unauthorized();

        var token = _jwtService.GenerateToken(identity);

        return Ok(new
        {
            access_token = token.Token,
            expires_at = token.ExpiresAtUtc
        });
    }
}

Both ICredentialValidator<AuthCredential> and IJwtTokenService are resolved from dependency injection — no extra registration required.

Production-grade validator

In production, the validator should check credentials against a real user store using password hashing — never plaintext comparison:

using Rkd.Scalar.Security.Contracts;
using System.Security.Claims;

public sealed class LoginValidator : ICredentialValidator<AuthCredential>
{
    private readonly IUserRepository _users;
    private readonly IPasswordHasher _hasher;

    public LoginValidator(IUserRepository users, IPasswordHasher hasher)
    {
        _users = users;
        _hasher = hasher;
    }

    public async Task<ClaimsIdentity?> ValidateAsync(
        AuthCredential request,
        CancellationToken cancellationToken = default)
    {
        var user = await _users.FindByUsernameAsync(
            request.Username, cancellationToken);

        if (user is null || !_hasher.Verify(request.Password, user.PasswordHash))
            return null;

        var claims = new List<Claim>
        {
            new(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new(ClaimTypes.Name, user.Username)
        };

        claims.AddRange(user.Roles.Select(r => new Claim(ClaimTypes.Role, r)));

        return new ClaimsIdentity(claims, "Bearer");
    }
}

IUserRepository and IPasswordHasher represent your own persistence and hashing infrastructure (e.g. Microsoft.AspNetCore.Identity.PasswordHasher<T>, BCrypt or Argon2).

Production checklist

  • Load the JWT secret from environment variables or a secret manager
  • Hash and verify passwords — never store or compare plaintext
  • Apply your own rate limiting policy to the login route ([EnableRateLimiting("your-policy")])
  • Log failed authentication attempts for auditing
  • Consider refresh tokens and token revocation if your scenario requires them

Default JWT Login Endpoint (Development / Testing)

⚠️ This feature is intended for development, testing and prototyping — not for production. It exposes a generic login endpoint with a fixed response shape and a simple fixed-window rate limiter. For production, build your own endpoint as shown in JWT in Production.

Rkd.Scalar can automatically expose a login endpoint that issues JWT tokens, which is convenient for testing your API through the Scalar UI without writing any authentication endpoint.

.WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
.WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1))

This creates:

POST /auth/login

The request body is automatically bound to the credential model (TCredential).

This means the JSON payload must match the credential type configured in WithBearerAuth<TCredential, TValidator>().

Example request:

{
  "username": "admin",
  "password": "123"
}

Example response:

{
  "access_token": "JWT_TOKEN",
  "expires_at": "2026-01-01T12:00:00Z"
}

Built-in Brute Force Protection

The default login endpoint automatically configures ASP.NET Rate Limiting using the values you provide:

.WithDefaultJwtLogin<AuthCredential>(
    "/auth/login",
    5,
    TimeSpan.FromMinutes(1))

This means:

  • Maximum 5 login attempts
  • Within 1 minute

If exceeded, the API returns:

HTTP 429 Too Many Requests

Don't forget to add app.UseRateLimiter(); before app.UseAuthentication(); in your Program.cs file.

Requirements

WithDefaultJwtLogin() requires JWT authentication with credential validation.

You must configure this before calling it:

.WithBearerAuth<TCredential, TValidator>(jwtOptions)

The validation-only overload cannot issue login tokens:

.WithBearerAuth(jwtOptions) // ❌ not compatible with WithDefaultJwtLogin

Credential Type Requirement

The credential type used in WithDefaultJwtLogin<TCredential>() must be the same used in WithBearerAuth<TCredential, TValidator>().

Correct usage:

.WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
.WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1))

Incorrect usage (will throw an exception during startup):

.WithBearerAuth<BasicAuthCredentials, UiCredentialValidator>(jwtOptions)
.WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1))

The login endpoint depends on the credential model registered for JWT authentication, therefore both methods must use the same request model type.


Authentications

Important

ICredentialValidator<T> is provided by the Rkd.Scalar NuGet package (Rkd.Scalar.Security.Contracts).

When implementing validators, you should use the interface from the package, not create your own interface with the same name. This interface defines the contract used internally by Rkd.Scalar authentication features (Basic, JWT, and API Key).


Basic Authentication

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithBasicAuth<UiCredentialValidator>();

Validator example (illustrative only — in real applications validate against a user store with hashed passwords):

public class UiCredentialValidator : ICredentialValidator<BasicAuthCredentials>
{
    public Task<ClaimsIdentity?> ValidateAsync(
        BasicAuthCredentials request,
        CancellationToken cancellationToken = default)
    {
        if (request.Username == "admin" && request.Password == "123")
        {
            var identity = new ClaimsIdentity(
                new[] { new Claim(ClaimTypes.Name, request.Username) },
                "Basic");

            return Task.FromResult<ClaimsIdentity?>(identity);
        }

        return Task.FromResult<ClaimsIdentity?>(null);
    }
}

API Key Authentication

Rkd.Scalar supports API Key authentication using a request header.

Enable API Key support:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithApiKeyAuth<ApiKeyValidator>();

Requests must include the header:

X-API-Key: YOUR_API_KEY

Validator example (illustrative only — in real applications validate keys against a secure store):

using Rkd.Scalar.Security.ApiKey;
using Rkd.Scalar.Security.Contracts;
using System.Security.Claims;

public class ApiKeyValidator : ICredentialValidator<ApiKeyCredentials>
{
    public Task<ClaimsIdentity?> ValidateAsync(
        ApiKeyCredentials request,
        CancellationToken cancellationToken = default)
    {
        if (request.Key == "ABC123")
        {
            var identity = new ClaimsIdentity(
                new[]
                {
                    new Claim(ClaimTypes.Name, "ApiKeyUser"),
                    new Claim(ClaimTypes.Role, "SERVICE")
                },
                "ApiKey"
            );

            return Task.FromResult<ClaimsIdentity?>(identity);
        }

        return Task.FromResult<ClaimsIdentity?>(null);
    }
}

The API Key scheme will automatically appear in the Scalar authentication panel.


Securing Endpoints

Example protected endpoint:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[Authorize(AuthenticationSchemes = "Bearer,Basic,ApiKey")]
[HttpGet("secure")]
public IActionResult SecureEndpoint()
{
    return Ok("Authorized access");
}

Protecting the Scalar UI

To require authentication before accessing the documentation UI:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithUiProtection<UiCredentialValidator>();

This protects:

  • Scalar UI
  • OpenAPI documents

using Basic Authentication.


Reading UI Credentials from appsettings.json

When using WithUiProtection<TValidator>(), the recommended approach is to implement the validator by injecting IConfiguration and reading credentials directly from appsettings.json.

This keeps Program.cs clean and allows credentials to be managed per environment without changing code.

appsettings.json:

{
  "UiCredentials": {
    "Username": "myuser",
    "Password": "mypassword"
  }
}

Validator implementation:

using System.Security.Claims;
using Microsoft.Extensions.Configuration;
using Rkd.Scalar.Security.Basic;
using Rkd.Scalar.Security.Contracts;

public sealed class UiCredentialValidator : ICredentialValidator<BasicAuthCredentials>
{
    private readonly IReadOnlyDictionary<string, string> _credentials;

    public UiCredentialValidator(IConfiguration configuration)
    {
        var section = configuration.GetSection("UiCredentials");
        var creds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

        // Format 1: UiCredentials:Username / UiCredentials:Password
        var singleUsername = section["Username"];
        var singlePassword = section["Password"];
        if (!string.IsNullOrWhiteSpace(singleUsername) && singlePassword is not null)
            creds[singleUsername] = singlePassword;

        // Format 2: UiCredentials:{ "user1": "pass1", "user2": "pass2" }
        foreach (var child in section.GetChildren())
        {
            if (child.Key.Equals("Username", StringComparison.OrdinalIgnoreCase) ||
                child.Key.Equals("Password", StringComparison.OrdinalIgnoreCase))
                continue;

            if (!string.IsNullOrWhiteSpace(child.Key) && child.Value is not null)
                creds[child.Key] = child.Value;
        }

        _credentials = creds;
    }

    public Task<ClaimsIdentity?> ValidateAsync(
        BasicAuthCredentials request,
        CancellationToken cancellationToken = default)
    {
        if (request is null ||
            string.IsNullOrWhiteSpace(request.Username) ||
            request.Password is null)
            return Task.FromResult<ClaimsIdentity?>(null);

        var valid = _credentials.TryGetValue(request.Username, out var expectedPassword) &&
                    string.Equals(expectedPassword, request.Password, StringComparison.Ordinal);

        if (!valid)
            return Task.FromResult<ClaimsIdentity?>(null);

        var identity = new ClaimsIdentity(
            new[]
            {
                new Claim(ClaimTypes.Name, request.Username),
                new Claim(ClaimTypes.Role, "user")
            },
            authenticationType: "Basic");

        return Task.FromResult<ClaimsIdentity?>(identity);
    }
}

This validator supports two credential formats in appsettings.json:

Single user:

{
  "UiCredentials": {
    "Username": "myuser",
    "Password": "mypassword"
  }
}

Multiple users:

{
  "UiCredentials": {
    "alice": "password1",
    "bob": "password2"
  }
}

Behavior:

  • Username comparison is case-insensitive
  • Password comparison is case-sensitive (exact match)
  • Any username with a null password is rejected

Registration:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithUiProtection<UiCredentialValidator>()
    .WithBearerAuth(jwtOptions)
    .WithLowercaseRouting();

IConfiguration is injected automatically by ASP.NET's dependency injection container. No additional registration is required.


API Versioning

Rkd.Scalar integrates with Asp.Versioning automatically.

Configuration:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1", "v2", "v3");

Example controller:

using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/payments")]
public class PaymentController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok("API v1 running");
    }
}

Scalar automatically generates a document for each version.


Launch Scalar Automatically

To open Scalar automatically when the application starts:

Edit:

Properties/launchSettings.json

Enable browser launch:

"launchBrowser": true

Set Scalar as startup page:

"launchBrowser": true,
"launchUrl": "scalar/v1"

Feature‑Based Architecture

Rkd.Scalar is built using a modular feature system.

Rkd.Scalar

Builder
Configuration
Extensions
Features
Middleware
OpenApi
Security

Each capability (JWT, Basic Auth, API Key Auth, Versioning, UI protection) is implemented as an independent feature.

This makes the library:

  • easy to extend
  • easy to maintain
  • easy to evolve

Advantages

  • Extremely simple configuration
  • Minimal OpenAPI boilerplate
  • Built-in security features
  • Modern Scalar documentation UI
  • Versioning support
  • Highly extensible architecture

Compatibility

  • .NET 10
  • ASP.NET Core Minimal APIs
  • ASP.NET Core Controllers

Production Example

A realistic production setup issues tokens through your own login endpoint (see JWT in Production) and does not use WithDefaultJwtLogin:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1", "v2", "v3")
    .WithUiProtection<UiCredentialValidator>()
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
    .WithApiKeyAuth<ApiKeyValidator>()
    .WithLowercaseRouting();

If your API does not issue tokens at all (they come from an external identity provider), prefer the simpler validation-only setup:

.WithBearerAuth(jwtOptions)

Development Example

For local development and prototyping, the default login endpoint removes all authentication boilerplate:

builder.Services
    .AddRkdScalar(builder.Configuration)
    .WithVersioning("v1")
    .WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)
    .WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1));

Features Overview

Below is a brief explanation of each feature available in Rkd.Scalar and the problem it is designed to solve.


API Versioning

.WithVersioning("v1", "v2", "v3")

Enables API versioning and automatically exposes each version in the Scalar documentation UI.

Each version becomes selectable in the documentation interface, allowing developers to test and explore different API versions independently.

This feature integrates with ASP.NET API Versioning and configures the OpenAPI documents required for Scalar.

Typical use cases:

  • Maintaining backward compatibility between API versions
  • Gradually migrating clients between versions
  • Supporting multiple client applications using different API versions

Scalar UI Protection

.WithUiProtection<UiCredentialValidator>()

Protects the Scalar documentation interface using Basic Authentication.

This prevents unauthorized users from accessing the API documentation while still allowing the API itself to remain public if desired.

The provided validator (ICredentialValidator<BasicAuthCredentials>) is responsible for validating the credentials used to access the UI.

Typical use cases:

  • Restricting documentation access in production environments
  • Allowing only internal teams to view API documentation
  • Preventing accidental exposure of internal APIs

Basic Authentication

.WithBasicAuth<UiCredentialValidator>()

Enables HTTP Basic Authentication support for API endpoints.

This feature registers the required OpenAPI security scheme and integrates the authentication flow so credentials can be provided directly from the Scalar UI when testing endpoints.

The validator implementation is responsible for validating the provided username and password.

Typical use cases:

  • Internal APIs
  • Simple service-to-service authentication
  • Legacy integrations

JWT Bearer Authentication

Rkd.Scalar supports two JWT setup modes:

Validation-only (no token issuing):

.WithBearerAuth(jwtOptions)

JWT with credential validation (token issuing support):

.WithBearerAuth<AuthCredential, LoginValidator>(jwtOptions)

The validation-only mode configures token validation and the OpenAPI Bearer scheme. The generic mode additionally registers ICredentialValidator<TCredential> and IJwtTokenService, enabling token issuing either from your own endpoint (production) or from WithDefaultJwtLogin<TCredential>() (development).

This feature configures:

  • JWT token validation
  • OpenAPI security definitions
  • Authentication middleware integration

Typical use cases:

  • Modern API authentication
  • Stateless authentication
  • Mobile and SPA clients

Default JWT Login Endpoint (Development / Testing)

.WithDefaultJwtLogin<AuthCredential>("/auth/login", 5, TimeSpan.FromMinutes(1))

Registers a default login endpoint that issues JWT access tokens, intended for development, testing and prototyping.

The endpoint automatically binds the request body to the credential model (TCredential) and validates it using the configured ICredentialValidator<TCredential>.

Example endpoint:

POST /auth/login

The endpoint includes built-in rate limiting to protect against brute-force attempts during testing.

Example configuration above means:

  • Maximum 5 login attempts
  • Within 1 minute

If the limit is exceeded, the API returns:

HTTP 429 Too Many Requests

Typical use cases:

  • Development environments
  • Rapid prototyping
  • Integration test scenarios

For production, implement your own authentication endpoint using the services registered by WithBearerAuth<TCredential, TValidator>() — see JWT in Production.


API Key Authentication

.WithApiKeyAuth<ApiKeyValidator>()

Enables API Key authentication support.

Clients authenticate by sending an API key in the request header.

X-API-Key: YOUR_API_KEY

The provided validator (ICredentialValidator<ApiKeyCredentials>) is responsible for validating the API key.

The feature automatically registers the OpenAPI security scheme so the API key can be provided directly from the Scalar UI.

Typical use cases:

  • Partner integrations
  • Machine-to-machine communication
  • Public APIs with controlled access

Lowercase Routing

.WithLowercaseRouting()

Configures ASP.NET routing to generate lowercase URLs and query strings.

This improves URL consistency and avoids issues caused by case-sensitive routing in certain environments.

Benefits include:

  • Consistent API URLs
  • Better compatibility with proxies and gateways
  • Improved SEO for public APIs

Roadmap

Planned features:

  • OAuth2 support
  • Extended Scalar customization

Contributing

Pull requests are welcome.

Open an issue to propose new features or improvements.


License

MIT License


Author

Built on the belief that API documentation should take minutes, not hours.

About

Zero-boilerplate Scalar wrapper for ASP.NET Core that configures OpenAPI, Versioning, and Auth in seconds, featuring built-in UI Protection to secure your documentation.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages