Skip to content

docs: add login hooks and custom claims guide, with an Auth0 Actions mapping - #166

Draft
Bccorb wants to merge 2 commits into
docs/webhooks-guidefrom
docs/login-hooks-custom-claims-guide
Draft

Bccorb wants to merge 2 commits into
docs/webhooks-guidefrom
docs/login-hooks-custom-claims-guide

Conversation

@Bccorb

@Bccorb Bccorb commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Closes #154. Adds build/login-hooks-custom-claims.mdx: login hooks, static custom claims, and how to port Auth0 Actions and Rules to them.

Merge with the auth API v0.23.0 release, not before. Every route on the page needs API v0.23.0, which is held (fells-code/seamless-auth-api#566). The page opens with a caution, and its versions table marks the console pages (fells-code/seamless-auth-admin-dashboard#343), the CLI commands (fells-code/seamless-cli#359) and provider token claims (fells-code/seamless-auth-oidc-provider#63) as unreleased.

Stacked on #165 (base docs/webhooks-guide), since the page links the webhooks guide for the shared signing and URL rules. It also adds the webhooks guide's link back to this page.

What it covers

  • Where each runs: a table for sign-in, organization switch, refresh, session exchange, break-glass and recovery. pre_token claims are as fresh as the session (not called on refresh); static role claims are resolved at every token, refresh included.
  • Hooks: the call body (LoginHookCallSchema) and answers, reason (audited, never shown) versus userMessage (shown), stripping of reserved names versus failing on other bad claims, the sign-in routes that can answer 403 login_denied and 503 login_hook_unavailable, timeouts (2000 ms default, 100 to 5000, one attempt), failure modes and when to pick each, the invocation log and audit events, setup through the console, CLI and admin API, and that a PUT resets omitted settings to defaults.
  • Example hook service: a dependency-free Node.js service with signature verification. It notes that verifyWebhook refuses hook calls (invalid_payload), because it parses against the webhook catalog.
  • Static claims: sources and precedence (instance roles, then organization roles, then the OpenID client, then pre_token, with role name order inside a kind), setup, name and value rules, the full reserved list, the shared 1 KiB budget in the order chosen on 2026-11-07, and the provider scopes permissions and custom_claims (final, per Brandon's decision of 2026-11-07).
  • Auth0 mapping: each Action API and trigger mapped, with every Auth0 behavior cited to Auth0's docs, and a section on the refresh difference.
  • Cross-link: the "Actions" row in operate/migrate-from-auth0.mdx now points here, saying v0.23.0 is not released.

How the example was proven

The hook service was run locally and called with bodies built by LoginHookCallSchema.parse and headers from the auth API's own signedCalloutHeaders (on feat/oidc-provider-claims): an allowed post_login, a denied one, and a pre_token call signed with two secrets. Each answer parsed with PostLoginHookResultSchema or PreTokenHookResultSchema, and the API's screenHookClaims kept the claims unchanged. A call signed with the wrong secret and one with a timestamp 400 seconds old both got 401.

Auth0 facts, each checked on Auth0's site on 2026-11-07

For review

  • Provider sign retry: described as built in seamless-auth-oidc-provider#63 (cda30da, src/claimsMismatch.ts) with seamless-auth-api#585 answering claims_mismatch: the provider reads the account again and signs once more; a second mismatch, or an account that has gone, answers 500 server_error with "the account changed while the token was being issued, try again"; no other refusal is retried.
  • Showing userMessage: the page says @seamless-auth/react and @seamless-auth/client put the code in err.message and the hook's text at err.body.message, and the built-in views show fixed text (from the seamless-auth-api#583 body). An SDK change would let the line go.
  • Left out: what Auth0 does when an Action throws or times out, since I did not find it stated on the pages above.

Testing

  • npm run typecheck: 0 errors, 0 warnings, 0 hints.
  • npm run lint: exit 0.
  • npm run build: 76 pages built (re-run after the retry update in a5d8f98). The pre-commit hook ran the build again.
  • A script confirmed every internal link and anchor in the new page, the webhooks page and migrate-from-auth0 resolves in dist. The page is in dist/llms.txt and the sitemap.
  • Not run: npm run check:matrix, and nothing against a live API (none can be until v0.23.0).

…mapping

Covers where post_login, pre_token and static claims run (never for
break-glass or recovery, pre_token not on refresh), the call and answer
bodies, reason versus userMessage, the 403 login_denied and 503
login_hook_unavailable responses, timeouts and when to fail open or
closed, a verified example hook service, static claims per instance
role, organization role and OpenID client with their precedence, the
reserved names, the shared 1 KiB budget, the provider scopes, and how
Auth0 Actions and Rules port, including that Auth0 runs post-login
Actions on refresh and Seamless does not.

Closes #154
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant