.agents/features/managed-auth.md
Managed Auth (also called "Embedding" or "Managed Authentication") enables SaaS vendors to embed the Activepieces workflow builder inside their own product. The vendor's backend signs a short-lived JWT using an RSA private key (from a Signing Key), then passes it to the Activepieces embed SDK. The SDK calls POST /v1/managed-authn/external-token with that JWT. The backend verifies the JWT against the stored public key, then auto-provisions or retrieves the user, project, and project limits defined in the token claims, and returns a full Activepieces AuthenticationResponse (including an access token). This feature is gated by platform.plan.embeddingEnabled.
packages/server/api/src/app/ee/managed-authn/managed-authn-module.ts — module registration (no plan gate at module level; gate is on signing-key module)packages/server/api/src/app/ee/managed-authn/managed-authn-controller.ts — single POST /external-token endpointpackages/server/api/src/app/ee/managed-authn/managed-authn-service.ts — orchestration: token extraction, user/project provisioning, token issuancepackages/server/api/src/app/ee/managed-authn/lib/external-token-extractor.ts — JWT verification using the platform's signing key; parses v1/v2/v3 token payloadspackages/shared/src/lib/ee/managed-authn/managed-authn-requests.ts — ManagedAuthnRequestBody schemapackages/web/src/features/authentication/api/managed-auth-api.ts — frontend API client (used by embed SDK integration)Enterprise and Cloud. The endpoint itself is public (securityAccess.public()), but functional only when valid signing keys exist. Signing keys are gated by platform.plan.embeddingEnabled.
managed_<platformId>_<externalUserId>).externalId.| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /v1/managed-authn/external-token | Public | Exchange external JWT for Activepieces session token |
Request body: { externalAccessToken: string }.
Response: AuthenticationResponse (same shape as standard sign-in response, includes token and projectId).
The extractor supports three token versions:
v1/v2 (implicit — no version field):
{ externalUserId, externalProjectId, firstName, lastName, role?, pieces?, concurrencyPoolKey?, concurrencyPoolLimit? }
v3 (explicit version: "v3" field):
{ version: "v3", externalUserId, externalProjectId, firstName, lastName, role?, piecesFilterType?, piecesTags?, concurrencyPoolKey?, concurrencyPoolLimit? }
The JWT header must include kid set to the Signing Key ID.
externalToken)externalTokenExtractor (resolves signing key by kid header, verifies with RS256).getOrCreateProject — looks up project by (platformId, externalProjectId); if absent, creates a new TEAM type project owned by the platform owner.displayName from projectDisplayName claim.updateProjectLimits — resolves allowed pieces from tags/filter type and upserts the project plan.getOrCreateUser — finds user by (platformId, externalUserId); if absent, creates a user identity using a deterministic hashed email (managed_<platformId>_<externalUserId> SHA-256), then creates the platform user.EDITOR).AuthenticationResponse.User emails for managed users are never real emails. The identity email is derived as:
sha256("managed_<platformId>_<externalUserId>").toLowerCase()
This ensures stable, deterministic, non-conflicting identities across vendors.