Lockspire + Sigra (same Phoenix host)
Copy MarkdownLockspire is an embedded OAuth/OIDC authorization server for third-party clients of your API. Sigra is your end-user authentication stack (sessions, passwords, MFA, passkeys, “login with Google” via Assent, admin, audit).
This document is the Lockspire-side counterpart to Sigra’s recipe Companion OAuth provider (guides/recipes/companion-oauth-provider.md on hexdocs).
Boundaries (do not blur)
| Own in Sigra / host | Own in Lockspire |
|---|---|
| User table, sessions, MFA, passkeys, login UX | Clients, codes, tokens, consent protocol, JWKS, discovery |
sub identity for your users | Authorization decisions for external OAuth clients |
Lockspire must not import Sigra at compile time. Integration is host-generated code: your AccountResolver reads the same session Sigra established, typically through conn.assigns.current_scope.user.
Install hint
mix lockspire.install --sigra-host
This adds Sigra-oriented comments (and @moduledoc) to the generated AccountResolver stub. You still implement real resolve_current_account/2 and claim building.
It does not create a second install topology. The canonical path is still mix lockspire.install; --sigra-host only adjusts guidance for the host-owned seam.
After wiring the generated files, use:
mix lockspire.verify
to confirm router wiring, seam presence, config, and migrations. Later, use mix lockspire.upgrade only for Lockspire-managed scaffolding; keep Sigra-facing resolver and UX code host-owned.
Recommended sequencing
- Ship Sigra end-user auth first (register, login, orgs if needed).
- Add Lockspire; complete Phase 3 (OIDC + token lifecycle) before exposing third-party integrations broadly.
- Point
login_pathat your real Sigra login route; preservereturn_to/interaction_idquery params Lockspire needs, then resume the browser through the generated Lockspire interaction route after sign-in.
Host seam contract
For a Sigra-backed host, keep the seam narrow:
- Read the signed-in user from
conn.assigns.current_scope.user. - Build
subfrom a stable internal identifier, not email. - Keep the canonical example claim set narrow; richer profile or org claims remain host-owned decisions.
- Preserve both
return_toandinteraction_idthrough your login bounce so Lockspire can resume the pending interaction safely.
The repo-owned proof for that shape lives in test/integration/phase6_onboarding_e2e_test.exs, which exercises unauthenticated /authorize -> host login -> interaction resume -> consent -> token exchange through generated-host code.
Planning
Cross-repo sequencing lives in Lockspire .planning/ECOSYSTEM-SIGRA.md.