Background
When private-key-path is configured, SecurityConfig.loadRsaKey currently sets a random UUID as kid in the JWT assertion header when cert-path is not provided. This works for Entra ID (which matches on x5t, added in #149) but is broken for providers that match on kid — Keycloak, Okta, Auth0, Dex — because the kid changes on every server restart and no longer matches the kid registered with the provider's JWKS.
Proposed Fix
Add an optional key-id field to OidcAuthConfig. Precedence in loadRsaKey:
cert-path set → compute and set x5t (Entra ID)
key-id set → use as explicit kid
- Neither → random UUID
kid (backward compat only; suitable for providers that accept any kid)
auth:
oidc:
private-key-path: /run/secrets/gitproxy-oidc-key.pem
key-id: my-registered-kid # must match the kid in the JWKS registered with the provider
Affected Providers
- Keycloak — registers a JWKS with a fixed
kid; assertion kid must match
- Okta — same
- Auth0 — same
- Dex — same
- Entra ID — unaffected (uses
cert-path / x5t)
Background
When
private-key-pathis configured,SecurityConfig.loadRsaKeycurrently sets a random UUID askidin the JWT assertion header whencert-pathis not provided. This works for Entra ID (which matches onx5t, added in #149) but is broken for providers that match onkid— Keycloak, Okta, Auth0, Dex — because thekidchanges on every server restart and no longer matches thekidregistered with the provider's JWKS.Proposed Fix
Add an optional
key-idfield toOidcAuthConfig. Precedence inloadRsaKey:cert-pathset → compute and setx5t(Entra ID)key-idset → use as explicitkidkid(backward compat only; suitable for providers that accept anykid)Affected Providers
kid; assertionkidmust matchcert-path/x5t)