Install And Onboard
Copy MarkdownThe canonical onboarding path is Phoenix-first and generator-first. Lockspire stays embedded inside your host app; the host continues to own accounts, login UX, layouts, branding, and product policy. For the full 1.0 GA support contract, see docs/supported-surface.md.
If you plan to authenticate confidential clients with private_key_jwt, read docs/private-key-jwt-host-guide.md for the shipped jwks / jwks_uri support slice, issuer-string aud requirement, and key-rotation behavior.
1. Add Lockspire
Add :lockspire to your dependencies and fetch deps.
Lockspire's logout propagation slice also expects:
Obanrunning in the host release. Lockspire starts a named Oban runtime and fails fast if the repo or Oban runtime config is missing or invalid.Reqavailable for back-channel logout delivery. Lockspire usesReqfor server-to-server logout POSTs once/end_session/completepersists and enqueues the work.
2. Generate the host seam
Run:
mix lockspire.install
This creates one canonical Phoenix onboarding layout with two ownership classes:
- Lockspire-managed scaffolding:
config/lockspire.exslib/<web>/router/lockspire.extest/<app>/lockspire_fapi_smoke_e2e_test.exs.lockspire/install_manifest.json
- Host-owned seams:
- Account resolution
- Interaction handoff
- Consent UI shell
- Authorized apps account surface
- Device verification controller and templates
The manifest tracks only Lockspire-managed scaffolding. It is the source of truth for later safe upgrades.
The generator also creates host-owned files for:
- Lockspire config
- Router mount helpers
- Account resolution
- Interaction handoff
- Consent UI shell
- Authorized apps account surface
- Device verification controller (
lockspire_verification_controller.ex) - Device verification HTML module (
lockspire_verification_html.ex) - Device verification template (
lockspire_verification_html/index.html.heex)
3. Wire the generated files
Import config/lockspire.exs from your main config entrypoint.
Import YourAppWeb.Router.Lockspire from your host router and call lockspire_routes/0 where your product wants the Lockspire routes to live.
Implement the generated AccountResolver with:
- Current-account lookup from your host-owned session seam
- For Sigra pairings, read
conn.assigns.current_scope.userinstead of importing Sigra at compile time - Account lookup by subject reference
- Claim building for ID token and userinfo
- Login redirect behavior that preserves
interaction_idandreturn_to - Post-login resume behavior that sends the browser back through the generated interaction path before consent continues
Implement the generated interaction and consent modules in the host app where your product wants login and approval UX to live. Lockspire owns the OAuth/OIDC protocol flow; your host app owns the human-facing account and policy decisions.
If you need custom RAR consent copy, edit the generated lockspire_consent_live.ex seam directly and follow docs/rar-consent-host-guide.md. The guide shows one illustrative payment_initiation example built on structural authorization_details data while keeping semantics, branding, and policy host-owned.
Keep the generated host logout seam truthful as well: your host app clears its own browser session first, then returns to Lockspire's /end_session/complete endpoint. That completion endpoint is the protocol-owned fork point for token revocation, logout propagation persistence, back-channel enqueueing, and the front-channel best effort page.
Implement the generated LockspireVerificationController and lockspire_verification_html files as a host-owned /verify seam. Keep your session and account pipeline in front of the approval routes, treat verification_uri_complete as prefill-only, and keep GET side-effect free.
If you plan to support device login, keep that host-owned /verify seam paired with Lockspire's shipped device endpoints:
POST /device/codeissues the device authorization and tells clients to begin with a 5-second poll interval.POST /tokenacceptsgrant_type=urn:ietf:params:oauth:grant-type:device_code, returnsauthorization_pendingwhile approval is still pending, and returnsslow_downwhen the client polls too aggressively.- Approval still happens only through the host-owned
/verifyseam; Lockspire does not take over your browser UX.
4. Run migrations
Run:
mix ecto.migrate
5. Verify the install wiring
Run:
mix lockspire.verify
This is the canonical post-install diagnostics step. It checks:
- required
:lockspireruntime config - the generated seam modules are present
- the host router still exposes the host-owned
/verifyroutes - the host router still forwards the embedded Lockspire routes at your mount path
- Lockspire and Oban migrations are applied
6. Create a client and prove the flow
The canonical proof bar is:
- Discovery returns the issuer and endpoint set.
- JWKS returns the public signing keys.
- A client can complete an authorization-code + PKCE exchange.
- A confidential client can use the shipped direct-client auth surface the way
docs/private-key-jwt-host-guide.mddescribes if you choose that mode. - If you configure RP logout propagation,
/end_session/completepersists the logout event, enqueues back-channel delivery through Oban, and renders front-channel iframe cleanup as best effort only.
The executable repo proof lives in:
test/integration/install_generator_test.exstest/integration/phase6_onboarding_e2e_test.exsfor the unauthenticated/authorize-> host login -> interaction resume -> consent -> token exchange path
The maintained contributor gate for that proof is mix ci, which runs the docs, package, fast-test, integration, and phase gates described in .github/workflows/ci.yml.
7. Upgrade only the managed scaffolding
When a newer Lockspire version changes generated managed files, preview the update with:
mix lockspire.upgrade --dry-run
Apply it with:
mix lockspire.upgrade
mix lockspire.upgrade only touches manifest-tracked managed scaffolding that is still unchanged. It never rewrites host-owned seams, and it refuses risky overwrites when a managed file has drifted from the recorded checksum.
8. Finish the verification seam before shipping device login
Before you expose /verify publicly:
- Wire host auth and session behavior around the generated
LockspireVerificationController. - Add host-owned rate limiting for both
GET /verifyandPOST /verify. - Keep approve and deny behind explicit signed-in user actions.
- Read
docs/device-flow-host-guide.mdfor the full verification security contract, including anti-phishing rules, trusted proxy IP guidance, the 5-second device polling baseline,slow_downbackoff,Retry-After, and normalized-code limiter keys.
Sigra companion path
If your host app already uses Sigra for end-user auth, run:
mix lockspire.install --sigra-host
That only changes comments and guidance in the generated resolver stub. It does not add a compile-time dependency on Sigra or create a second canonical path. For the full host-seam contract, including conn.assigns.current_scope.user, claim-shape guidance, and login-resume expectations, see docs/sigra-companion-host.md.