ZITADEL keeps one client secret per app. _generate_client_secret ran on every apply and invalidated the deployed copies. Generate only on create; re-encrypt grafana's secret.
ZITADEL keeps one client secret per app. _generate_client_secret ran on every apply and invalidated the deployed copies. Generate only on create; re-encrypt grafana's secret.
Grafana sign-in failed with "Failed to get token from provider". The deployed
client secret no longer matched, because _ensure_oidc_apps called
_generate_client_secret for every app on every run, and ZITADEL stores exactly one
client secret per app: each call replaced the previous value and invalidated every
deployed copy.
Two changes:
1. Generate a secret only when the app is created. For an app that already exists,
reuse the value from state.json, because the API cannot read a secret back.
2. Re-encrypt grafana-oidc-secrets.enc.yaml with the live secret, so Grafana's
token exchange succeeds again.
Verified with the introspection endpoint:
old deployed secret -> {"error":"unauthorized_client"}
new secret -> {"active":false} (credentials accepted)
rock
merged commit ac73035c9e into main2026-10-27 19:46:57 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
ZITADEL keeps one client secret per app. _generate_client_secret ran on every apply and invalidated the deployed copies. Generate only on create; re-encrypt grafana's secret.
Grafana sign-in failed with "Failed to get token from provider". The deployed client secret no longer matched, because _ensure_oidc_apps called _generate_client_secret for every app on every run, and ZITADEL stores exactly one client secret per app: each call replaced the previous value and invalidated every deployed copy. Two changes: 1. Generate a secret only when the app is created. For an app that already exists, reuse the value from state.json, because the API cannot read a secret back. 2. Re-encrypt grafana-oidc-secrets.enc.yaml with the live secret, so Grafana's token exchange succeeds again. Verified with the introspection endpoint: old deployed secret -> {"error":"unauthorized_client"} new secret -> {"active":false} (credentials accepted)