Skip to main content

Troubleshooting IdP Logins

Goal

A user signs in through your external IdP successfully, but the application then behaves as though they have no access — the Policies tab is missing, creating an AI System fails, or the UI reports an authentication error even though the login itself worked.

None of the symptoms below indicate a misconfigured Identity Provider. If sign-in completes and the user reaches the application at all, the IdP integration is working. Each one is a distinct, later step in onboarding that a federated user does not receive automatically.

Most of this is avoidable

The first three sections exist because a required onboarding step was skipped, not because something broke. If you are setting up an IdP now, follow Activate Each IdP User on the Platform and Add the Email Claim and you should never reach this page. It is here for deployments already past that point, and to map symptoms back to causes that are not obvious from the error text.

Use this guide after completing Entra ID as IdP or Keycloak as IdP and Adding Mappers.

The Policies Tab Is Missing for an IdP User

The user signs in, sees Projects and AI Systems, and no Policies tab. Roles and group membership look correct in Keycloak.

The tab is gated on a single per-user flag, not on a role:

hasDynamoGuardAccess = config.MODERATION.dynamoGuardAccess === 'ACTIVATED'

That flag is set per user by the platform's user-setup routine, which also creates the demo policies. It runs for users created by the platform bootstrap, and when called explicitly — but there is no first-login hook, so a user who arrives through an IdP never has it run. Checking their Keycloak roles is a dead end: the roles are correct and irrelevant to this flag.

Confirm before changing anything — the flag is user-scoped, so query it as the affected user, not as an admin:

Read the access config as the affected user
curl -s -H "Authorization: Bearer $USER_TOKEN" \
https://api.<domain>/v1/config | jq '.response.MODERATION'

ACTIVATED means this is not your problem. Anything else means setup has not run.

Fix

Run the activation step from the setup guide: Activate Each IdP User on the Platform. Note the ordering constraint documented there — the user must load the application once before setup is run, or the POLICIES step fails (see the next section).

This is per user, not per deployment

Every user who arrives through the IdP needs this. Plan for it during onboarding rather than treating it as a one-off fix, and re-check after adding a new cohort.

Policy user:<email> not found When Creating an AI System

Creating an AI System (or another shared resource) fails with:

Policy user:someone@example.com not found

Creating a resource attaches a permission bound to a Keycloak authorization policy named after the creator. That policy is created lazily, from the email on an authenticated request. If it is absent, resource creation fails while everything else about the session works — which is why this looks like a permissions bug rather than a missing object.

List the policies that exist on the API client's resource server:

List per-user authorization policies
curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
"https://<keycloak-domain>/admin/realms/<realm>/clients/<api-client-uuid>/authz/resource-server/policy?max=100" \
| jq -r '.[] | select(.name | startswith("user:")) | .name'

Expect one user:<email> entry per active user. A federated user missing from that list is the failure.

Create the missing policy

Have the user load the application once and retry first — the lazy creation is driven by their request, so an admin acting on their behalf does not trigger it. If it still does not appear, create it explicitly:

Create the user policy
curl -s -X POST \
"https://<keycloak-domain>/admin/realms/<realm>/clients/<api-client-uuid>/authz/resource-server/policy/user" \
-H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"user:someone@example.com","users":["<keycloak-user-uuid>"]}'
This also blocks user setup

The POLICIES step of user setup fails with this same message when the policy is absent. Create the policy first, then re-run setup — otherwise setup reports a partial success that is easy to misread as complete.

The IdP Returns No Email Claim

A first-time IdP user is shown Keycloak's Review Profile page and asked to type their email, or a request fails because the platform cannot resolve the user.

The email is not cosmetic. The platform resolves the signed-in user by email on every request, and the lazy creation of the authorization policy above is keyed on it — so a token without an email produces failures that look unrelated to the IdP.

Two things to check, in order:

  1. Does the IdP actually send it? Microsoft Entra ID only emits an email claim when the user's mail attribute is populated. For many directories the address lives in the UPN instead. Add email (and upn) as optional ID-token claims on the application registration — the same Token configuration screen used to add the groups claim in Adding Mappers.

  2. Is it mapped onto the user? Add an Attribute Importer mapper on the Identity Provider so the claim lands on the account:

    AttributeValue
    Mapper TypeAttribute Importer
    Claimemail
    User Attribute Nameemail
    Sync Mode OverrideInherit

    Add a second one from preferred_username to email as a fallback for directories that only populate the UPN. Identity-provider mappers run before the profile-review step, so a populated email suppresses the prompt.

Where the prompt is actually controlled

The Review Profile page is governed by the first broker login flow's Review Profile execution, whose config is update.profile.on.first.login. The default missing prompts only when a required field is absent — which is the correct setting, and means a prompt is evidence that a claim is genuinely missing rather than something to switch off. The Identity Provider's own updateProfileFirstLoginMode field is legacy and is not honoured by current Keycloak versions; setting it has no effect.

Unable to authenticate user During Normal Use

The UI intermittently reports Unable to authenticate user, or an action such as saving a policy fails with Please try later, and retrying a minute later succeeds.

Check whether Keycloak restarted rather than looking for a permissions problem:

Keycloak and API pod age
kubectl -n <namespace> get pods -l app.kubernetes.io/name=keycloak
kubectl -n <namespace> get pods -l app.kubernetes.io/name=dynamoai-api

A Keycloak pod that is only a minute or two old, alongside API pods with recent restarts, is the signature. The API treats Keycloak as a hard startup dependency — it logs Keycloak is not available, then Failed to authenticate with Keycloak after multiple attempts, and exits. So a brief Keycloak outage becomes a longer API outage, and the user-visible error names authentication rather than the restart.

Confirm from the API's own logs
kubectl -n <namespace> logs deploy/dynamoai-api --previous | grep -i keycloak

On clusters with node autoscaling this is usually node consolidation evicting the pod:

kubectl -n <namespace> get events --sort-by=.lastTimestamp | grep -iE 'Evicted|Underutilized'
A PodDisruptionBudget may not protect a single-replica component

A PDB written as maxUnavailable: 1 against a one-replica workload permits disrupting 100% of it — it looks like protection and provides none. kubectl get pdb shows ALLOWED DISRUPTIONS 0 only while the pod is already down, which makes the gap easy to miss.

For a stateful singleton such as Keycloak or MinIO, either use minAvailable: 1, or exclude it from consolidation entirely. With Karpenter or AKS Node Auto Provisioning:

Exclude a singleton from node consolidation
podAnnotations:
karpenter.sh/do-not-disrupt: "true"

Apply the same treatment to any single-replica component whose loss breaks others — MinIO is the other common one, because guard model servers stream their weights from it and crashloop while it is gone.

Claim-Mapped Roles Missing After Entra ID Sign-In

The user signs in through Entra ID without error, is in the all-users group, but is missing org-level roles that their Entra security group membership should grant. Other users with fewer Entra groups receive the expected roles.

This is not a Keycloak permissions bug. Entra ID omits the groups claim from the ID token when the user belongs to too many groups (more than 200 for JWT tokens). Keycloak Advanced Claim to Role mappers read only what is in the token — they do not call Microsoft Graph via the _claim_sources overage endpoint.

Fix

Follow Entra ID Groups Claim Overage: switch the groups claim to Groups assigned to the application, assign only your DynamoAI authorization groups to the dynamoai-idp enterprise application, and have the user sign in again.