Repository navigation
EN Clever Keycloak
Français · Type: how-to · Audience: admin · Context: hosted Studio · Status: ready · Applies from: 4.2.3
The Studio Server (hosted team Studio) · contract: experimental · verified by CI (support matrix of 4.4.0, 2026-10-23): Postgres, S3 and Keycloak in CI; Chromium and Firefox (job studio-hosted); WebKit on macOS, by hand only · automated checks: jobs
studio-hosted,studio-install-smoke; CI planstudioHosted; 3 test files · people's passes:studio-hostednot run (#149),studio-collabnot run (#150),studio-previewnot run (#166),studio-assets-hostednot run (#167),studio-mcp-remotenot run (#196),studio-oidc-genericnot run (#197) · known limits: none listed on this page
The Studio Server logs people in through an OpenID Connect provider. This page sets up Clever Cloud's managed Keycloak for it, from the test realm the repository carries. The provider says who someone is; what they may do is decided in the Studio.
A realm web-scumm on a managed Keycloak, with the two clients the Studio needs (studio for the browser,
web-scumm-cli for the CLI and the MCP), an audience mapper, 5-minute access tokens, and your own users with a
verified email. Its issuer, https://<keycloak host>/realms/web-scumm, goes in the configuration.
- A hosted Studio on Clever Cloud, from 4.2.3.
-
Verified on: 19 October 2026, by the reference deployment (Keycloak managed, plan BASE, Keycloak 26.7.4,
engine at commit 52e68932, package.json 4.2.2 before the 4.2.3 tag): the realm was created from the edited
realm.jsonwithPOST /admin/realms(201), and the maintainer's test user logged in as owner. The console path (step 4, first way) and this page's exact text are not verified on a live installation.
-
Domains and TLS: you know
publicUrl(https://studio.example.fr). -
clever-toolslogged in, andopensslon your machine. - The engine repository, for
ops/studio/keycloak/realm.json.
On your machine: clever … in the engine repository; the realm file in a folder kept out of Git
(~/secrets/my-game/). The realm itself is made in Keycloak's admin console, in a browser.
-
Create a managed Keycloak add-on in the same organisation (Clever's console, or
clever addon createwith the Keycloak provider;clever addon providersgives its name). Then read its admin console's address and first credentials:# on your machine, in the engine repository clever keycloak get <keycloak-addon-id>
- Log in to the admin console once. That first password is temporary: Keycloak asks for a new one. Clever's console
and the add-on's variable
CC_KEYCLOAK_ADMIN_DEFAULT_PASSWORDkeep showing the old one afterwards, so keep the new one where you keep secrets: without it you lose the provider's administration (Recovering admin access).
-
Copy
ops/studio/keycloak/realm.jsonout of the repository and change, in the copy:-
clients[studio].redirectUristo["<publicUrl>/auth/callback"]; -
clients[studio].attributes:backchannel.logout.urlto<publicUrl>/auth/backchannel, andpost.logout.redirect.uristo<publicUrl>; -
clients[studio].secretto a new random value, the one you will set asSTUDIO_OIDC_CLIENT_SECRET; -
users: your own, or none (Keycloak's console adds them), each with a verified email and a password that is not the file's. The file'slea@example.org/lea-local-onlyis for a local test only.
# on your machine mkdir -p ~/secrets/my-game && cp ops/studio/keycloak/realm.json ~/secrets/my-game/realm.json chmod 600 ~/secrets/my-game/realm.json openssl rand -base64 32 > ~/secrets/my-game/oidc-client-secret && chmod 600 ~/secrets/my-game/oidc-client-secret
Keep the edited file, with its secret and passwords, out of Git.
-
- Create the realm from the edited file. The admin API does not take the admin password through the master realm's
admin-cli(401 invalid_client), sokcadm.shand scripts built on it fail as they are. Two ways work:- in the admin console (
clever keycloak open webui <keycloak-addon-id>), Create realm, and give it the editedrealm.json; - or, with an admin token from a login through the console's own client (
security-admin-console, Authorization Code with PKCE),POST /admin/realmswith the edited file: what the reference deployment did.
- in the admin console (
- For members who log in from the CLI or the MCP: the
web-scumm-cliclient needs the client scopeoffline_access(optional or default), and each such member the realm roleoffline_access. Without them the login saysthe login was refused: not_allowed (Offline tokens not allowed for the user or client).
-
Give the studio app the client's secret from its file, so the value is never typed or shown:
# on your machine, in the engine repository clever env set --alias my-game-studio -- STUDIO_OIDC_CLIENT_SECRET "$(cat ~/secrets/my-game/oidc-client-secret)"
-
Put the provider in the configuration's
oidc(Configuration):{ "issuer": "https://keycloak.example.fr/realms/web-scumm", "clientId": "studio", "audience": "studio-api", "cliClientId": "web-scumm-cli" }
-
The
studioclient: confidential, Authorization Code with PKCE S256, redirect URI<publicUrl>/auth/callback, post-logout redirect<publicUrl>, back-channel logout to<publicUrl>/auth/backchannelwith the session id. -
The
web-scumm-cliclient: public, the device authorization grant, and the client scopeoffline_access. -
An audience mapper adding
studio-api(the configuration'soidc.audience) to the access tokens ofweb-scumm-cli. It must differ from thestudioclient's id: an id_token is never accepted as an access token. -
Access tokens of 5 minutes. Up to 15 if the configuration says so (
oidc.maxTokenSeconds, 900 at most): a longer token is refused.
The test realm sets all of this (accessTokenLifespan: 300, PKCE S256, back-channel logout with the session
required, the studio-api audience mapper).
-
https://<keycloak host>/realms/web-scumm/.well-known/openid-configurationanswers, withbackchannel_logout_supported: trueand adevice_authorization_endpoint(both measured on the managed Keycloak by spike S §8). - Once the Studio is deployed, it starts: it reads the issuer's discovery at start, and does not start while the
realm is missing. An invited member logs in and
GET /auth/megives their role. - From the CLI,
npm run studio-server -- login --server https://studio.example.frends withlogged in.
| Symptom | Cause | Fix |
|---|---|---|
401 invalid_client from the admin API |
The admin password through admin-cli
|
Create the realm in the console, or with a security-admin-console token (step 4) |
the login was refused: not_allowed (Offline tokens not allowed for the user or client) |
No offline_access scope on web-scumm-cli, or no role for the user |
Step 5 |
| The Studio does not start, the logs name the issuer | The realm is missing, or oidc.issuer is wrong |
Create the realm; check the issuer's discovery URL |
oidc.audience must differ from oidc.clientId |
The audience set to studio
|
Use studio-api
|
| A login loops back or the provider refuses the redirect |
redirectUris still the test realm's http://localhost:8080/...
|
Step 3 |
- The realm in Keycloak (clients, users, roles).
-
~/secrets/my-game/realm.jsonandoidc-client-secreton your machine (mode 0600, out of Git). -
STUDIO_OIDC_CLIENT_SECRETon the studio app.
Delete the realm in the admin console and create it again. Users of the deleted realm get new identities in the new
one (a new sub): the Studio sees new users, who need new invitations
(Changing domain or OIDC provider).
- The test realm:
ops/studio/keycloak/realm.json; the provider's checks:studio-server/src/server/auth/oidc.ts. -
ADR 0027;
STUDIO_OIDC_CLIENT_SECRET. - Another provider: Generic OIDC and GitLab.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits