AUTH_ENABLED=true.
Authentication is optional. Planning data is accessible without authentication. Auth enables user preferences sync across devices.
Authentication methods
OAuth providers
Sign in with Discord or GitHub
Passkeys
WebAuthn/FIDO2 passwordless authentication
BetterAuth endpoints
All authentication endpoints are handled by BetterAuth at/api/auth/*:
Session management
Get current user session.Response:
Sign out the current user.Invalidates the session and clears cookies.
OAuth sign-in
Initiate Discord OAuth flow.Redirects to Discord authorization page.
Initiate GitHub OAuth flow.Redirects to GitHub authorization page.
OAuth callback for Discord.Handles authorization code exchange and user creation.
OAuth callback for GitHub.Handles authorization code exchange and user creation.
Passkey authentication
Register a new passkey.Request body:Initiates WebAuthn registration ceremony.
Authenticate with passkey.Initiates WebAuthn authentication ceremony.
Custom auth routes
PlanningSup adds custom routes for Tauri/extension OAuth handling:Auto-redirect for OAuth callbacks in Tauri/extension.Path parameters:
provider- OAuth provider (e.g.,discord,github)
client- Client type (tauriorextension)- Standard OAuth parameters (
code,state, etc.)
- Tauri:
tauri://localhost/auth-callback/discord?... - Extension:
planningsup://auth-callback/discord?...
User preferences
Authenticated users can sync preferences across devices.Preference fields
These fields are stored in the user table and synced automatically:UI theme preference.Values:
dark, light, dracula, autoDefault: autoWhether to highlight events missing teacher info.Default:
falseWhether to show weekends in calendar view.Default:
trueWhether to merge duplicate events.Default:
falseArray of keywords to filter out from events.Example:
["exam", "test", "contrôle"]Array of planning full IDs user has selected.Example:
["enscr.elevesing1iereannee", "fac-de-sciences.l1info"]JSON string of custom planning groups.Structure:Example:
JSON string of custom color mappings.Structure:Example:
JSON string of preference update timestamps.Used for conflict resolution during sync.Structure:Example:
Preferences sync
The web app usesuseUserPrefsSync composable for bidirectional sync:
Sync logic
Merge with local state
For each preference:
- Compare
prefsMetatimestamps - If server value is newer, use it
- If local value is newer, push to server
Example: Update preference
Rate limiting
BetterAuth applies rate limits to prevent abuse:- General endpoints: 100 requests per 60 seconds
- Passkey endpoints: 5 requests per 10 seconds
429 Too Many Requests
The response may include a Retry-After header with seconds to wait.
OAuth configuration
To enable OAuth providers, configure environment variables:Discord
- Create an application at https://discord.com/developers/applications
- Add OAuth2 redirect URL:
https://your-domain.com/api/auth/callback/discord - Configure environment variables:
GitHub
- Create an OAuth app at https://github.com/settings/developers
- Set callback URL:
https://your-domain.com/api/auth/callback/github - Configure environment variables:
Passkey configuration
Passkeys (WebAuthn) require HTTPS in production:- Ensure
PUBLIC_ORIGINuses HTTPS - Configure
TRUSTED_ORIGINSto include all valid origins - Passkeys are registered per-domain (e.g.,
planningsup.app)
- Localhost is allowed for testing:
http://localhost:4444 - Passkeys registered on localhost won’t work on production domain
Security considerations
Session lifetime
Sessions are configured with:- Expires in: 30 days
- Update age: 7 days (session refreshed every 7 days of activity)
Example: Full authentication flow
Server exchanges code for tokens
BetterAuth:
- Exchanges authorization code for access token
- Fetches user profile from Discord
- Creates or updates user in database
- Creates session and sets cookie
Next steps
Environment variables
Configure authentication environment variables
Architecture
Learn about the authentication system design