The Sim platform supports four authentication methods for user access:
All authentication methods are implemented using Better Auth as the core authentication framework. The system enforces email verification for new accounts and provides password reset functionality.
Authentication Flow Overview
Sources: apps/sim/app/(auth)/login/login-form.tsx1-638 apps/sim/app/(auth)/signup/signup-form.tsx1-632 apps/sim/app/(auth)/components/social-login-buttons.tsx1-120 apps/sim/app/(auth)/sso/sso-form.tsx1-276
Email and password authentication is the primary authentication method, supporting account creation, login, and password reset.
Signup Form Component
The signup form apps/sim/app/(auth)/signup/signup-form.tsx74-597 collects three required fields:
Field Validation Rules
| Field | Validation | Implementation |
|---|---|---|
| Name | Letters, spaces, hyphens, apostrophes only | NAME_VALIDATIONS apps/sim/app/(auth)/signup/signup-form.tsx40-57 |
| No consecutive spaces | /^(?!.*\s\s).*$/ | |
| 1-100 characters | Truncation check apps/sim/app/(auth)/signup/signup-form.tsx259-264 | |
| Valid email format | quickValidateEmail() apps/sim/app/(auth)/signup/signup-form.tsx59-73 | |
| Case-insensitive | Normalized to lowercase apps/sim/app/(auth)/signup/signup-form.tsx218 | |
| Password | Minimum 8 characters | PASSWORD_VALIDATIONS.minLength apps/sim/app/(auth)/signup/signup-form.tsx24 |
| At least one uppercase letter | /(?=.*?[A-Z])/ apps/sim/app/(auth)/signup/signup-form.tsx25-28 | |
| At least one lowercase letter | /(?=.*?[a-z])/ apps/sim/app/(auth)/signup/signup-form.tsx29-32 | |
| At least one number | /(?=.*?[0-9])/ apps/sim/app/(auth)/signup/signup-form.tsx33 | |
| At least one special character | /(?=.*?[#?!@$%^&*-])/ apps/sim/app/(auth)/signup/signup-form.tsx34-37 |
Signup Workflow
Error Handling
The signup form handles specific error codes from Better Auth apps/sim/app/(auth)/signup/signup-form.tsx275-313:
| Error Code | User Message | Action |
|---|---|---|
USER_ALREADY_EXISTS | "Account already exists. Please sign in instead." | Display error on email field |
INVALID_EMAIL | "Please enter a valid email address." | Display error on email field |
PASSWORD_TOO_SHORT | "Password must be at least 8 characters long." | Display error on password field |
PASSWORD_TOO_LONG | "Password must be less than 128 characters long." | Display error on password field |
| Network errors | "Network error. Please check your connection." | Display error on password field |
| Rate limit | "Too many requests. Please wait a moment." | Display error on password field |
Sources: apps/sim/app/(auth)/signup/signup-form.tsx1-597 apps/sim/lib/messaging/email/validation.ts1-50
Login Form Component
The login form apps/sim/app/(auth)/login/login-form.tsx92-628 accepts:
Login Workflow
Callback URL Security
The login system validates redirect URLs to prevent open redirect attacks apps/sim/app/(auth)/login/login-form.tsx58-74:
Password Visibility Toggle
Both login and signup forms include a password visibility toggle apps/sim/app/(auth)/login/login-form.tsx477-484:
Sources: apps/sim/app/(auth)/login/login-form.tsx1-629
Password Reset Initiation
Users can reset their password via:
Reset Request Flow
Reset Password Form
When users click the reset link in their email, they're directed to /reset-password?token=... apps/sim/app/(auth)/reset-password/page.tsx13-117
Password Reset Workflow
Password Requirements
The reset form enforces the same password rules as signup apps/sim/app/(auth)/reset-password/reset-password-form.tsx105-138:
| Requirement | Check | Error Message |
|---|---|---|
| Minimum length | password.length < 8 | "Password must be at least 8 characters long" |
| Maximum length | password.length > 100 | "Password must not exceed 100 characters" |
| Uppercase | !/[A-Z]/.test(password) | "Password must contain at least one uppercase letter" |
| Lowercase | !/[a-z]/.test(password) | "Password must contain at least one lowercase letter" |
| Number | !/[0-9]/.test(password) | "Password must contain at least one number" |
| Special character | !/[^A-Za-z0-9]/.test(password) | "Password must contain at least one special character" |
| Confirmation match | password !== confirmPassword | "Passwords do not match" |
Sources: apps/sim/app/(auth)/login/login-form.tsx303-625 apps/sim/app/(auth)/reset-password/page.tsx1-118 apps/sim/app/(auth)/reset-password/reset-password-form.tsx1-241 apps/sim/app/api/auth/reset-password/route.ts1-63
After signup, users must verify their email address before accessing the platform. The verification system uses one-time passwords (OTP) sent via email.
Verification Configuration
| Setting | Value | Source |
|---|---|---|
| OTP Length | 6 digits | Better Auth emailOTP plugin |
| OTP Validity | 15 minutes | expiresIn: 15 * 60 |
| Email Service | Configurable | Set via hasEmailService() |
| Required | Conditional | Controlled by isEmailVerificationEnabled flag |
Verification Components
The verification flow is implemented across three components:
Email Verification Workflow
OTP Input Component
The verification UI uses InputOTP component apps/sim/app/(auth)/verify/verify-content.tsx91-156 with:
isInvalidOtp)Resend Verification Code
Users can request a new OTP with rate limiting apps/sim/app/(auth)/verify/verify-content.tsx56-193:
The resend button shows:
Development Mode Behavior
When no email service is configured, the system provides different experiences:
| Environment | Behavior | Source |
|---|---|---|
| Production without email | Error message: "Email verification enabled but no email service configured" | apps/sim/app/(auth)/verify/verify-content.tsx79 |
| Development without email | Message: "Check console logs for verification code" | apps/sim/app/(auth)/verify/verify-content.tsx77-79 |
| Development with console logging | OTP printed to server console | Better Auth emailOTP plugin |
Verification Error Handling
The system handles three verification error scenarios apps/sim/app/(auth)/verify/use-verification.ts137-156:
| Error Type | Condition | Message | Action |
|---|---|---|---|
| Expired | Code older than 15 minutes | "The verification code has expired. Please request a new one." | Prompt to resend |
| Invalid | Wrong code entered | "Invalid verification code. Please check and try again." | Clear input, allow retry |
| Too Many Attempts | Multiple failed attempts | "Too many failed attempts. Please request a new code." | Force resend |
Auto-Verification on Complete
When the user enters the 6th digit, verification automatically triggers apps/sim/app/(auth)/verify/use-verification.ts191-199:
SessionStorage State Management
The verification system uses sessionStorage for temporary state apps/sim/app/(auth)/verify/use-verification.ts51-66:
| Key | Purpose | Cleared On |
|---|---|---|
verificationEmail | Email being verified | Successful verification |
inviteRedirectUrl | Post-verification redirect | Successful verification |
isInviteFlow | Invitation flow flag | Successful verification |
Sources: apps/sim/app/(auth)/verify/page.tsx1-18 apps/sim/app/(auth)/verify/verify-content.tsx1-242 apps/sim/app/(auth)/verify/use-verification.ts1-241
Social login enables users to authenticate using their existing GitHub or Google accounts via OAuth 2.0.
Supported Providers
| Provider | Icon | Scopes Requested | Configuration |
|---|---|---|---|
| GitHub | GitHub logo | user:email, repo | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET |
| Google logo | userinfo.email, userinfo.profile | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
Social Login Component
The SocialLoginButtons component apps/sim/app/(auth)/components/social-login-buttons.tsx17-119 renders OAuth buttons on both /login and /signup pages.
OAuth Authentication Flow
Provider Button Rendering
Each provider button apps/sim/app/(auth)/components/social-login-buttons.tsx82-104:
Provider Availability
Providers are only rendered if their credentials are configured apps/sim/app/(auth)/components/social-login-buttons.tsx17-23:
OAuth Error Handling
The component handles common OAuth error scenarios apps/sim/app/(auth)/components/social-login-buttons.tsx42-76:
| Error Type | Detection | User Message |
|---|---|---|
| Account exists | err.message?.includes('account exists') | "An account with this email already exists. Please sign in instead." |
| User cancelled | err.message?.includes('cancelled') | "Sign in was cancelled. Please try again." |
| Network error | err.message?.includes('network') | "Network error. Please check your connection and try again." |
| Rate limited | err.message?.includes('rate limit') | "Too many attempts. Please try again later." |
| Generic failure | Default case | "Failed to sign in with [Provider]" |
Hydration Prevention
The component prevents hydration errors using client-side mounting check apps/sim/app/(auth)/components/social-login-buttons.tsx26-34:
Button States
Each button has three visual states:
Integration Points
Social login buttons appear on:
The buttons are conditionally rendered based on:
Sources: apps/sim/app/(auth)/components/social-login-buttons.tsx1-120 apps/sim/app/(auth)/login/login-form.tsx519-536 apps/sim/app/(auth)/signup/signup-form.tsx517-538
Enterprise single sign-on (SSO) enables organizations to authenticate users via their identity provider using SAML or OIDC protocols.
SSO Configuration
| Setting | Environment Variable | Purpose |
|---|---|---|
| Enable SSO | NEXT_PUBLIC_SSO_ENABLED | Feature flag to enable/disable SSO |
| Trusted Providers | SSO_TRUSTED_PROVIDERS | List of trusted SSO provider patterns |
SSO Login Page
The dedicated SSO login page apps/sim/app/(auth)/sso/sso-form.tsx54-275 accepts work email addresses to initiate SSO authentication.
SSO Authentication Flow
SSO Form Component
The SSO form apps/sim/app/(auth)/sso/sso-form.tsx105-208 handles email validation and SSO initiation:
SSO Error Handling
The form handles various SSO error conditions apps/sim/app/(auth)/sso/sso-form.tsx133-152:
| Error Type | Message | User Action |
|---|---|---|
NO_PROVIDER_FOUND | "SSO provider not found. Please check your configuration." | Contact administrator |
INVALID_EMAIL_DOMAIN | "Email domain not configured for SSO. Please contact your administrator." | Use different email or contact admin |
SSO_DISABLED | "SSO authentication is disabled. Please use another sign-in method." | Use email/password or social login |
| Network error | "Network error. Please check your connection and try again." | Check connection and retry |
| Rate limit | "Too many requests. Please wait a moment before trying again." | Wait and retry |
SSO Button Integration
The SSOLoginButton component renders on login/signup pages when SSO is enabled:
Button Variants
| Variant | Use Case | Appearance |
|---|---|---|
primary | SSO is the only auth method | Full-width gradient button |
outline | SSO alongside other auth methods | Outlined button in button group |
Conditional Rendering
SSO buttons appear based on configuration apps/sim/app/(auth)/login/login-form.tsx377-383:
SSO-Only Mode
When SSO is the only authentication method apps/sim/app/(auth)/login/login-form.tsx397-404:
Multi-Method Mode
When SSO exists alongside other methods apps/sim/app/(auth)/login/login-form.tsx527-533:
Email Pre-fill from Deployed Chat
SSO forms support email pre-filling via URL parameter apps/sim/app/(auth)/sso/sso-form.tsx76-79:
This enables seamless SSO initiation from deployed chat interfaces.
Sources: apps/sim/app/(auth)/sso/sso-form.tsx1-276 apps/sim/app/(auth)/components/sso-login-button.tsx1-100 apps/sim/app/(auth)/login/login-form.tsx377-533 apps/sim/app/(auth)/signup/signup-form.tsx356-535
Sessions are configured with a multi-layered caching and expiry strategy apps/sim/lib/auth.ts73-81:
Session Lifecycle Timeline:
Configuration Breakdown:
| Setting | Duration | Purpose |
|---|---|---|
cookieCache.maxAge | 24 hours | How long session data is cached in the cookie |
freshAge | 1 hour | Period during which session is considered "fresh" |
updateAge | 24 hours | Minimum time between session expiry updates |
expiresIn | 30 days | Maximum session lifetime before re-authentication required |
Session Refresh Logic:
Sources: apps/sim/lib/auth.ts73-81
Sessions are stored in PostgreSQL using the Drizzle adapter apps/sim/lib/auth.ts69-72:
The adapter automatically manages the following tables from packages/db/schema:
user - User accountssession - Active sessionsaccount - Linked OAuth accountsverification - Email verification tokensSources: apps/sim/lib/auth.ts69-72 packages/db/schema
Better Auth provides lifecycle hooks for user and session creation. The Sim platform implements two key hooks.
When a new user account is created, the system initializes user statistics apps/sim/lib/auth.ts84-99:
Hook Flow:
Implementation:
The handleNewUser() function initializes billing and usage tracking for the new user. Errors in this process are logged but do not prevent user creation from succeeding.
Sources: apps/sim/lib/auth.ts84-99 apps/sim/lib/billing/core/usage.ts
When a new session is created, the system automatically sets the user's active organization apps/sim/lib/auth.ts101-138:
Organization Selection Logic:
Implementation Details:
The hook queries the member table to find the first organization the user belongs to:
This ensures users are immediately placed in a workspace context when they authenticate. If the user belongs to multiple organizations, the first one found becomes the active organization (users can switch later).
Sources: apps/sim/lib/auth.ts101-138 packages/db/schema
Better Auth supports linking multiple authentication methods to a single user account through its account linking feature apps/sim/lib/auth.ts140-164
Account Linking Configuration:
Trusted Providers:
| Provider Category | Providers | Purpose |
|---|---|---|
| Authentication | google, github, email-password | Primary sign-in methods |
| OAuth Services | confluence, x, notion, microsoft, slack, etc. | Tool integrations that can also authenticate |
| SSO Patterns | SSO_TRUSTED_PROVIDERS | Enterprise SSO configurations |
Account Linking Behavior:
allowDifferentEmails: true)trustedProviders list can be automatically linkedExample Flow:
[email protected] via email/password[email protected]Sources: apps/sim/lib/auth.ts140-164 apps/sim/lib/sso/consts.ts
The password reset system consists of two flows: requesting a reset and setting a new password.
Password Reset Components:
Password Reset Flow:
Password Validation Rules:
The new password form enforces the same validation as signup apps/sim/app/(auth)/reset-password/reset-password-form.tsx174-207:
| Check | Requirement | Validation |
|---|---|---|
| Minimum length | 8 characters | password.length < 8 |
| Maximum length | 100 characters | password.length > 100 |
| Uppercase | At least one | /[A-Z]/.test(password) |
| Lowercase | At least one | /[a-z]/.test(password) |
| Number | At least one | /[0-9]/.test(password) |
| Special character | At least one | /[^A-Za-z0-9]/.test(password) |
| Confirmation match | Must match | password !== confirmPassword |
Password Visibility Toggle:
Both password fields include eye icon toggles apps/sim/app/(auth)/reset-password/reset-password-form.tsx238-277:
Sources: apps/sim/app/(auth)/login/login-form.tsx299-634 apps/sim/app/(auth)/reset-password/reset-password-form.tsx1-320 apps/sim/app/(auth)/reset-password/page.tsx1-118
The system implements authentication middleware using createAuthMiddleware to enforce registration and access policies apps/sim/lib/auth.ts205-241
Middleware Flow:
Middleware Checks:
Checks DISABLE_REGISTRATION environment variable apps/sim/lib/auth.ts207-208:
Validates email addresses against allowlists apps/sim/lib/auth.ts210-237:
Environment Variables:
ALLOWED_LOGIN_EMAILS: Comma-separated list of allowed email addressesALLOWED_LOGIN_DOMAINS: Comma-separated list of allowed email domainsValidation Logic:
Use Cases:
| Configuration | Use Case |
|---|---|
DISABLE_REGISTRATION=true | Closed beta, invitation-only access |
ALLOWED_LOGIN_EMAILS | Specific user allowlist |
ALLOWED_LOGIN_DOMAINS | Corporate domain restriction (e.g., only @company.com) |
Sources: apps/sim/lib/auth.ts205-241
Better Auth is extended through seven plugins that add critical functionality:
Plugin Overview:
nextCookies apps/sim/lib/auth.ts244
oneTimeToken apps/sim/lib/auth.ts245-247
customSession apps/sim/lib/auth.ts248-251
emailOTP apps/sim/lib/auth.ts252-314
genericOAuth apps/sim/lib/auth.ts315-1679
organization apps/sim/lib/auth.ts14
stripe apps/sim/lib/auth.ts2
STRIPE_SECRET_KEY is provided apps/sim/lib/auth.ts54-61Sources: apps/sim/lib/auth.ts1-314
The Stripe client and plugin are conditionally initialized based on environment configuration apps/sim/lib/auth.ts52-61:
This conditional loading enables:
The Stripe plugin handles billing webhooks including subscription lifecycle events. See the billing documentation for webhook handler details.
Sources: apps/sim/lib/auth.ts52-61 apps/sim/lib/billing/webhooks
The authentication system exports a configured auth instance apps/sim/lib/auth.ts63 that is used throughout the application:
Server-Side Usage:
auth to validate sessionsClient-Side Usage:
client from @/lib/auth-clientclient.oauth2.link()Example OAuth Flow:
This demonstrates how the authentication client is used to initiate OAuth flows from the UI when users need to connect external services.
Sources: apps/sim/lib/auth.ts63 apps/sim/lib/auth-client.ts apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/components/oauth-required-modal.tsx:276-298
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.