Single Sign-On

Every Inklura app — the console, SMS Designer, SEO, Mail, POS, support — shares one login. SSO works through two cooperating mechanisms:

  1. OIDC PKCE — each app authenticates users against the shared identity provider, and the IdP's own session makes subsequent logins silent.
  2. A console→app hand-off token — for silently launching an already-authenticated console user into a sibling app (used when embedding).

For the broader authentication picture (session cookies, Bearer JWTs, magic links) see Authentication.

Mechanism 1 — OIDC PKCE per app

The identity provider is auth.1clic.pro. Each *.inklura.fr app is its own public PKCE (S256) OIDC client — a public client with no client secret:

  • e.g. client id smsdesigner-prism, redirect https://smsdesigner.inklura.fr/auth/callback
  • or the shared-realm client inklura-admin, used by seo + pos

Scopes: openid profile email offline_access.

Host-scoped session cookies

After the OIDC round-trip, each app mints its own host-scoped session cookie:

Set-Cookie: <session>; Path=/; SameSite=Lax; Secure

Note there is no Domain= attribute — the cookie is scoped to that one host, not shared across subdomains.

Why login stays silent across subdomains

Users appear "logged in everywhere," but not because one cookie is shared. Each app has its own host-scoped cookie. What is shared is the IdP's own session at auth.1clic.pro: when a user who has already authenticated visits a second app, that app's PKCE round-trip completes silently at the IdP (no password re-entry), and the app mints its local cookie.

app B: no local cookie ──> redirect to auth.1clic.pro
       IdP already has a session ──> silent authorize ──> /auth/callback
       app B mints its OWN host-scoped cookie
Info

node:crypto caveat. PRISM's V8 isolate stubs node:crypto and crypto.subtle.digest, so SHA-256 / HMAC are hand-rolled in pure JS in each app's oidc.ts. By default the id_token is decoded, not signature-verified — the trust anchor is the TLS-protected token exchange with the IdP. Optional RS256-via-JWKS verification is available behind a flag.

Mechanism 2 — console→app hand-off token

To silently drop an already-authenticated console user into a sibling app (for example inside an iframe), the console mints a short-lived signed token and redirects the browser to the target app, which verifies it and mints its own local session.

Token format

b64url(JSON(payload)) + "." + b64url(hmacSha256(INKLURA_SSO_SECRET, b64payload))
  • The HMAC is computed over the b64url-encoded payload using INKLURA_SSO_SECRET.
  • TTL: 120 seconds.

Payload:

{ "sub": "…", "email": "…", "name": "…", "tenant_id": "…", "aud": "…", "iat": 0, "exp": 0 }

The aud claim is the target app's OIDC client id. Because the signature covers aud, the token is not replayable at a different app — a token minted for app A fails app B's audience check.

The mint route

GET /api/manage/designer-sso?app=<key>&next=<path>&embed=1
  • Gated by the console's own access check.
  • Carries only the caller's own identity (it can't impersonate another user).
  • Resolves the sibling app on the same registrable domain and 302-redirects there with the token.

The landing route (app side)

The target app exposes a landing route that consumes the token:

Landing route Apps
/auth/sso mail, sms, ads
/auth/manage-sso seo, pos, support

The landing route:

  1. Verifies the HMAC.
  2. Checks exp (not expired).
  3. Asserts aud === CLIENT_ID (this app is the intended audience).
  4. Mints the local session and redirects to next.
console (authenticated) ──GET /api/manage/designer-sso?app=mail&next=/inbox&embed=1
   mint token (aud = mail's client id, TTL 120s)
   302 ──> https://mail.inklura.fr/auth/sso?token=…&next=/inbox
      verify HMAC + exp + aud === CLIENT_ID
      mint local session ──> 302 /inbox

Same-site vs new-tab

When the console launches a sibling this way, same-site apps are embedded in an iframe; cross-site apps are launched in a new tab. The framing rules that make same-site embedding work are covered in Iframe Embedding.

See also