Skip to main content

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
}
emailAndPassword.enabled
boolean
default:true
Enable or disable email/password authentication.
emailAndPassword.minPasswordLength
number
default:8
Minimum required password length for user accounts.
emailAndPassword.autoSignIn
boolean
default:true
Automatically sign in users after successful registration.

OAuth Providers

KnowledgeCheckr supports GitHub and Google OAuth providers. Configure them using environment variables.

GitHub OAuth

AUTH_GITHUB_ID
string
required
GitHub OAuth application client ID.Obtain from: GitHub Developer Settings
AUTH_GITHUB_SECRET
string
required
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

AUTH_GOOGLE_ID
string
required
Google OAuth application client ID.Obtain from: Google Cloud Console
AUTH_GOOGLE_SECRET
string
required
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

DEX_PROVIDER_URL
string
required
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

BETTER_AUTH_URL
string
required
Trusted domain URL where users can authenticate.
BETTER_AUTH_URL=https://yourdomain.com
AUTH_SECRET
string
required
Base64-encoded secret for signing authentication tokens.Generate with:
openssl rand -base64 32
Reference: Env.ts:10
NEXT_PUBLIC_BASE_URL
string
required
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

Build docs developers (and LLMs) love