Multica Docs

Sign-in and signup configuration

Configure email + verification code sign-in, Google OAuth, signup allowlists, and local test codes.

Multica supports two sign-in methods: email + verification code (default) and Google OAuth (optional). On successful sign-in, the server issues a JWT cookie with a 30-day lifetime. This page covers how to configure each method, how to restrict who can sign up, and the single biggest trap for self-hosted deployments.

For the list of environment variables referenced below, see Environment variables; for token usage and lifecycle details, see Authentication and tokens.

How email + verification code sign-in works

The user enters an email on the sign-in page → the server sends a 6-digit code → the user enters it → the server verifies it → a JWT cookie is issued. Standard flow. It requires Resend as the email provider:

  1. Create a Resend account and verify your domain

  2. Create an API key

  3. Set the environment variables:

    RESEND_API_KEY=re_xxxxxxxxxxxxxxxx
    RESEND_FROM_EMAIL=[email protected]  # must be a domain verified in Resend
  4. Restart the server

What happens if you don't set RESEND_API_KEY: the server doesn't error, but every email that should have been sent is written to the server's stdout only. Handy for local development (copy the code from the logs); in production it's a black hole.

Fixed local testing codes

Do not enable a fixed verification code on a publicly reachable instance.

The old behavior where non-production instances accepted 888888 by default has been removed. Unless you explicitly configure it, typing 888888 is treated like any other wrong code.

Local development without Resend should use the generated code printed in server logs. If you need deterministic local/private automation, set MULTICA_DEV_VERIFICATION_CODE to a 6-digit value such as 888888, and keep APP_ENV non-production:

APP_ENV=development
MULTICA_DEV_VERIFICATION_CODE=888888

This shortcut is ignored when APP_ENV=production.

Production deployments should leave MULTICA_DEV_VERIFICATION_CODE empty and set APP_ENV=production. If you deploy via make selfhost / docker-compose.selfhost.yml, APP_ENV defaults to production.

Google OAuth configuration

Optional. Without it, only email + verification code is available; with it, the sign-in page gets a "Sign in with Google" button.

  1. Create an OAuth 2.0 client in the Google Cloud Console

  2. Set the Authorized redirect URIs to your Multica frontend address plus /auth/callback, for example:

    https://multica.yourdomain.com/auth/callback
  3. Once you have the client ID and client secret, set three environment variables:

    GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxx
    GOOGLE_REDIRECT_URI=https://multica.yourdomain.com/auth/callback
  4. Restart the server.

Takes effect at runtime: the frontend reads these settings at runtime via /api/config — after changing them, restart the server and the frontend picks up the new values with no rebuild or redeploy.

The redirect URI must match exactly in both the Google Console and GOOGLE_REDIRECT_URI — including protocol (http vs https), trailing slash, and port. Any mismatch and Google rejects the entire OAuth flow; the error shown to the user is redirect_uri_mismatch.

Restricting who can sign up

Three environment variables combine by priority:

Rendering diagram…

Existing users can always sign in again — the signup allowlist only applies to first-time signup, not returning users.

  • ALLOWED_EMAILS (highest priority) — explicit email allowlist, comma-separated. When non-empty, only listed emails can sign up.
  • ALLOWED_EMAIL_DOMAINS — domain allowlist, comma-separated (for example company.io,partner.com).
  • ALLOW_SIGNUP — master switch, default true. Set false to disable signup entirely.

The three layers are AND semantics, not OR. A common wrong intuition is that ALLOWED_EMAIL_DOMAINS=company.io + ALLOW_SIGNUP=true means "allow company.io plus everyone else." It does not. If any layer has a non-empty value, emails not matching it are rejected outrightALLOW_SIGNUP=true does not override that.

To actually "allow everyone," leave all three variables empty (or keep ALLOW_SIGNUP=true).

Typical configurations:

GoalConfiguration
Internal only, employees of company.ioALLOWED_EMAIL_DOMAINS=company.io
Internal + a few external collaboratorsALLOWED_EMAIL_DOMAINS=company.io + collaborator addresses added to ALLOWED_EMAILS
Disable self-serve signup entirely, invite-onlyALLOW_SIGNUP=false
Open signup (not recommended for production)All three empty

Can you still invite people when signup is disabled?

Only people who already have a Multica account. Accepting an invite doesn't check the signup allowlist — if the invitee has signed up already (for example in another workspace), clicking the invite link and signing in lets them accept.

But people who have never signed up cannot be rescued by an invite. Before accepting, they must sign in, and the first step of sign-in (requesting the verification code) passes through the signup allowlist check. If ALLOW_SIGNUP=false, or their email isn't in ALLOWED_EMAILS / ALLOWED_EMAIL_DOMAINS, they cannot complete signup, and therefore cannot accept the invite.

To invite an external collaborator who hasn't signed up yet: temporarily add their email to ALLOWED_EMAILS, wait for them to sign up and accept the invite, then remove the entry.

For how to create and use invites, see Members and roles.

Next