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
Cookie Configuration
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:
- User requests MFA code via email
- Generates code #1 (emailed)
- User requests again → Code #2 (new email)
- 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:
- User changes email to new@example.com
- Confirmation email sent
- User clicks link
- For next 72 hours, user can revert to old@example.com
- 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.comfor 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
-
Use environment variables for secrets:
"clientSecret": "${Auth:ClientSecret}" -
Separate development/production configs:
appsettings.json // Defaults
appsettings.Development.json
appsettings.Production.json -
Test MFA settings with real users before deploying
-
Monitor authentication metrics:
- Token generation rates
- Failed attempt patterns
- MFA enrollment rates
-
Regularly rotate secrets:
- Azure app secrets (Entra ID)
- Cookie encryption keys
- Redis passwords
Troubleshooting Configuration
Users Getting Logged Out Unexpectedly
- Increase
cookieExpiryLengthMinutes - Enable
useSessionStoreto maintain sessions server-side
MFA Codes Expiring Too Quickly
- Increase
emailMfaTokenGenerations - Increase
emailMfaHelpMessageThreshold
External Sign-in Not Working
- Verify
appAddressmatches Azure redirect URI - Check
clientIdandclientSecretare correct - Confirm
tenantIdmatches your Azure tenant
High Failed Login Attempts
- Adjust
authHelpMessageThreshold - Review
accountLockoutsettings - Check password complexity rules aren't too strict
Next Steps
- MFA Setup - Configure email, SMS, and authenticator MFA
- User Management - Create and manage users
- External Authentication - Entra ID detailed setup