Skip to content

Authentication

GrydAuth provides a complete JWT-based authentication system with access and refresh tokens, password management, and secure session handling.

Token Types

Access Token

Short-lived token (default: 10 minutes, max 15) used for API authentication. Access tokens are snapshots of authorization, so they are deliberately short-lived; use refresh tokens for session continuity.

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InByb2Qta2V5In0...

Asymmetric signing (v5)

Tokens are signed with RS256 (or ES256) using a private key held only by GrydAuth. The alg header is RS256 and a kid header selects the signing key. Consumers validate with the public key published at /.well-known/jwks.json. See the v4 → v5 migration guide if you are upgrading from HS256.

Claims included:

  • sub - User ID
  • email - User email
  • name - Full name
  • roles - Assigned roles
  • permissions - Granted permissions
  • tenant_id - Tenant ID (if multi-tenant)
  • token_version - Token version for invalidation
  • scope - Token scope (tenant-selector-only for global tokens)
  • jti - JWT ID for token blacklisting

Refresh Token

Long-lived token (default: 7 days) used to obtain new access tokens without re-authentication.

Global vs Tenant Tokens

  • Global Token (2 minutes TTL): Restricted scope, used only for tenant selection when user has multiple tenants
  • Tenant Token (10 minutes TTL, max 15): Full access within a tenant context

Authentication Endpoints

Login

Authenticates a user and returns tokens.

http
POST /api/v1/auth/login
Content-Type: application/json
X-App-Id: my-app-id

{
  "email": "user@example.com",
  "password": "Password123!",
  "isPasswordEncrypted": false,
  "preferredTenantId": "550e8400-e29b-41d4-a716-446655440001"
}

Success Response (200):

json
{
  "isSuccess": true,
  "data": {
    "token": "eyJhbGciOiJSUzI1NiIs...",
    "expiresAt": "2026-01-29T13:00:00Z",
    "permissions": ["read:products", "update:products"],
    "isFirstLogin": false,
    "mustChangePassword": false,
    "daysUntilPasswordExpiration": null,
    "isGlobal": false,
    "requiresTenantSelection": false,
    "tokenType": "Tenant",
    "currentTenant": {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "name": "Acme Corp",
      "isDefault": true,
      "permissions": ["read:products"],
      "type": "company",
      "parentTenantId": "550e8400-e29b-41d4-a716-446655440010",
      "parentTenantName": "Acme Holding",
      "groupId": "550e8400-e29b-41d4-a716-446655440010",
      "groupName": "Acme Holding"
    },
    "smartAutoSwitched": true,
    "groupId": "550e8400-e29b-41d4-a716-446655440010",
    "groupName": "Acme Holding",
    "tenantType": "company"
  }
}

Multi-Tenant Login

When the user has access to multiple tenants and no preferredTenantId is specified:

  • isGlobal: true - Token is a Global Token (2min TTL)
  • requiresTenantSelection: true - User must select a tenant
  • availableTenants - List of tenants the user can access
  • currentTenant.type/groupId/groupName - Hierarchy context for grouped UI rendering
  • Use POST /api/v1/auth/switch-tenant to get a full Tenant Token

Error Responses:

StatusCodeDescription
401INVALID_CREDENTIALSEmail or password is incorrect
401ACCOUNT_LOCKEDAccount is locked due to failed attempts
401EMAIL_NOT_CONFIRMEDEmail confirmation required
401ACCOUNT_DISABLEDAccount has been disabled

Register

Creates a new user account.

http
POST /api/v1/auth/register
Content-Type: application/json

{
  "email": "newuser@example.com",
  "password": "SecurePass123!",
  "fullName": "Jane Doe",
  "phoneNumber": "+1234567890"
}

Success Response (201):

json
{
  "isSuccess": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440001",
    "email": "newuser@example.com",
    "fullName": "Jane Doe",
    "createdAt": "2026-01-29T12:00:00Z"
  }
}

Refresh Token

Exchanges a valid refresh token for new tokens.

http
POST /api/v1/auth/refresh
Content-Type: application/json

{
  "tenantId": "550e8400-e29b-41d4-a716-446655440001"
}

Success Response (200):

json
{
  "isSuccess": true,
  "data": {
    "token": "eyJhbGciOiJSUzI1NiIs...",
    "expiresAt": "2026-01-29T14:00:00Z",
    "permissions": ["read:products"],
    "isGlobal": false,
    "tokenType": "Tenant"
  }
}

Refresh Token Rotation

GrydAuth uses refresh token rotation by default. Each refresh request issues a new refresh token and invalidates the previous one. This enhances security by limiting the window for token theft.

Logout

Invalidates the current session and all user tokens globally.

http
POST /api/v1/auth/logout
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Simplified OAuth 2.0 Logout

GrydAuth follows OAuth 2.0 RFC 7009 best practices:

  • No request body required - All info extracted from Authorization header
  • Global logout - Invalidates ALL user sessions using timestamp-based blacklist
  • More secure - Doesn't expose refresh token in requests

For selective session management, consider implementing GET /api/v1/auth/sessions in your application.

Password Management

Change Password

http
POST /api/v1/auth/change-password
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/json

{
  "currentPassword": "OldPassword123!",
  "newPassword": "NewSecurePass456!"
}

Forgot Password

Initiates password reset flow.

http
POST /api/v1/auth/request-password-reset
Content-Type: application/json

{
  "email": "user@example.com"
}

This sends a password reset email with a token.

Reset Password

http
POST /api/v1/auth/reset-password
Content-Type: application/json

{
  "email": "user@example.com",
  "token": "reset-token-from-email",
  "newPassword": "NewSecurePass789!"
}

Password Policy Configuration

Password policy is configured via appsettings.json under the GrydAuth section:

json
{
  "GrydAuth": {
    "PasswordPolicy": {
      "MinLength": 8,
      "RequireUppercase": true,
      "RequireLowercase": true,
      "RequireDigit": true,
      "RequireSpecialChar": true,
      "SpecialCharacters": "!@#$%^&*()_+-=[]{}|;':\",./<>?",
      "MaxLength": 128,
      "EnablePasswordExpiration": true,
      "ExpirationDays": 90,
      "WarnBeforeExpirationDays": 7,
      "EnablePasswordHistory": false,
      "PasswordHistoryCount": 5
    }
  }
}

Account Lockout

Protect against brute-force attacks via appsettings.json under the GrydAuth section:

json
{
  "GrydAuth": {
    "Security": {
      "MaxFailedAccessAttempts": 5,
      "LockoutDurationMinutes": 15,
      "EnableSecurityLogging": true
    }
  }
}

Token Versioning

GrydAuth supports token versioning for immediate invalidation:

csharp
// Invalidate all tokens for a user
await authService.InvalidateAllTokensAsync(userId);

// This increments the user's token version, making all existing tokens invalid

Scenarios that trigger token invalidation:

  1. Password change
  2. Security settings change
  3. Role/permission update
  4. Manual logout from all devices
  5. Admin-triggered invalidation

Using Authentication in Code

Injecting Current User

csharp
using GrydAuth.Application.Common.Interfaces;

public class ProductService
{
    private readonly ICurrentUserService _currentUser;
    
    public ProductService(ICurrentUserService currentUser)
    {
        _currentUser = currentUser;
    }
    
    public async Task<Product> CreateAsync(CreateProductRequest request)
    {
        var product = new Product
        {
            Name = request.Name,
            CreatedBy = _currentUser.UserId, // Get current user ID
            TenantId = _currentUser.TenantId // Get current tenant
        };
        
        // ...
    }
}

ICurrentUserService Properties

PropertyTypeDescription
UserIdGuid?Current user's ID
Emailstring?Current user's email
FullNamestring?Current user's full name
TenantIdGuid?Current tenant ID
RolesIEnumerable<string>User's roles
PermissionsIEnumerable<string>User's permissions
IsAuthenticatedboolWhether user is authenticated

Custom Claims

Add custom claims to tokens:

csharp
public class CustomClaimsService : ICustomClaimsProvider
{
    private readonly IUserService _userService;
    
    public async Task<IEnumerable<Claim>> GetClaimsAsync(User user)
    {
        var department = await _userService.GetDepartmentAsync(user.Id);
        
        return new[]
        {
            new Claim("department", department.Name),
            new Claim("department_id", department.Id.ToString())
        };
    }
}

// Register in DI
builder.Services.AddScoped<ICustomClaimsProvider, CustomClaimsService>();

Two-Factor Authentication (2FA)

Coming Soon

Two-factor authentication support is planned for GrydAuth v1.1.0

External Authentication

Social Login

GrydAuth supports social login via POST /api/v1/auth/social-login:

http
POST /api/v1/auth/social-login
Content-Type: application/json
X-App-Id: my-app-id

{
  "provider": "google",
  "accessToken": "ya29.a0AfH6SM...",
  "preferredTenantId": "550e8400-e29b-41d4-a716-446655440001"
}

Supported providers depend on your Auth0 or custom OAuth configuration.

Auth0 Integration

Install the Auth0 package:

bash
dotnet add package GrydAuth.Infrastructure.Auth0

Configure in appsettings.json:

json
{
  "Auth0": {
    "Domain": "your-tenant.auth0.com",
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "Audience": "https://your-api.com"
  }
}

JWKS Endpoint

GrydAuth publishes its public signing keys so that any service can validate tokens without holding a secret:

http
GET /.well-known/jwks.json

The response is a standard JWK Set (kty, use, kid, alg, and key material). It exposes only public keys and returns two keys during rotation so tokens signed by the previous key keep validating. See Migrating from v4 to v5 for key generation, configuration and rotation details.

Security Best Practices

  1. Use HTTPS - Always use HTTPS in production
  2. Protect the private signing key - Store the JWT private key (JwtSettings:PrivateKeyPem) in a secure vault (Azure Key Vault, AWS Secrets Manager); never commit it. Consumers use the public JWKS only.
  3. Short Token Lifetime - Keep access tokens short-lived (1–15 minutes; default 10)
  4. Refresh Token Rotation - Enable refresh token rotation (default)
  5. Token Versioning - Enable token versioning for immediate invalidation
  6. Rate Limiting - Configure rate limiting for auth endpoints
  7. Audit Logging - Enable audit logging for authentication events

Released under the MIT License.