Module

Authentication and authorization architecture.

Core.Auth provides JWT authentication, session management, claims-based permissions, and a complete admin API. Three packages cover backend services, API endpoints, and Blazor UI components.

Overview

The Auth module is split into three NuGet packages. Use only what you need — the base package provides services and abstractions, the API package adds REST endpoints, and the Components package provides ready-to-use Blazor pages.

Package Purpose Key Contents
Sillium.Core.Auth Core services and abstractions IAuthService, ISessionService, IProfileService, CoreAuthDbContext, JWT token generation, claims transformation
Sillium.Core.Auth.Api Minimal API endpoints Login, refresh, profile, admin user/role/claim management endpoints
Sillium.Core.Auth.Components Blazor Server UI Login page, profile, sessions, admin pages, CoreAuthStateProvider, CoreTokenStore

Backend Setup

Register Core.Auth services and map endpoints in your Program.cs. The module integrates with ASP.NET Core Identity and JWT Bearer authentication.

Service Registration

AddCoreAuth registers Identity, JWT authentication, session management, claims transformation, and all business services.

Show code
// Program.cs — Backend
services.AddCoreAuth(options =>
{
    options.Jwt.SigningKey = builder.Configuration["Auth:SigningKey"]!;
    options.Jwt.Issuer = "my-app";
    options.Jwt.Audience = "my-api";
    options.Jwt.AccessTokenExpiryMinutes = 60;
    options.Jwt.RefreshTokenExpiryDays = 7;

    options.Sessions.MaxSessionsPerUser = 10;

    options.Identity.RequireConfirmedEmail = true;
    options.Identity.Password.RequiredLength = 8;
    options.Identity.Password.RequireUppercase = true;
    options.Identity.Password.RequireDigit = true;
    options.Identity.Lockout.MaxFailedAccessAttempts = 5;
    options.Identity.Lockout.DefaultLockoutMinutes = 15;
});

// Register custom claim providers (optional)
services.AddScoped<IClaimDefinitionProvider, MyAppClaimProvider>();
services.AddCoreAuthPoliciesFromProviders();

Endpoint Mapping

MapCoreAuthEndpoints creates all auth, profile, and admin endpoint groups under the configured base path.

Show code
// Program.cs — Endpoint mapping
app.MapCoreAuthEndpoints(options =>
{
    options.BasePath = "/api/v1";
    options.AdminReadPolicy = "identity.read";
    options.AdminWritePolicy = "identity.update";
    options.AdminUsersCreatePolicy = "identity.users.create";
    options.ProfileReadPolicy = "auth.profile.read";
    options.ProfileUpdatePolicy = "auth.profile.update";
});

Database

CoreAuthDbContext extends IdentityDbContext and adds the UserSessions table for multi-device session tracking.

Show code
// Program.cs — Database
services.AddDbContext<CoreAuthDbContext>(options =>
    options.UseNpgsql(
        builder.Configuration.GetConnectionString("auth")));

Authentication Flow

Core.Auth implements a stateful JWT flow with refresh token rotation. Access tokens are short-lived (default 60 min), refresh tokens are long-lived (default 7 days) and rotated on each use to prevent replay attacks.

Flow Sequence

The complete authentication lifecycle from login to token refresh.

Show code
// 1. Client sends credentials
POST /auth/login  { "email": "...", "password": "..." }

// 2. Server validates, returns tokens + creates session
{ "accessToken": "eyJ...", "refreshToken": "abc123..." }

// 3. Client stores tokens, sends Bearer on every request
GET /me  → Authorization: Bearer eyJ...

// 4. Token expires → client uses refresh token
POST /auth/refresh  { "refreshToken": "abc123..." }

// 5. Server rotates session, returns new token pair
{ "accessToken": "eyJ...(new)", "refreshToken": "def456..." }
Public Endpoints
Method Path Description
POST /auth/login Email/password login, returns access + refresh tokens
POST /auth/token OAuth 2.0 Resource Owner Password flow
POST /auth/refresh Exchange refresh token for new token pair
POST /auth/revoke Revoke a refresh token (logout)
POST /auth/confirm-email Confirm email address with token
POST /auth/resend-confirmation Resend confirmation email
GET /me Get current user profile
PUT /me/change-password Change password (requires current password)

JWT Configuration

Token generation and validation are configured through CoreAuthOptions. Access tokens use HMAC-SHA512 signing. Refresh tokens are cryptographically random (64-byte entropy) and stored as SHA256 hashes.

CoreJwtOptions
Property Type Default Description
SigningKey string "" Base64-encoded HMAC-SHA512 signing key (min. 256 bits)
Issuer string "" Token issuer claim (iss)
Audience string "" Expected audience claim (aud)
AccessTokenExpiryMinutes int 60 Access token lifetime in minutes
RefreshTokenExpiryDays int 7 Refresh token lifetime in days
CoreSessionOptions
Property Type Default Description
MaxSessionsPerUser int 10 Maximum concurrent sessions per user
RefreshTokenExpiryDays int 7 Session refresh token lifetime in days

Permission System

Authorization uses claims-based policies. Users receive claims directly or through role membership. The system supports custom claim providers for application-specific permissions and implements deny-override semantics.

Custom Claim Provider

Implement IClaimDefinitionProvider to register application-specific claims that automatically become authorization policies.

Show code
// Define custom claims for your application
public class MyAppClaimProvider : IClaimDefinitionProvider
{
    public IEnumerable<ClaimDefinition> GetDefinitions() =>
    [
        new("orders.read",   "Orders",  "Read orders"),
        new("orders.create", "Orders",  "Create orders"),
        new("reports.view",  "Reports", "View reports"),
    ];
}

// Registration in Program.cs
services.AddScoped<IClaimDefinitionProvider, MyAppClaimProvider>();
services.AddCoreAuthPoliciesFromProviders();

// Now usable as authorization policies:
// [Authorize(Policy = "orders.read")]
// or in Minimal API: .RequireAuthorization("orders.read")
Default Policies
Policy Protects
identity.read Admin: list and view users, roles, claims
identity.update Admin: modify users, roles, claim assignments
identity.users.create Admin: create new user accounts
auth.profile.read User: read own profile and sessions
auth.profile.update User: update own profile, change password

Session Management

Core.Auth tracks active sessions per user with device fingerprinting. Each login creates a session entry. Sessions are limited per user (default 10) — when the limit is reached, the oldest session is evicted.

Field Type Description
TokenHash string SHA256 hash of the refresh token
DeviceName string Extracted device name (e.g. 'Chrome on Windows')
UserAgent string Raw User-Agent header
IpAddress string Client IP address
LocationHint string Approximate location from IP
CreatedAt DateTime Session creation timestamp
LastSeenAt DateTime Last token refresh timestamp
ExpiresAt DateTime Session expiration timestamp

Blazor Integration

The Components package provides a complete frontend auth stack for Blazor Server. It handles token storage, automatic refresh, and exposes the authentication state to Blazor's built-in authorization system.

Frontend Registration

AddCoreAuthComponents registers the auth state provider, token store, API client, and session client.

Show code
// Program.cs — Blazor frontend
services.AddCoreAuthComponents(options =>
{
    options.ApiBaseUrl = "https://api.example.com/api/v1";
});

builder.Services.AddCascadingAuthenticationState();
Service Responsibility
CoreAuthStateProvider Implements AuthenticationStateProvider — provides ClaimsPrincipal to AuthorizeView and cascading auth state
CoreTokenStore Persists access and refresh tokens in browser LocalStorage
CoreAuthApiClient Type-safe HTTP client for all auth endpoints with automatic token attachment
CoreAuthSessionClient Handles session validation and automatic token refresh on API calls

Authorization in Razor Components

Use Blazor's built-in AuthorizeView for conditional rendering based on auth state and policies.

Show code
<!-- Razor component  show/hide based on auth state -->
<AuthorizeView>
    <Authorized>
        <Typo>Welcome, @context.User.Identity?.Name</Typo>
        <Button Text="Logout" OnClick="Logout" />
    </Authorized>
    <NotAuthorized>
        <Button Text="Login" Href="/login" />
    </NotAuthorized>
</AuthorizeView>

<!-- Policy-based authorization -->
<AuthorizeView Policy="orders.read">
    <Authorized>
        <OrderList />
    </Authorized>
</AuthorizeView>

Admin API

The admin endpoints provide full CRUD for users, roles, and claims. All admin endpoints require authorization and are protected by configurable policies.

User Management
Method Path Description
GET /admin/identity/users List all users with pagination
GET /admin/identity/users/{id} Get user details including roles and claims
POST /admin/identity/users Create a new user account
PUT /admin/identity/users/{id} Update user details, assign roles
DELETE /admin/identity/users/{id} Delete or anonymize a user account
Role & Claim Management
Method Path Description
GET /admin/identity/roles List all roles with assigned claims
POST /admin/identity/roles Create a new role
DELETE /admin/identity/roles/{id} Delete a role
GET /admin/identity/claims List all available claim definitions
PUT /admin/identity/users/{id}/claims Assign or revoke claims for a user
An unhandled error has occurred. Reload Dismiss