Summary: Authentication in the 7Mind system uses SuperTokens as the JWT issuer, validated in elixir-backend via JWKS, with Cloudflared providing a separate layer of protection for admin and internal access. Sources: direct code inspection (config/runtime/prod.ex, mix.exs — Joken 2.6 + Joken JWKS 1.7; lib/backend/user_identity/) Last updated: 2026-05-15


Auth layers

The backend uses two independent token validation paths:

1. SuperTokens JWT (mobile and web clients)

SuperTokens acts as the auth server and issues JWTs. The backend validates tokens using JWKS (JSON Web Key Sets) rather than a shared secret, meaning the backend never holds a signing key — it fetches the public key from SuperTokens and verifies signatures against it.

Relevant env vars:

  • SUPERTOKENS_JWT_ISSUER — expected iss claim in incoming tokens
  • SUPERTOKENS_JWKS_URL — endpoint the backend fetches public keys from

Library: Joken 2.6 for JWT parsing + Joken JWKS 1.7 for key fetching.

SSO flows (Apple, Google, Facebook sign-in) are handled within the user_identity domain and ultimately produce a SuperTokens session.

2. Cloudflared JWT (internal and admin access)

Admin panel and internal service traffic is protected by Cloudflare Access tunnels. The backend validates the Cloudflare-issued JWT using a separate JWKS endpoint.

Relevant env vars:

  • CLOUDFLARED_JWT_AUDIENCE — expected aud claim
  • CLOUDFLARED_JWKS_URL — Cloudflare’s public key endpoint

This is entirely separate from the SuperTokens path. Cloudflared handles identity at the network layer; SuperTokens handles identity for application users.

User identity domain

The user_identity domain in elixir-backend owns:

  • Session creation and validation
  • SSO integrations (Apple, Google, Facebook)
  • The Backend.Shared.AuthenticationToken behaviour, which allows pluggable auth strategies
  • Its own Ecto repos (BACKEND_USER_IDENTITY_IDENTITY_DATABASE_URL, BACKEND_USER_IDENTITY_APIV1_DATABASE_URL)

Two databases exist for this domain — one appears to be a legacy V1 API store and one the current identity store.

What agents should know

  • Do not implement custom token signing. All token issuance goes through SuperTokens.
  • The JWKS URLs are fetched at runtime, not compiled in. Rotating SuperTokens keys does not require a backend redeploy.
  • When adding a new protected endpoint, use the existing auth plugs from user_identity rather than rolling your own.

From api-contracts

The wire-level contracts capture three distinct auth schemes in contracts/shared/common.tsp, applied via @useAuth decorators:

TypeSpec modelHTTP shapeUsed on
Shared.Common.Requests.SuperTokensAuthbearer header st-access-tokenthe deprecated /auth/* routes that proxied directly to SuperTokens (signin, signup, signinup, password reset) and the deprecated Identity /me routes
Shared.Common.Requests.APIv1Authbearer header carrying the legacy v1 auth_tokena small set of legacy endpoints (/monetization/mondia/link_user, /chargebee/self_serve_portal/session)
Shared.Common.Requests.BackendSessionAuthcookie backend_sessionall of the new /user/* routes, plus /monetization, /content, /practice, /prevention — everything authenticated after the supertokens-auth migration

Every endpoint under Identity.SuperTokens.SuperTokensOperations and Identity.Identity.IdentityOperations is marked #deprecated "Use Backend.UserIdentity instead". The same is true for the DeprecatedEndpoints interface under SevenMind.User, which mirrors the new endpoints under the old /user_identity/* prefix. Clients should target the new /user/* routes with the cookie-based session.

From 7mind-mobile-apps-monorepo

The Flutter app does not link the SuperTokens SDK directly. supertokens-flutter is not in pubspec.yaml. Instead:

  • Users authenticate via SSO (google_sign_in 6.2.2, sign_in_with_apple 6.1.4, flutter_facebook_auth 7.1.2) or email
  • Resulting tokens are stored on-device using flutter_secure_storage 9.2.4
  • Requests to the backend attach the token through Dio interceptors in lib/features/core/network/interceptors/

The exact path by which SSO credentials are exchanged for a SuperTokens session is not yet traced from code inspection. The likely model: the mobile app sends the SSO ID token to the backend, which validates it with the SSO provider and then asks SuperTokens to mint a session. TBD: confirm from lib/features/authentication/ and the backend user_identity SSO modules.

From nuxt-website

The web client uses supertokens-web-js (v0.6) wired into @nuxtjs/auth for the 7mind theme. The flow is the cookie-based BackendSessionAuth variant described above, not bearer-token:

  • Login (POST /user/signin) returns a session cookie that the browser stores host-scoped. Configured redirect target is /login.
  • axios.withCredentials = true is set globally in plugins/axios-config.js so every backend call carries the cookie.
  • auth.resetOnError: false — API errors do not clear the auth state, because cookie expiry and invalidation is the backend’s job.
  • plugins/auth.js augments $auth.userInfo by JWT-decoding the local token when present and deriving isAppleGeneratedEmail from the email suffix.
  • The 7sleep theme has auth: false — no auth surface on the 7sleep website.
  • Identity service domain is configured via IDENTITY_SERVICE_DOMAIN (id.7mind.de prod, id.6mind.de staging).
  • For the cookie to flow correctly across 7mind.de / 6mind.de / 8mind.de / 9mind host families, see multi-domain-hostname-rewriting — the frontend rewrites backend hostnames at request time so the cookie domain matches.