Authentication
MikroChat supports multiple authentication modes: a simple dev mode for local development, magic link authentication, password-based authentication, and OAuth 2.0 sign-in with external providers (Google, Microsoft, GitHub, GitLab, or custom).
Authentication Modes
Section titled “Authentication Modes”Dev Mode
Section titled “Dev Mode”Dev mode provides simple email-based authentication without sending actual emails. Enter an email address, and you’re signed in immediately.
When to use: Local development and testing only.
Configuration:
Backend (mikrochat.config.json):
{ "auth": { "authMode": "dev", "jwtSecret": "any-secret-key", "appUrl": "http://localhost:8000", "isInviteRequired": false }}Frontend (config.js):
window.MIKROCHAT_CONFIG = { AUTH_MODE: 'dev', // ...};Magic Link Authentication
Section titled “Magic Link Authentication”Magic link authentication sends a one-time login link to the user’s email. Clicking the link signs them in securely without a password.
When to use: Production deployments.
Configuration:
Backend (mikrochat.config.json):
{ "auth": { "jwtSecret": "your-strong-random-secret-key", "authMode": "magic-link", "appUrl": "https://chat.example.com", "isInviteRequired": true, "magicLinkExpirySeconds": 900, "jwtExpirySeconds": 900, "refreshTokenExpirySeconds": 604800, "maxActiveSessions": 3 }, "email": { "user": "noreply@example.com", "host": "smtp.example.com", "password": "smtp-password", "port": 465, "secure": true }}Frontend (config.js):
window.MIKROCHAT_CONFIG = { AUTH_MODE: 'magic-link', // ...};Password Authentication
Section titled “Password Authentication”Password authentication provides traditional email and password login. It works with or without an email provider — when email is not configured, admins manage user passwords directly.
When to use: Production deployments where you prefer traditional credentials over passwordless login.
Configuration:
Backend (mikrochat.config.json):
{ "auth": { "jwtSecret": "your-strong-random-secret-key", "appUrl": "https://chat.example.com", "authMode": "password", "isInviteRequired": false, "jwtExpirySeconds": 900, "refreshTokenExpirySeconds": 604800, "maxActiveSessions": 3 }, "chat": { "initialUser": { "userName": "admin", "email": "admin@example.com", "password": "change-me-on-first-login" } }}The initialUser.password field sets the admin’s password on first server start. Without it (or without email configured), the initial admin has no way to sign in. You can also set this via the INITIAL_USER_PASSWORD environment variable.
Email configuration is optional in password mode. Add it if you want email-based invite links and self-service password reset:
{ "email": { "user": "noreply@example.com", "host": "smtp.example.com", "password": "smtp-password", "port": 465, "secure": true }}Frontend (config.js):
window.MIKROCHAT_CONFIG = { AUTH_MODE: 'password', HAS_EMAIL: false, // Set to true if email is configured // ...};When HAS_EMAIL is false, the “Forgot password?” link is hidden and the admin add-user form shows a password field so the admin can set initial passwords directly.
OAuth 2.0 Authentication
Section titled “OAuth 2.0 Authentication”OAuth authentication lets users sign in with external identity providers like Google, Microsoft, GitHub, or GitLab. It can also be configured with any custom OAuth 2.0 compliant provider (e.g. Keycloak, Authentik).
OAuth works alongside other authentication modes — you can offer OAuth sign-in together with magic link or password authentication.
When to use: Production deployments where you want users to sign in with their existing accounts from a trusted identity provider.
Configuration:
Backend (mikrochat.config.json):
{ "auth": { "jwtSecret": "your-strong-random-secret-key", "authMode": "magic-link", "appUrl": "https://chat.example.com", "isInviteRequired": true }, "oauth": { "presets": { "google": { "clientId": "your-google-client-id", "clientSecret": "your-google-client-secret", "redirectUri": "https://chat.example.com/auth/oauth/google/callback" } } }}Frontend (config.js):
window.MIKROCHAT_CONFIG = { ENABLE_OAUTH: true, // ...};When ENABLE_OAUTH is true, the login screen fetches available providers from the backend and renders “Sign in with …” buttons. If no providers are configured on the backend, the buttons are simply not shown. See the Frontend Configuration guide for full details.
How OAuth Authentication Works
Section titled “How OAuth Authentication Works”- User clicks “Sign in with Google” (or another provider)
- Browser is redirected to
GET /auth/oauth/:providerId - Server generates a CSRF state token and redirects to the provider’s authorization page
- User authenticates with the provider and grants consent
- Provider redirects back to
/auth/oauth/:providerId/callbackwith an authorization code - Server validates the CSRF state, exchanges the code for provider tokens, and fetches the user’s profile
- Server looks up the user by email, issues a MikroChat JWT and refresh token
User Creation
Section titled “User Creation”OAuth respects the isInviteRequired setting:
isInviteRequired: true(default): The user must already exist in MikroChat (invited by an admin). If the OAuth email doesn’t match an existing user, sign-in is rejected with a 403 error.isInviteRequired: false: If the OAuth email doesn’t match an existing user, a new user is automatically created from the OAuth profile.
Supported Providers
Section titled “Supported Providers”MikroChat includes built-in presets for common providers. You only need to supply your client credentials:
| Provider | Preset ID | Scopes |
|---|---|---|
google | openid email profile | |
| Microsoft | microsoft | openid email profile User.Read |
| GitHub | github | user:email read:user |
| GitLab | gitlab | read_user email |
Custom Providers
Section titled “Custom Providers”For self-hosted or less common OAuth providers, use the custom array:
{ "oauth": { "custom": [ { "id": "keycloak", "name": "Keycloak", "authorizationUrl": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/auth", "tokenUrl": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token", "userInfoUrl": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/userinfo", "clientId": "your-client-id", "clientSecret": "your-client-secret", "redirectUri": "https://chat.example.com/auth/oauth/keycloak/callback", "scopes": "openid email profile" } ] }}Setting Up Provider Credentials
Section titled “Setting Up Provider Credentials”Google:
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Navigate to APIs & Services > Credentials
- Create an OAuth 2.0 Client ID (Web application)
- Add your redirect URI:
https://your-domain.com/auth/oauth/google/callback - Copy the Client ID and Client Secret into your config
Microsoft:
- Go to the Azure Portal > App registrations
- Register a new application
- Under Authentication, add a Web redirect URI:
https://your-domain.com/auth/oauth/microsoft/callback - Under Certificates & secrets, create a new client secret
- Copy the Application (client) ID and secret into your config
GitHub:
- Go to GitHub Settings > Developer settings > OAuth Apps
- Register a new OAuth application
- Set the Authorization callback URL:
https://your-domain.com/auth/oauth/github/callback - Copy the Client ID and Client Secret into your config
OAuth Security
Section titled “OAuth Security”- CSRF protection: Every OAuth flow generates a one-time state token tied to the user’s IP address. The token is validated on callback and consumed immediately.
- Rate limiting: OAuth endpoints are rate-limited per IP (default: 10 attempts per 15-minute window).
- Server-side token exchange: Authorization codes are exchanged for tokens server-to-server, never exposed to the browser.
How Password Authentication Works
Section titled “How Password Authentication Works”Invite Flow (isInviteRequired: true)
Section titled “Invite Flow (isInviteRequired: true)”With email configured:
- Admin adds a user through the settings panel (providing their email)
- Server creates the user and sends an invite email with a setup link
- User clicks the link and is taken to a “Set your password” screen
- User enters and confirms their password (minimum 8 characters)
- Server hashes the password, stores it, and creates a session
- User is signed in
Without email configured:
- Admin adds a user through the settings panel (providing their email and an initial password)
- Server creates the user and sets the password immediately
- Admin shares the credentials with the user out-of-band
- User signs in with the provided email and password
Self-Registration (isInviteRequired: false)
Section titled “Self-Registration (isInviteRequired: false)”When invites are not required, users can create their own accounts:
- User navigates to the login page and clicks “Create Account”
- User enters their email and a password
- Server creates the user, hashes the password, and creates a session
- User enters their email and password
- Server verifies the credentials and creates a session
- Server issues a JWT and refresh token
Password Reset
Section titled “Password Reset”With email configured:
Users who have forgotten their password can reset it from the sign-in screen:
- User clicks “Forgot password?” on the sign-in screen
- User enters their email and submits
- If the email matches an account with a password, a reset link is sent via email
- User clicks the link and is taken to a “Reset your password” screen
- User enters and confirms their new password (minimum 8 characters)
- Server hashes the new password, stores it, and creates a session
- User is signed in
Without email configured:
The “Forgot password?” link is hidden. Instead, an admin can reset any user’s password from the settings panel:
- Admin opens the settings panel and finds the user
- Admin clicks the reset password button and enters a new password
- Server updates the user’s password hash
- Admin shares the new credentials with the user
Security
Section titled “Security”- Passwords are hashed using
scryptwith a 16-byte random salt and 64-byte derived key - Password verification uses timing-safe comparison to prevent timing attacks
- Minimum password length: 8 characters
- Password hashes are never returned in API responses
How Magic Links Work
Section titled “How Magic Links Work”- User enters their email address
- Server generates a signed JWT token with a short expiry
- Server sends an email with a link containing the token
- User clicks the link, which redirects to the app with the token
- App verifies the token and creates a session
- Server issues a longer-lived JWT and refresh token
Token Lifecycle
Section titled “Token Lifecycle”MikroChat uses JWTs with refresh tokens for session management:
| Token Type | Default Expiry | Purpose |
|---|---|---|
| Magic link | 15 minutes | One-time login link |
| JWT | 15 minutes | API authentication |
| Refresh token | 7 days | Obtain new JWTs |
When the JWT expires, the frontend automatically uses the refresh token to get a new one. When the refresh token expires, the user must sign in again.
Session Limits
Section titled “Session Limits”By default, each user can have up to 3 active sessions. When a user signs in on a fourth device, the oldest session is invalidated.
Configure this with auth.maxActiveSessions:
{ "auth": { "maxActiveSessions": 5 }}Invite-Only Registration
Section titled “Invite-Only Registration”Control whether users can self-register or must be invited by an admin:
{ "auth": { "isInviteRequired": true }}When isInviteRequired is true:
- Only admins can add new users through the settings panel
- Users who haven’t been invited cannot sign in
- The initial user (configured in
chat.initialUser) is always allowed
When isInviteRequired is false:
- Anyone with a valid email can sign in
- New users are created automatically on first sign-in
The Initial User
Section titled “The Initial User”Every MikroChat server has an initial admin user created when the server first starts. This is configured in chat.initialUser:
{ "chat": { "initialUser": { "userName": "admin", "email": "admin@example.com", "password": "change-me-on-first-login" } }}The password field is optional but required for password auth mode without email. It sets the admin’s password on first server start only — if the user already has a password, it is not overwritten on subsequent starts. You can also set it via the INITIAL_USER_PASSWORD environment variable or the --initialUserPassword CLI flag.
The initial user:
- Is automatically created on first server start
- Has admin privileges
- Cannot be removed (as the last remaining admin)
- Is the only user who can sign in when
isInviteRequiredistrueand no other users exist
Email Configuration
Section titled “Email Configuration”Email configuration is required for magic-link authentication. For password mode, it is optional — without it, admins manage passwords directly through the settings panel (setting initial passwords when adding users and resetting passwords as needed). With email configured, users get invite links and can use self-service password reset. Dev mode and OAuth-only setups do not need email configuration.
{ "email": { "emailSubject": "Your MikroChat Login Link", "user": "noreply@example.com", "host": "smtp.example.com", "password": "your-smtp-password", "port": 465, "secure": true, "maxRetries": 2 }}Common SMTP Providers
Section titled “Common SMTP Providers”Proton Mail (with SMTP token):
{ "email": { "host": "smtp.protonmail.ch", "port": 465, "secure": true }}Gmail (with App Password):
{ "email": { "host": "smtp.gmail.com", "port": 465, "secure": true }}SendGrid:
{ "email": { "host": "smtp.sendgrid.net", "port": 465, "secure": true, "user": "apikey" }}Mailgun:
{ "email": { "host": "smtp.mailgun.org", "port": 465, "secure": true }}Custom Email Templates
Section titled “Custom Email Templates”Customize the magic link email content:
{ auth: { templates: { textVersion: (magicLink, expiryMinutes) => `Sign in to MikroChat by visiting: ${magicLink}\n\nThis link expires in ${expiryMinutes} minutes.`, htmlVersion: (magicLink, expiryMinutes) => `<h1>Sign in to MikroChat</h1> <p><a href="${magicLink}">Click here to sign in</a></p> <p>This link expires in ${expiryMinutes} minutes.</p>` } }}Security Best Practices
Section titled “Security Best Practices”- Use a strong JWT secret: Generate a random key with
openssl rand -base64 32 - Enable HTTPS: Always use HTTPS in production to protect tokens in transit
- Set appropriate expiry times: Balance security (shorter) with convenience (longer)
- Enable invite-only mode: Prevent unauthorized access in private deployments
- Use rate limiting: Prevent brute-force attacks on the login endpoint