pgAdmin SSO fails
pgAdmin redirects through IAM but ends up at an error page
pgAdmin uses OIDC SSO via Olympus IAM. When the flow fails, the user sees pgAdmin's login screen with an error, or IAM Hera shows an error before the redirect completes.
Diagnostic
What does the URL look like at the error?
If you end up at iam.<domain>/login with an error in the query string:
error=invalid_request→ pgAdmin's redirect URI doesn't match what's registered in Hydra.error=access_denied→ user explicitly denied consent (rare).error=server_error→ Hydra had an internal error (check Hydra logs).
If you end up at pgadmin.<domain> with a pgAdmin error:
- "Authentication failed" → pgAdmin couldn't validate the ID token.
- "User not authorized" → the OIDC claims mapper isn't returning the expected role claim.
Check the pgAdmin client registration
ssh prod 'podman exec iam-hydra hydra get client pgadmin --endpoint http://localhost:7003'Verify:
redirect_urisincludeshttps://pgadmin.<domain>/oauth2/authorize.grant_typesincludesauthorization_code.response_typesincludescode.scopeincludesopenid profile email.
Check the OIDC mapper
podman exec iam-hydra cat /etc/config/hydra/pgadmin-claims-mapper.jsonnetThe mapper transforms Kratos identity claims into what pgAdmin expects:
local kratos = std.extVar('claims').identity.traits;
{
username: kratos.email,
dba_role: kratos.dba_role
}If kratos.dba_role is null (the user doesn't have that trait), pgAdmin gets an empty role and rejects the login.
Fix: ensure your IAM identity has a dba_role trait. Set it via Athena → Identity → Edit → traits → add dba_role: "olympus_readonly" (or olympus_app_admin).
Check pgAdmin's auth config
podman exec olympus-pgadmin cat /pgadmin4/config_local.pyYou should see:
AUTHENTICATION_SOURCES = ['oauth2']
OAUTH2_CONFIG = [{
'OAUTH2_NAME': 'olympus',
'OAUTH2_DISPLAY_NAME': 'Olympus IAM',
'OAUTH2_CLIENT_ID': '<pgadmin client id>',
'OAUTH2_CLIENT_SECRET': '<pgadmin client secret>',
'OAUTH2_TOKEN_URL': 'https://iam.example.com/oauth2/token',
'OAUTH2_AUTHORIZATION_URL': 'https://iam.example.com/oauth2/auth',
'OAUTH2_USERINFO_ENDPOINT': 'https://iam.example.com/userinfo',
'OAUTH2_SCOPE': 'openid email profile',
...
}]If the URLs point at the wrong host (e.g. CIAM Hydra instead of IAM), nothing will work. pgAdmin must point at IAM.
Check the Postgres role exists
If the OIDC flow completes but pgAdmin says "could not authenticate with database":
ssh prod 'podman exec olympus-postgres psql -U postgres -c "\du" | grep <expected-role>'If the role isn't there, create it:
ssh prod 'podman exec olympus-postgres psql -U postgres -c "
CREATE ROLE olympus_app_admin LOGIN PASSWORD '\''<random>'\'';
GRANT CONNECT ON DATABASE olympus TO olympus_app_admin;
GRANT USAGE ON SCHEMA public TO olympus_app_admin;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO olympus_app_admin;
"'See Security, pgAdmin DBA accounts for the canonical grants.
Quick recovery
If you're locked out of pgAdmin and need urgent DB access:
ssh prod 'podman exec olympus-postgres psql -U postgres'Direct shell access skips pgAdmin. Use sparingly, this bypasses the per-engineer audit trail.