Skip to content

fix: authenticate as the ID token's client in the ZeroID exchange - #375

Open
saucam wants to merge 5 commits into
mainfrom
fix/zeroid-id-token-client-auth
Open

saucam wants to merge 5 commits into
mainfrom
fix/zeroid-id-token-client-auth

Conversation

@saucam

@saucam saucam commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

ZeroID v1.12+ only accepts an id_token exchange from an authenticated,
registered client, and requires the ID token to have been issued to
that client (aud/azp). codeoid sent its front-door client id "codeoid"
with no credentials, so Google sign-in fails against a current ZeroID.

The exchange now authenticates as oauth.zeroidClientId (default
GOOGLE_CLIENT_ID, override CODEOID_ZEROID_CLIENT_ID) with
CODEOID_ZEROID_CLIENT_SECRET (env only). The daemon warns at startup
when the secret is missing, and a 401 from ZeroID names the variable.

Deploy step (required before AuthN rolls out ZeroID v1.12.1)

  1. Register a confidential client at ZeroID:
    • client_id = the Google client id;
    • token_endpoint_auth_method = client_secret_post;
    • the Google issuer configured for that audience.
  2. Set CODEOID_ZEROID_CLIENT_SECRET on the codeoid deployment.

Against an older ZeroID, the extra credentials are harmless. oauth.clientId ("codeoid") is still codeoid's own front-door client id. Only the upstream exchange changes.

Tests

  • oauth-handler.test.ts:
    • the exchange sends the Google client id and the secret;
    • the secret is omitted when unset;
    • a 401 names the missing variable.
  • config.test.ts:
    • the client id defaults to and can override GOOGLE_CLIENT_ID;
    • the secret is read from env.
  • bun test passes (2978 pass, 0 fail), as do typecheck and biome check.

🤖 Generated with Claude Code

saucam and others added 5 commits October 11, 2026 14:51
ZeroID v1.12+ only accepts an id_token exchange from an authenticated,
registered client, and requires the ID token to have been issued to
that client (aud/azp). codeoid sent its front-door client id "codeoid"
with no credentials, so Google sign-in fails against a current ZeroID.

The exchange now authenticates as oauth.zeroidClientId (default
GOOGLE_CLIENT_ID, override CODEOID_ZEROID_CLIENT_ID) with
CODEOID_ZEROID_CLIENT_SECRET (env only). The daemon warns at startup
when the secret is missing, and a 401 from ZeroID names the variable.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.

1 participant