headless_idp
Headless IdP authenticates a decoupled Drupal site against an external identity provider, so you don't have to write the JWT-validation, MFA and account-linking glue yourself. The provider handles passwords, MFA and the user lifecycle; Drupal validates the token and runs as your API backend.
Features
- Two providers ready to use. AWS Cognito and Okta ship with the module, and a capability-interface plugin API lets you add more. Microsoft Entra ID, Keycloak and Supabase are on the 1.x roadmap, so you're not tied to one vendor.
- The whole auth lifecycle, not just login. Password sign-in, MFA challenge and response, user enrolment, session revocation, email and password sync, and refresh-token rotation.
- Headless-first. REST endpoints, JSON in and out, Bearer id_tokens. No redirect flows, no session cookies and no OAuth login screens to theme. Your frontend (Nuxt, Next, or anything that speaks HTTP) handles all of that.
- Security you don't have to build. JWKS signature verification, algorithm-confusion rejection, strict issuer and audience binding, and length caps. Defence-in-depth from the start, with a dedicated security-kernel test suite.
- Extensible by interface. Each provider declares which capabilities it supports and the module adapts. Adding a provider or a capability never breaks the ones already shipped.
- Operator tooling. Drush commands to inspect providers, manage the Drupal-to-IdP account links, migrate from openid_connect, and manage MFA preferences. Backed by over 900 unit and kernel tests.
Why use it
It's built for teams running a Nuxt, Next or other SPA frontend on a Drupal backend who want their external IdP to handle credentials, MFA and the lifecycle, with Drupal as the policy and API layer. The provider does the security-sensitive work; you get a clean, headless, provider-agnostic integration instead of bespoke glue code.
How it works
Your frontend signs the user in against the IdP and gets a JWT back, then sends that token to Drupal as a Bearer credential. Drupal verifies the signature against the provider's published keys (JWKS), links the token to a Drupal user through the externalauth module, and treats the request as authenticated.
Requirements
- Drupal 10.2 or 11, PHP 8.1 or later
- simple_oauth, externalauth, and firebase/php-jwt
- The AWS SDK (aws/aws-sdk-php) when you enable the Cognito sub-module
Getting started
Enable the base module and at least one provider sub-module (headless_idp_cognito and/or headless_idp_okta), then run drush cache:rebuild. Configure it at Configuration > People > Headless IdP. Each provider's own setup is documented in its sub-module README, and a reference Nuxt 3 frontend composable ships in the module's docs.
Documentation
- Module README - installation, configuration, endpoint reference and the capability table.
- AWS Cognito provider README - user-pool setup, IAM policy and operator recipes.
- Okta provider README - org setup, API token scopes and the setup FAQ.
- Frontend integration example (Nuxt 3) - a reference composable covering login, MFA challenge, token refresh and logout.
How it compares
- OpenID Connect is redirect-flow OIDC for server-rendered Drupal. Headless IdP is Bearer-token and headless-first instead, and provider-agnostic through capability interfaces.
- JWT mints and validates Drupal-issued JWTs. Headless IdP validates JWTs minted by an external IdP.