v0.4.0

Auth0

Configure Podium to authenticate against Auth0 via OIDC device-code flow.

This guide configures a Podium registry to authenticate against Auth0. Setup takes about 15 minutes. Group claims are not native to Auth0; an Action adds them, or a legacy Rule does.

Prerequisites

  • Auth0 tenant with admin access.
  • Podium registry running and reachable from developers' browsers.
  • Decide your audience identifier (suggestion: https://podium.acme.com; Auth0 conventionally uses URL-shaped audiences).

1. Create the API in Auth0

Auth0 dashboard: Applications → APIs → Create API.

  • Name: Podium.
  • Identifier: https://podium.acme.com (this is the audience).
  • Signing Algorithm: RS256.

Save. The API is now what tokens are issued for.

2. Create the application

Dashboard: Applications → Applications → Create Application.

  • Name: Podium CLI.
  • Type: Native (best fit for the device-code flow).

In the new application's settings:

  • Token Endpoint Authentication Method: None (public client).
  • Grant Types: enable Device Code and Refresh Token.
  • Save.

Note from the app's settings tab: Client ID.

Connect the application to the API:

  • APIs tab in the application → toggle Authorized for the Podium API.
  • Permissions: leave default. Podium uses identity claims rather than Auth0-issued permissions.

3. Add the groups claim via an Action

Dashboard: Actions → Library → Build Custom.

  • Name: Add groups to access token.
  • Trigger: Login / Post Login.

Action code:

js
exports.onExecutePostLogin = async (event, api) => {
  const namespace = "https://podium.acme.com/";
  const groups = (event.user.app_metadata && event.user.app_metadata.groups) || [];
  api.idToken.setCustomClaim(`${namespace}groups`, groups);
  api.accessToken.setCustomClaim(`${namespace}groups`, groups);
};

Save and deploy. Then attach the Action: Actions → Triggers → post-login → drag the new Action into the flow → Apply.

This reads the user's groups from app_metadata. Populate app_metadata through your provisioning process: manually for small teams, or via SCIM for larger setups.

The registry reads group membership from the top-level groups claim only. The claim path is not configurable, and IdpGroupMapping rewrites group values rather than redirecting the registry to another claim. A namespaced claim such as https://podium.acme.com/groups therefore never reaches the visibility evaluator. Emit the claim as a top-level groups array on the access token:

js
exports.onExecutePostLogin = async (event, api) => {
  const groups = (event.user.app_metadata && event.user.app_metadata.groups) || [];
  api.accessToken.setCustomClaim("groups", groups);
};

Auth0 restricts non-namespaced custom claims, so the Action emits membership under a namespaced path rather than a top-level groups array. Point identity_provider.groups_claim at that path so the verifier reads it. A deployment that would rather not name the claim can use users: visibility, or resolve membership through SCIM instead of the token claim.

4. Configure Podium

Registry side (registry.yaml):

yaml
registry:
  identity_provider:
    type: oidc-jwt
    issuer: https://<your-tenant>.auth0.com/   # must be https; Auth0 issuers end in a slash
    audience: https://podium.acme.com

Every server-side key nests under the top-level registry: mapping. A document that starts at identity_provider: parses to an empty config and the registry ignores it without reporting an error.

oidc-jwt is the registry's side of the flow: it verifies each presented token against the issuer's JWKS and validates the aud claim against audience:. Setting oauth-device-code as the registry's own provider stops startup with config.identity_provider_unverified.

Restart the registry. The Action emits group membership under the namespaced claim path https://podium.acme.com/groups. A registry that verifies the forwarded token itself runs the oidc-jwt provider: it reads that path when identity_provider.groups_claim (PODIUM_OAUTH_GROUPS_CLAIM) names it, and the IdpGroupMapping adapter then maps the values the claim carries to group names registry-side. The oauth-device-code configuration above installs no request-time verifier, so neither the claim name nor the adapter applies to it. See gateway-delegated identity.

Developer side:

shell
podium init --global --registry https://podium.acme.com
export PODIUM_OAUTH_CLIENT_ID=<client-id>
export PODIUM_OAUTH_AUDIENCE=https://podium.acme.com
export PODIUM_OAUTH_AUTHORIZATION_ENDPOINT=https://<your-tenant>.auth0.com/oauth/device/code
export PODIUM_OAUTH_TOKEN_URL=https://<your-tenant>.auth0.com/oauth/token
podium login

Set PODIUM_OAUTH_TOKEN_URL explicitly. With it unset, podium login derives the token endpoint by appending /token to the device-authorization URL, which produces https://<your-tenant>.auth0.com/oauth/device/code/token and the token exchange fails.

The device-flow verification URL is https://<your-tenant>.auth0.com/activate. After completion, podium login prints the resolved identity.

5. Populate user groups

For small teams, edit app_metadata per user manually:

json
{
  "groups": ["engineering", "platform"]
}

(Dashboard: User Management → Users → [user] → Metadata → app_metadata.)

For larger setups, populate via SCIM (Auth0 Enterprise) or via a directory sync script.

6. Test

Configure an admin layer scoped to a group in registry.yaml. Group-scoped visibility is set in the registry layer config, or with podium layer register --group <name> (also --public, --organization, and --user). Layers registered with --user-defined are private to the registrant and cannot be widened.

yaml
registry:
  layers:
    - id: engineering-only
      source:
        git:
          repo: git@github.com:acme/podium-engineering.git
          ref: main
      visibility:
        groups: [engineering]

Group-scoped visibility resolves on a registry running oidc-jwt with identity_provider.groups_claim (PODIUM_OAUTH_GROUPS_CLAIM) set to the namespaced path the Action emits, and with IdpGroupMapping configured when those claim values have to be rewritten to registry-side group names. On such a registry a user with engineering in app_metadata.groups sees the layer, and a user without it does not. See gateway-delegated identity for that configuration.

Troubleshooting

  • Groups claim is missing from the token. The Action was not attached to the post-login trigger, or the user has no groups in app_metadata. Check the Action's logs: Actions → Library → [Action] → Logs.
  • Token rejected. The token's aud must match the registry's audience:. Confirm the API identifier and audience: match exactly.
  • Custom claim namespace error. Auth0 rejects non-namespaced custom claims. The claim must look like https://your-namespace/groups. A bare groups is rejected. On a registry running oidc-jwt, set identity_provider.groups_claim (PODIUM_OAUTH_GROUPS_CLAIM) to the namespaced path the Action emits.