Skip to content

Authentication

MINT supports two complementary authentication methods: a classic email + password flow that issues JWTs, and WebAuthn / passkey login that uses a hardware security key, Touch ID, Windows Hello, or any other passkey-capable authenticator.

[Screenshot: login page showing email-and-password form and "Sign in with passkey" button]

At a glance

MethodWhat you rememberServer storesCross-device
Password + JWTA passwordA salted password hash + your JWT secretYes
Passkey (WebAuthn)Nothing - your device authenticates youA public key onlyPer-device unless you sync via iCloud Keychain / Google Password Manager

Both methods can be enabled at the same time. Users sign in with a password first, register a passkey from their profile, and can then choose either method on the login page.

Sign in with email + password

Standard form on the login page. On success, MINT issues a bearer JWT with a 24-hour default expiry and also sets an HttpOnly mint_access_token cookie for server-side checks such as plugin frontend access. The frontend keeps the bearer token for API calls and can refresh it through /api/auth/refresh.

SettingDefaultWhere
Token TTL1,440 minutesauth.tokenExpireMinutes in config.json
JWT secretAuto-generated when omittedauth.jwtSecretKey (set a stable 32+ byte secret for production; never commit it)
Password hashingbcrypt, cost 12Implementation detail of auth_service

Rotate the JWT secret carefully

Rotating auth.jwtSecretKey invalidates every active session, signing every user out. Plan rotations during a maintenance window.

Sign in with a passkey

If passkeys are enabled (auth.enablePasskey: true), users can register one or more authenticators from the profile Passkey tab.

[Screenshot: profile Passkey tab listing registered credentials with device names and creation timestamps]

Each registered passkey carries:

  • A friendly name (e.g., "Work laptop", "YubiKey 5")
  • The credential ID
  • A public key
  • A creation timestamp

To log in with a passkey, click Sign in with passkey on the login page; your browser walks you through device unlock and the server verifies the signature. No password is involved.

Recovery and lockout

ScenarioResolution
Lost passkey, password still knownSign in with the password, then remove the old credential and register a new passkey from the profile Passkey tab.
Forgotten passwordAn admin with users.manage can set a new password from Admin → Users. There is no self-service email reset flow in the current core platform.
All authenticators lostAsk an admin to reset the password after the lab's normal out-of-band identity check, then register a fresh passkey.
Account compromisedAdmin disables or deletes the user from Admin → Users, then re-creates or re-enables access after a password reset and passkey review.

External identity providers

The current core configuration covers local password/JWT auth and WebAuthn passkeys. It does not include a built-in SSO/OIDC provider block or a local-login toggle in config.json. If a deployment needs organization SSO, put MINT behind a lab-managed reverse proxy or external access gateway and keep a break-glass MINT admin account available.

Rate limiting

Auth routes are rate-limited to 20 requests per 60 seconds per IP (api/middleware/rate_limit.py) for /api/auth and /api/passkey. X-Forwarded-For is trusted only when the request comes through a local proxy, so configure your reverse proxy to pass the original client IP to the backend.

Audit and observability

MINT can instrument FastAPI, SQLAlchemy, and logging with OpenTelemetry when tracing is configured. Authentication requests then appear as normal request spans and logs; MINT does not persist a separate auth audit log itself, so production deployments should ship backend logs to the lab's existing log store.

Next

Members & roles — what an authenticated user can do → Permissions — full RBAC reference

MINT is open source. Made by the Morscher Lab.