Overview
KnowledgeCheckr uses better-auth for authentication with support for multiple providers. Authentication is configured in src/lib/auth/server.ts and supports email/password, OAuth providers (GitHub, Google), and anonymous access.
Authentication Methods
Email and Password
Built-in email/password authentication is enabled by default:
// Configuration in server.ts:57
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
autoSignIn: true
}
Enable or disable email/password authentication.
emailAndPassword.minPasswordLength
Minimum required password length for user accounts.
emailAndPassword.autoSignIn
Automatically sign in users after successful registration.
OAuth Providers
KnowledgeCheckr supports GitHub and Google OAuth providers. Configure them using environment variables.
GitHub OAuth
GitHub OAuth application client secret.Security: Keep this secret secure and never commit to version control.
# .env
AUTH_GITHUB_ID=your_github_client_id
AUTH_GITHUB_SECRET=your_github_client_secret
Configuration in server.ts:63:
socialProviders: {
github: {
clientId: env.AUTH_GITHUB_ID,
clientSecret: env.AUTH_GITHUB_SECRET
}
}
Google OAuth
Google OAuth application client secret.
# .env
AUTH_GOOGLE_ID=your_google_client_id.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=your_google_client_secret
Configuration in server.ts:64:
socialProviders: {
google: {
clientId: env.AUTH_GOOGLE_ID,
clientSecret: env.AUTH_GOOGLE_SECRET
}
}
Anonymous Authentication
Anonymous authentication allows users to interact with the platform without creating an account. Anonymous sessions can later be linked to a permanent account.
// Configuration in server.ts:68
anonymous({
onLinkAccount: async ({ anonymousUser, newUser }) => {
// Transfer knowledge checks and results to permanent account
// See server.ts:69-83 for implementation
}
})
When an anonymous user creates a permanent account:
- All knowledge checks are transferred to the new account
- All examination results are preserved
- The anonymous session is linked and replaced
Reference: server.ts:69
Dex (Custom OAuth Provider)
KnowledgeCheckr supports Dex as a custom OAuth provider for integration with existing identity systems (LDAP, SAML, etc.).
Environment Variables
Base URL for the Dex server.# .env
DEX_PROVIDER_URL=http://localhost:5556/dex
Reference: Env.ts:40
DEX_CLIENT_ID
string
default:"nextjs-client"
Client ID for the Dex OAuth application.DEX_CLIENT_ID=nextjs-client
DEX_CLIENT_SECRET
string
default:"dev-secret"
Client secret for the Dex OAuth application.DEX_CLIENT_SECRET=your_secure_secret
Dex Configuration
The Dex server configuration is in dex/dex.config.yaml:
# Dex configuration (dex.config.yaml:1)
issuer: http://localhost:5556/dex
storage:
type: memory
oauth2:
responseTypes: ["code"]
skipApprovalScreen: true
enablePasswordDB: true
staticClients:
- id: nextjs-client
name: "Next.js CI/Local"
secret: dev-secret
redirectURIs:
- http://localhost:3000/api/auth/oauth2/callback/dex
staticPasswords:
- email: [email protected]
username: e2e
userID: "1001"
hash: $2y$10$bogN.exei8vyACcf0QQFzutOahNcKjU1sqxGgdRtYi2Pn/UXNH8ce%
Generic OAuth Configuration
Dex is configured using the genericOAuth plugin in server.ts:85:
genericOAuth({
config: [
{
providerId: 'dex',
clientId: env.DEX_CLIENT_ID,
clientSecret: env.DEX_CLIENT_SECRET,
authentication: 'basic',
authorizationUrl: `${env.DEX_PROVIDER_URL}/auth`,
tokenUrl: `${env.DEX_PROVIDER_URL}/token`,
userInfoUrl: `${env.DEX_PROVIDER_URL}/userinfo`,
scopes: ['openid', 'email', 'profile'],
mapProfileToUser(profile) {
return {
id: profile.sub,
name: profile.name || profile.email?.split('@')[0],
email: profile.email,
image: profile.picture ?? null
}
}
}
]
})
Core Environment Variables
Trusted domain URL where users can authenticate.BETTER_AUTH_URL=https://yourdomain.com
Base64-encoded secret for signing authentication tokens.Generate with:Reference: Env.ts:10
Public base URL of your application.NEXT_PUBLIC_BASE_URL=https://yourdomain.com
Rate Limiting
Rate limiting is enabled by default in production and development:
// Configuration in server.ts:35
rateLimit: {
enabled: env.NEXT_PUBLIC_MODE === 'test' ? false : true
}
Rate limiting is disabled in test mode to prevent flaky tests.
Database Configuration
Authentication uses custom table names for better-auth models:
// Configuration in server.ts:38
user: {
modelName: 'User'
},
account: {
modelName: 'Account',
fields: {
userId: 'user_id'
}
},
session: {
modelName: 'Session',
fields: {
userId: 'user_id'
}
},
verification: {
modelName: 'Verification'
}
Complete Example
# .env - Complete authentication configuration
# Core authentication
BETTER_AUTH_URL=https://yourapp.com
AUTH_SECRET=your_base64_encoded_secret_here
NEXT_PUBLIC_BASE_URL=https://yourapp.com
# GitHub OAuth (optional)
AUTH_GITHUB_ID=your_github_client_id
AUTH_GITHUB_SECRET=your_github_client_secret
# Google OAuth (optional)
AUTH_GOOGLE_ID=your_google_client_id.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=your_google_client_secret
# Dex OAuth (optional)
DEX_PROVIDER_URL=http://localhost:5556/dex
DEX_CLIENT_ID=nextjs-client
DEX_CLIENT_SECRET=your_dex_secret
# Database
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_NAME=knowledgecheckr
DATABASE_USER=dbuser
DATABASE_PASSWORD=dbpassword
Provider Validation
The environment schema validates that OAuth providers have both required credentials:
// From Env.ts:89
// Both client ID and secret must be provided, or both must be empty
// Partial configuration will result in an error
// ✅ Valid - Both provided
AUTH_GITHUB_ID=abc123
AUTH_GITHUB_SECRET=secret123
// ✅ Valid - Both empty (provider disabled)
# AUTH_GITHUB_ID=
# AUTH_GITHUB_SECRET=
// ❌ Invalid - Only one provided
AUTH_GITHUB_ID=abc123
# AUTH_GITHUB_SECRET= (missing)
// Error: GitHub auth requires BOTH credentials
Getting Server Session
Retrieve the current user session in server components:
import { getServerSession } from '@/src/lib/auth/server'
export default async function ProtectedPage() {
const { user, session } = await getServerSession()
if (!user) {
redirect('/login')
}
return <div>Welcome, {user.name}!</div>
}
Reference: server.ts:111