Skip to content

fix(website-ci): mint a real Keycloak token from the password before cloud builds#5249

Merged
liannacasper merged 1 commit into
masterfrom
fix-website-cloud-auth
Jun 16, 2026
Merged

fix(website-ci): mint a real Keycloak token from the password before cloud builds#5249
liannacasper merged 1 commit into
masterfrom
fix-website-cloud-auth

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Symptom

The "Build Hugo Website" workflow hangs the JS cloud builds at Waiting for login...CodeNameOneBuildTask tries to open a browser no CI runner can answer.

Root cause

CN1_TOKEN holds the account password, not a build token. scripts/website/build.sh fed it straight to cn1:set-user-token (and the SetCn1Prefs fallback), which writes it verbatim into the Java prefs token slot. The build then sends Authorization: Bearer <password> to the cloud server; the resource server tries to parse a password as a JWT, returns 401, and the client falls back to the interactive browser login. A password can never be a bearer token, so it fails every time (the old App Engine username/password fallback that used to mask this is gone).

Fix

In set_cn1_user_token, exchange the password for a short-lived Keycloak access token (OAuth2 direct access grant on the public cn1cloudapp client — Direct Access Grants is enabled) and seed that as the prefs token:

cn1_access_token="$(curl -fsS ... grant_type=password client_id=cn1cloudapp \
  username=$CN1_USER password=$CN1_TOKEN .../token | sed -n 's/..."access_token":"\([^"]*\)".*/\1/p')"

Minted per-build (this runs before each JS build), so it's fresh — no mid-build expiry for normal durations. No CodeNameOneBuildClient.jar change needed — the existing flow works once the prefs token is an actual token (alternative to the JAR-swap branch).

Triggers the build

Touches scripts/website/**, which is in the website-docs.yml pull_request path filter — so this PR runs the website build and exercises the fix end-to-end.

Note

If a cloud build ever exceeds the realm's access-token lifespan, bump Access Token Lifespan for the Realm realm in Keycloak. CN1_TOKEN secret stays as the password (no value change).

🤖 Generated with Claude Code

…cloud builds

The website docs JS cloud builds hang in CI at "Waiting for login...".
Root cause: CN1_TOKEN holds the account *password*, but build.sh fed it
to `cn1:set-user-token`, which writes it verbatim into the Java prefs
"token" slot. The build then sends it as `Authorization: Bearer <password>`
to the cloud server, which parses it as a JWT, 401s, and falls back to an
interactive browser login no CI runner can answer.

A password is not a bearer token. Exchange it for a short-lived Keycloak
access token via an OAuth2 direct access grant (public cn1cloudapp client,
which has Direct Access Grants enabled) and seed THAT instead. The token is
minted per-build (set_cn1_user_token runs before each JS build), so it is
fresh and won't expire mid-build for normal build durations.

No CodeNameOneBuildClient.jar change required — the existing build flow
works once the prefs "token" is an actual token.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@liannacasper liannacasper merged commit fd33c00 into master Jun 16, 2026
10 checks passed
@liannacasper liannacasper deleted the fix-website-cloud-auth branch June 16, 2026 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants