Olympus Docs
TroubleshootingInfrastructure issues

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_uris includes https://pgadmin.<domain>/oauth2/authorize.
  • grant_types includes authorization_code.
  • response_types includes code.
  • scope includes openid profile email.

Check the OIDC mapper

podman exec iam-hydra cat /etc/config/hydra/pgadmin-claims-mapper.jsonnet

The 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.py

You 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.

On this page