Skip to main content
Portal SSO lets your own portal or intranet sign learners into Juno without an identity provider. Your backend signs a short-lived token with a secret you generate in Juno’s admin, your page posts it to Juno, and the learner lands in Juno already signed in — full-tab or inside an iframe.
If your organization has a SAML 2.0 identity provider (Okta, Entra ID, Google Workspace…), use SSO & SAML instead. Portal SSO is for organizations without an IdP.

How it works

  1. A learner is signed into your portal
  2. Your backend signs a JSON Web Token (JWT) containing the learner’s email
  3. Your page auto-submits that token to Juno with a hidden form (POST)
  4. Juno verifies the token, creates or updates the learner, and redirects them into Juno — signed in
New Juno users are created as Learners, and any role claim in the token is ignored. An existing Juno user is signed in as themselves, with whatever role they already have.
Your signing secret is effectively a master credential: anyone who can sign a token can authenticate as any user in your organization — including an existing admin, at that account’s role. Keep the secret server-side only, and rotate it immediately if it’s ever exposed.

Setup

1

Ask Juno to turn on Portal SSO

Portal SSO is behind a feature flag. Ask your Juno customer success manager to enable it for your organization and to give you your tenant ID (the token aud). Once enabled, a Portal SSO section appears under Admin → SSO settings — that’s the only step that needs Juno.
2

Generate a signing secret (self-serve)

In the Portal SSO section, click Generate secret and copy the secret and its key id (kid) — the secret is shown only once, so store it in your backend’s secret manager (never in browser code). Then flip Enable Portal SSO on. You manage secrets yourself here — generate, rotate, and delete.
3

Sign tokens in your backend

Use a backend signing example below. Tokens must be signed server-side; the secret must never reach the browser.
4

Add the hand-off snippet to your portal

Use a frontend snippet below — React, plain JS, or server-rendered HTML; new tab or embedded iframe.

Token contract

Tokens are HS256-signed JWTs. Juno enforces every rule below and rejects the hand-off otherwise. Set the kid header to the key id you received. Any role claim is ignored — new users are created as Learners (an existing user keeps their current role; see the security note above). The attributes object is allowlisted to the five fields above; nothing else (roles, permissions, ids) is ever read from it.

Scaffold with an AI agent

In a hurry? Paste this into your coding assistant (Cursor, Claude, Copilot…) to scaffold the integration, then fill in the values from Admin → SSO settings → Portal SSO.
Prompt

Backend: sign the token

Sign server-side with the secret from Juno. Generate a fresh token for every hand-off — tokens are single-use and expire within minutes.

Frontend: hand off to Juno

Your frontend fetches the signed token from your backend, then POSTs it to https://api.the-juno.com/api/v1/sso/portal. Set the form’s target to _blank for a new tab, or to an <iframe name> to embed Juno in your page. The optional junoRedirectUrl deep-links the learner (a path like /unit/123, or an absolute URL on your Juno origin).
The token is minted by your backend (which holds the secret) — never sign in the browser. And never put the token in a URL or query string: Juno rejects it, and tokens in URLs leak through logs and history. Always POST it in the form body.

Error codes

Failed hand-offs redirect to the Juno app root with kind=error&code=…&message=…:

Secret rotation

Two secrets can be active at once, each with its own kid — so you rotate with zero downtime, all self-serve in the Portal SSO section:
  1. Click Generate secret to add a second secret (you’ll now have two active)
  2. Switch your backend to the new secret and kid
  3. Delete the old secret
Last modified on July 23, 2026