Skip to content

simoneM93/AspNetCoreAuthKit

Repository files navigation

AspNetCoreAuthKit

NuGet Publish to NuGet License: MIT GitHub Sponsors Changelog

A zero-friction authentication & authorization toolkit for ASP.NET Core with JWT Bearer, API Key, Refresh Tokens with rotation, and dynamic claim policies — all wired up with a single fluent call.

Why AspNetCoreAuthKit? Every ASP.NET Core project ends up writing the same boilerplate: JWT configuration, API Key middleware, refresh token logic, claim-based policies. AspNetCoreAuthKit wraps all of this into a clean, testable, opt-in abstraction.


✨ Features

  • 🔐 JWT Bearer — generate, validate and refresh tokens with one method call
  • 🔑 API Key — header or query string, static list or custom async validator
  • ♻️ Refresh Tokens — token rotation, revoke single device or all devices
  • 🛡️ Dynamic claim policies[RequireClaim("role", "admin")] without manual registration
  • 📋 Common policiesAdminOnly, AuthenticatedUser, ApiKeyOrJwt out of the box
  • 🔀 Multi-scheme — JWT and API Key in parallel on the same app
  • 🧩 Extensible — plug in your own IRefreshTokenStore (Redis, EF Core, etc.)
  • 🧪 DI-ready — every module is opt-in, nothing is registered unless you ask

📋 Requirements

Requirement Minimum version
.NET 8.0+
ASP.NET Core 8.0+

🚀 Installation

dotnet add package AspNetCoreAuthKit

🎯 Quick Start

1. Register services

// Program.cs
builder.Services.AddAuthKit(opt => opt
    .UseJwt(jwt =>
    {
        jwt.SecretKey         = builder.Configuration["Auth:SecretKey"]!;
        jwt.Issuer            = "myapp";
        jwt.Audience          = "myapp-users";
        jwt.AccessTokenExpiry = TimeSpan.FromMinutes(15);
    })
    .UseApiKey(key =>
    {
        key.HeaderName = "X-Api-Key";
        key.ValidKeys  = builder.Configuration
            .GetSection("Auth:ApiKeys").Get<string[]>()!;
    })
    .UseRefreshTokens()
    .UseAuthorization()
);

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

2. Generate a token at login

app.MapPost("/auth/login", async (LoginRequest req,
    IJwtTokenService tokenService,
    IRefreshTokenStore store) =>
{
    // validate credentials...

    var result = tokenService.GenerateToken(new TokenRequest
    {
        Subject = user.Id,
        Claims  = [new Claim("role", user.Role)]
    });

    await store.SaveAsync(result.RefreshToken, new RefreshTokenEntry
    {
        Subject   = user.Id,
        ExpiresAt = DateTimeOffset.UtcNow.AddDays(7)
    });

    return Results.Ok(result);
    // { accessToken, refreshToken, expiresAt }
});

3. Refresh a token

app.MapPost("/auth/refresh", async (RefreshRequest req,
    IRefreshTokenService refreshService) =>
{
    try
    {
        var result = await refreshService.RefreshAsync(
            req.AccessToken,
            req.RefreshToken);
        return Results.Ok(result);
    }
    catch (RefreshTokenException)
    {
        return Results.Unauthorized();
    }
});

4. Protect endpoints with policies

// Built-in policies
app.MapDelete("/users/{id}", ...).RequireAuthorization(CommonPolicies.AdminOnly);
app.MapGet("/dashboard", ...).RequireAuthorization(CommonPolicies.ApiKeyOrJwt);

// Declarative claim attribute — no manual policy registration needed
[RequireClaim("role", "admin")]
public IActionResult DeleteUser(int id) => Ok();

// Multiple accepted values (OR logic)
[RequireClaim("role", "admin", "moderator")]
public IActionResult BanUser(int id) => Ok();

📝 Refresh Tokens

AspNetCoreAuthKit implements token rotation by default: every refresh invalidates the old token and issues a new pair.

Operation Method
Refresh access token refreshService.RefreshAsync(accessToken, refreshToken)
Logout single device refreshService.RevokeAsync(refreshToken)
Logout all devices refreshService.RevokeAllAsync(subject)

Custom store (Redis, EF Core, etc.)

public class RedisRefreshTokenStore : IRefreshTokenStore { ... }

.UseRefreshTokens(rt =>
{
    rt.CustomStore = typeof(RedisRefreshTokenStore);
})

📚 API Reference

IJwtTokenService methods

Method Description
GenerateToken(TokenRequest) Generates a new access + refresh token pair
ValidateToken(string) Validates a token, returns ClaimsPrincipal?
ValidateTokenIgnoreExpiry(string) Validates ignoring lifetime (used during refresh)
GenerateRefreshToken() Generates a cryptographically secure random token

TokenRequest properties

Property Type Description
Subject string User ID or unique identifier (required)
Claims IEnumerable<Claim> Additional claims to embed in the token
ExpiresIn TimeSpan? Per-token expiry override

CommonPolicies constants

Constant Behaviour
CommonPolicies.AuthenticatedUser Any authenticated user
CommonPolicies.AdminOnly Requires admin role claim
CommonPolicies.ApiKeyOrJwt Accepts either scheme

⚙️ Configuration Reference

JwtAuthOptions

Option Type Default Description
SecretKey string (required) HMAC signing key — validated at startup
Issuer string "" Token issuer
Audience string "" Token audience
AccessTokenExpiry TimeSpan 1 hour Access token lifetime
RefreshTokenExpiry TimeSpan 7 days Refresh token lifetime
Algorithm string HmacSha256 Signing algorithm
ClockSkew TimeSpan 30 seconds Clock skew tolerance

ApiKeyOptions

Option Type Default Description
HeaderName string X-Api-Key Header to read the key from
QueryParamName string? null Query param name (disabled by default)
ValidKeys string[] [] Static list of valid keys
ValidateKeyAsync Func<string, Task<bool>>? null Custom async validator (overrides ValidKeys)

AuthKitAuthorizationOptions

Option Type Default Description
RoleClaimType string "role" Claim type used for roles
AdminRoleValue string "admin" Value that identifies an admin

🧪 Testing

IJwtTokenService and IRefreshTokenStore are plain interfaces — mock them directly in unit tests:

var tokenServiceMock = new Mock<IJwtTokenService>();

tokenServiceMock
    .Setup(s => s.GenerateToken(It.IsAny<TokenRequest>()))
    .Returns(new TokenResult
    {
        AccessToken  = "mocked.jwt.token",
        RefreshToken = "mocked-refresh-token",
        ExpiresAt    = DateTimeOffset.UtcNow.AddMinutes(15)
    });

❤️ Support

If you find AspNetCoreAuthKit useful, consider sponsoring its development.

Sponsor simoneM93


📄 License

MIT — see LICENSE for details.

About

Zero-friction authentication and authorization toolkit for ASP.NET Core. Provides JWT Bearer, API Key, Refresh Tokens with token rotation, and dynamic claim policies — all wired up with a single fluent AddAuthKit() call. Every module is opt-in with no unnecessary overhead.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages