Skip to main content

Authentication Configuration

Configure PearDrop authentication behavior through appsettings.json.

Complete Configuration Reference

{
"ConnectionStrings": {
"PearDrop-Auth": "Server=localhost,1433;Database=MyApp;User Id=sa;Password=...;TrustServerCertificate=True;"
},
"PearDrop": {
"modules": {
"authentication": {
// Session & Storage
"useSessionStore": false,

// Cookies
"authCookieName": "peardrop.auth",
"cookieExpiryLengthMinutes": 2880,
"appAddress": "https://myapp.example.com",

// MFA Token Settings
"emailMfaTokenGenerations": 3,
"smsMfaTokenGenerations": 3,
"userPrincipleNameTokenGenerations": 3,

// Help Message Thresholds
"authHelpMessageThreshold": 3,
"emailMfaHelpMessageThreshold": 3,
"smsMfaHelpMessageThreshold": 3,

// Account Changes
"emailChangeRevertWindowHours": 48,

// Features
"useInternal": true,
"useRegistration": false,
"useUPNAsContactEmail": true,

// Consumer API
"consumerApiId": "00000000-0000-0000-0000-000000000000",

// UI Customization
"additionalStyleSheets": [],
"additionalScripts": [],

// Providers
"providers": {
"internal": {
// Internal provider config
},
"external": {
"entra": {
// Entra ID providers
}
}
}
}
}
}
}

Session & Storage Configuration

useSessionStore

Type: boolean
Default: false

Enable session store for ticket management. Use when you need server-side session tracking.

"useSessionStore": true

What it does:

  • Stores authentication tickets on server
  • Enables server-side session invalidation
  • Allows admin logout of user sessions
  • Increases memory usage with many concurrent sessions

authCookieName

Type: string
Default: "peardrop.auth"

HTTP-only cookie name for storing authentication state.

"authCookieName": "myapp.auth"

Best practices:

  • Make it application-specific
  • Keep it short (less overhead in requests)
  • Avoid special characters

cookieExpiryLengthMinutes

Type: integer
Default: 2880 (48 hours)

How long until authentication cookie expires.

"cookieExpiryLengthMinutes": 1440  // 24 hours

Considerations:

  • Shorter = More secure but more frequent re-authentication
  • Longer = Better UX but more security risk if device compromised
  • Typical range: 240 minutes (4 hours) to 2880 minutes (48 hours)

appAddress

Type: string
Default: null

Your application's public URL. Used for:

  • External provider redirects
  • Password reset email links
  • Email verification links
  • MFA callback URLs
"appAddress": "https://myapp.example.com"

Must be:

  • Full URL with protocol (https)
  • Reachable from internet
  • Match redirect URIs configured in external providers

Multi-Factor Authentication Configuration

Email MFA

emailMfaTokenGenerations

Type: integer
Default: 3

Number of email codes that can be generated per MFA request.

"emailMfaTokenGenerations": 5

Scenario:

  1. User requests MFA code via email
  2. Generates code #1 (emailed)
  3. User requests again → Code #2 (new email)
  4. This repeats up to 5 times before reset

Use for:

  • Preventing user lockout if codes expire
  • Balancing security vs. UX

emailMfaHelpMessageThreshold

Type: integer
Default: 3

Show help message after this many failed MFA attempts.

"emailMfaHelpMessageThreshold": 2

Behavior:

  • Attempt 1 fails → "Try again"
  • Attempt 2 fails → "Try again"
  • Attempt 3 fails → Show help (check spam, resend code, etc.)

SMS MFA

smsMfaTokenGenerations

Type: integer
Default: 3

Number of SMS codes that can be generated per request.

smsMfaHelpMessageThreshold

Type: integer
Default: 3

Show help after this many failed SMS MFA attempts.

User Principal Name Tokens

userPrincipleNameTokenGenerations

Type: integer
Default: 3

Code generations for UPN/username verification.

Authentication Help

authHelpMessageThreshold

Type: integer
Default: 3

Show help message after this many failed sign-in attempts.

"authHelpMessageThreshold": 2

Behavior:

  • Failed attempt 1 → "Invalid credentials"
  • Failed attempt 2 → "Invalid credentials"
  • Failed attempt 3+ → "Forgot password?" link, account locked warning, etc.

Account Management

emailChangeRevertWindowHours

Type: integer
Default: 48

Time window to revert email address changes after confirmation.

"emailChangeRevertWindowHours": 72  // 3 days

Scenario:

  1. User changes email to new@example.com
  2. Confirmation email sent
  3. User clicks link
  4. For next 72 hours, user can revert to old@example.com
  5. After 72 hours, revert window closes

Feature Configuration

useInternal

Type: boolean
Default: false

Enable internal (password-based) authentication provider.

"useInternal": true

Run after enabling:

dotnet tool run peardrop auth toggle-internal --enable

useRegistration

Type: boolean
Default: false

Allow new users to self-register via signup page.

"useRegistration": true

When enabled:

  • Sign-up page available
  • Email verification required
  • Password rules enforced

useUPNAsContactEmail

Type: boolean
Default: true

Use User Principal Name (username) as contact email if no explicit email provided.

"useUPNAsContactEmail": true

Example:

  • UPN: john.doe@company.com
  • No contact email provided during user creation
  • System uses john.doe@company.com for MFA, password reset, etc.

Branding & Customization

additionalStyleSheets

Type: array<string>
Default: []

Additional CSS stylesheets to include on auth pages.

"additionalStyleSheets": [
"/css/custom-auth.css",
"https://cdn.example.com/branding/auth.css"
]

additionalScripts

Type: array<string>
Default: []

Additional JavaScript files to include on auth pages.

"additionalScripts": [
"/js/custom-analytics.js",
"https://cdn.example.com/tracking.js"
]

API Configuration

consumerApiId

Type: Guid
Default: Guid.Empty

API client identifier for authentication API calls.

"consumerApiId": "550e8400-e29b-41d4-a716-446655440000"

Used for:

  • Rate limiting authentication requests per client
  • Tracking API usage by consumer
  • Multi-tenant API key management

Generate a new GUID if not provided.

Internal Provider Configuration

Password Rules

Configure password complexity under providers.internal:

"providers": {
"internal": {
"password": {
"minimumLength": 8,
"requireUpperCase": true,
"requireLowerCase": true,
"requireNumbers": true,
"requireNonAlphanumeric": false,
"maxConsecutiveCharacters": 3
}
}
}

Account Policies

"providers": {
"internal": {
"accountLockout": {
"maxFailedAttempts": 5,
"lockoutDurationMinutes": 15
}
}
}

External Provider Configuration

Entra ID Provider

Set up via CLI or manually:

"providers": {
"external": {
"entra": {
"your-provider-id": {
"clientId": "application-id-from-azure",
"clientSecret": "secret-from-azure",
"tenantId": "azure-tenant-id",
"buttonText": "Sign in with Entra ID",
"iconUrl": "https://example.com/entra-icon.png",
"internalAuthUrl": "/auth/callback"
}
}
}
}

Configuration by Scenario

Single Sign-On (SSO)

{
"useInternal": false,
"providers": {
"external": {
"entra": {
"your-id": {
"clientId": "...",
"clientSecret": "...",
"tenantId": "..."
}
}
}
}
}

Development (Local Testing)

{
"useSessionStore": false,
"useInternal": true,
"useRegistration": true,
"cookieExpiryLengthMinutes": 10080,
"emailMfaTokenGenerations": 10
}

Production (High Security)

{
"useSessionStore": true,
"useInternal": false,
"cookieExpiryLengthMinutes": 240,
"emailMfaTokenGenerations": 3,
"authHelpMessageThreshold": 1
}

Multi-Tenant (Many Organizations)

{
"useSessionStore": true,
"useInternal": true,
"useRegistration": true,
"providers": {
"external": {
"entra": {
"tenant-1-id": { ... },
"tenant-2-id": { ... },
"tenant-3-id": { ... }
}
}
}
}

Configuration Best Practices

  1. Use environment variables for secrets:

    "clientSecret": "${Auth:ClientSecret}"
  2. Separate development/production configs:

    appsettings.json           // Defaults
    appsettings.Development.json
    appsettings.Production.json
  3. Test MFA settings with real users before deploying

  4. Monitor authentication metrics:

    • Token generation rates
    • Failed attempt patterns
    • MFA enrollment rates
  5. Regularly rotate secrets:

    • Azure app secrets (Entra ID)
    • Cookie encryption keys
    • Redis passwords

Troubleshooting Configuration

Users Getting Logged Out Unexpectedly

  • Increase cookieExpiryLengthMinutes
  • Enable useSessionStore to maintain sessions server-side

MFA Codes Expiring Too Quickly

  • Increase emailMfaTokenGenerations
  • Increase emailMfaHelpMessageThreshold

External Sign-in Not Working

  • Verify appAddress matches Azure redirect URI
  • Check clientId and clientSecret are correct
  • Confirm tenantId matches your Azure tenant

High Failed Login Attempts

  • Adjust authHelpMessageThreshold
  • Review accountLockout settings
  • Check password complexity rules aren't too strict

Next Steps