@adonis-agora/authkit-server 0.59.0 → 0.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/build/index.d.ts +4 -2
  2. package/build/index.js +3 -1
  3. package/build/providers/authkit_server_provider.js +7 -0
  4. package/build/src/accounts/account_store.d.ts +20 -1
  5. package/build/src/accounts/account_store.js +4 -0
  6. package/build/src/accounts/lucid_account_store.js +4 -0
  7. package/build/src/accounts/lucid_store/login_methods.d.ts +11 -0
  8. package/build/src/accounts/lucid_store/login_methods.js +32 -0
  9. package/build/src/define_config.d.ts +23 -0
  10. package/build/src/define_config.js +6 -0
  11. package/build/src/host/account_api/account_api_controller.d.ts +38 -0
  12. package/build/src/host/account_api/account_api_controller.js +84 -3
  13. package/build/src/host/auth_host_config.d.ts +9 -0
  14. package/build/src/host/controllers/headless_login_methods_controller.d.ts +31 -0
  15. package/build/src/host/controllers/headless_login_methods_controller.js +79 -0
  16. package/build/src/host/controllers/interaction_controller.js +159 -12
  17. package/build/src/host/controllers/social_controller.js +29 -1
  18. package/build/src/host/login_methods_state.d.ts +39 -0
  19. package/build/src/host/login_methods_state.js +52 -0
  20. package/build/src/host/register_auth_host.js +18 -0
  21. package/build/src/host/ui-dist/assets/{index-6cE5JMyP.js → index-Cb38N16r.js} +1 -1
  22. package/build/src/host/ui-dist/index.html +1 -1
  23. package/build/src/host/user_login_methods.d.ts +94 -0
  24. package/build/src/host/user_login_methods.js +132 -0
  25. package/package.json +7 -4
  26. package/skills/authkit-idp-setup/SKILL.md +222 -0
  27. package/skills/authkit-interactions/SKILL.md +236 -0
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: authkit-interactions
3
+ description: >-
4
+ Implement the host-owned login/consent interaction screens of @adonis-agora/authkit-server.
5
+ Covers oidc-provider's interactions.url redirect to /auth/interaction/:uid, the three
6
+ routes every IdP app must register (show/login/consent on AuthInteractionController),
7
+ `node ace configure --ui=edge|react|headless` presets, the shell-controller +
8
+ service.interactions split (details(ctx), login(ctx,{email,password}), consent(ctx)),
9
+ overriding verifyCredentials in config/authkit.ts, renderers edgeRenderer/inertiaRenderer,
10
+ and end-to-end testing with @adonis-agora/authkit-testing (createTestIdentity,
11
+ mintTestIdToken, serveJwks, fakeAuthenticator). Use when the authorization flow 404s at
12
+ the login screen, wiring custom login UI, plugging an external user base, or testing
13
+ OIDC flows without booting an IdP.
14
+ license: MIT
15
+ metadata:
16
+ type: core
17
+ library: "@adonis-agora/authkit-server"
18
+ library_version: "0.60.0"
19
+ framework: adonisjs
20
+ sources:
21
+ - "DavideCarvalho/adonis-authkit:packages/authkit-server/README.md"
22
+ - "DavideCarvalho/adonis-authkit:packages/authkit-server/src/host/renderers/inertia_renderer.ts"
23
+ - "DavideCarvalho/adonis-authkit:packages/authkit-server/src/define_config.ts"
24
+ - "DavideCarvalho/adonis-authkit:packages/authkit-testing/README.md"
25
+ ---
26
+
27
+ # Login & consent screens (interactions)
28
+
29
+ When `oidc-provider` meets an unauthenticated user it redirects to
30
+ `interactions.url` (`/auth/interaction/:uid`). Those screens are **yours** — the kit
31
+ ejects a controller shell via `node ace configure` and you register the routes that
32
+ point at it. Without them the authorization code flow dies with a 404 exactly when
33
+ the user should log in.
34
+
35
+ ## Setup
36
+
37
+ Pick a UI preset when configuring (asks interactively if omitted):
38
+
39
+ ```bash
40
+ node ace configure @adonis-agora/authkit-server --ui=edge
41
+ # values: edge | react | headless
42
+ ```
43
+
44
+ Each preset publishes `app/controllers/auth_interaction_controller.ts`; `edge` adds
45
+ Edge views, `react` adds Inertia pages (validating that `@adonisjs/inertia` + Vite +
46
+ React exist first), `headless` returns JSON only. Register the three routes:
47
+
48
+ ```ts
49
+ // start/routes.ts
50
+ import router from '@adonisjs/core/services/router'
51
+ import AuthInteractionController from '#controllers/auth_interaction_controller'
52
+
53
+ router.get('/auth/interaction/:uid', [AuthInteractionController, 'show'])
54
+ router.post('/auth/interaction/:uid/login', [AuthInteractionController, 'login'])
55
+ router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'consent'])
56
+ ```
57
+
58
+ Source: `packages/authkit-server/README.md` § Rotas de interaction.
59
+
60
+ ## Core patterns
61
+
62
+ ### Pattern 1 — edit the shell, keep logic in `service.interactions`
63
+
64
+ In all presets the ejected controller is a thin shell: the logic lives in
65
+ `service.interactions`, resolved via `containerResolver.make('authkit.server')`.
66
+ It exposes `details(ctx)` (the prompt + params), `login(ctx, { email, password })`
67
+ and `consent(ctx)`. You only edit the render/redirect parts:
68
+
69
+ ```ts
70
+ // headless preset flavor — show() returns JSON, you build your own front
71
+ async show({ request, response }) {
72
+ const service = await this.ctx.containerResolver.make('authkit.server')
73
+ const details = await service.interactions.details(this.ctx)
74
+ return response.json({ uid: request.param('uid'), prompt: details.prompt, params: details.params })
75
+ }
76
+ ```
77
+
78
+ Keep validation, MFA prompts and grant bookkeeping inside `service.interactions`;
79
+ the shell only translates between HTTP and those calls.
80
+
81
+ Source: `packages/authkit-server/README.md` § UI de login/consent ("o controller
82
+ ejetado é casca: a lógica vive em `service.interactions`").
83
+
84
+ ### Pattern 2 — plug your user base via `verifyCredentials`
85
+
86
+ `verifyCredentials` in `config/authkit.ts` decides whether credentials are valid;
87
+ `service.interactions.login` calls it. The default queries the `AuthUser` model by
88
+ email and uses `verifyPassword` — override to authenticate against anything else:
89
+
90
+ ```ts
91
+ // config/authkit.ts
92
+ defineConfig({
93
+ issuer: env.get('AUTHKIT_ISSUER'),
94
+ adapter: adapters.redis({ connection: 'main' }),
95
+ accountStore: lucidAccountStore(AuthUser),
96
+ verifyCredentials: async (email, password) => {
97
+ // Return the account on success; throw/falsy paths fail the login.
98
+ const account = await AuthUser.query().where('email', email).first()
99
+ if (!account) throw new Error('Invalid credentials')
100
+ await verifyPassword(account.passwordHash, password)
101
+ return account
102
+ },
103
+ })
104
+ ```
105
+
106
+ Whatever it returns must be the same identity surface the configured
107
+ `accountStore` serves, or downstream `findAccount` lookups diverge from what just
108
+ logged in.
109
+
110
+ Source: `packages/authkit-server/README.md` § UI de login/consent (verifyCredentials),
111
+ `src/define_config.ts` (`accountStore` derives findAccount/verifyCredentials).
112
+
113
+ ### Pattern 3 — custom rendering with `inertiaRenderer`
114
+
115
+ Hosts building their own React screens set the `render` option instead of relying
116
+ on the default Edge renderer:
117
+
118
+ ```ts
119
+ import { defineConfig, inertiaRenderer } from '@adonis-agora/authkit-server'
120
+
121
+ defineConfig({
122
+ issuer: env.get('AUTHKIT_ISSUER'),
123
+ adapter: adapters.database(),
124
+ accountStore: lucidAccountStore(AuthUser),
125
+ render: inertiaRenderer(), // renders Inertia pages for /account/* and /auth/interaction/*
126
+ })
127
+ ```
128
+
129
+ Without any renderer, every `/account/*` and `/auth/interaction/*` request fails
130
+ with an unexplained 500 (`render` is undefined).
131
+
132
+ Source: `src/define_config.ts` (`render` JSDoc), `index.ts` exports
133
+ (`inertiaRenderer`, `edgeRenderer`).
134
+
135
+ ### Pattern 4 — test flows without booting an IdP
136
+
137
+ `@adonis-agora/authkit-testing` mints real signed ID tokens validated by a local
138
+ JWKS, and fakes the authenticator for controller tests:
139
+
140
+ ```ts
141
+ import { mintTestIdToken, serveJwks, fakeAuthenticator } from '@adonis-agora/authkit-testing'
142
+ import { resolvers } from '@adonis-agora/authkit-client'
143
+
144
+ const { token, jwks } = await mintTestIdToken({
145
+ issuer: 'https://idp.test',
146
+ clientId: 'my-app',
147
+ claims: { sub: 'user-42', email: 'jane@test.dev', roles: ['ADMIN'] },
148
+ })
149
+
150
+ const served = await serveJwks(jwks)
151
+ const factory = resolvers.jwt({ jwksUri: served.jwksUri })
152
+ const resolver = await factory.resolver({
153
+ issuer: 'https://idp.test',
154
+ clientId: 'my-app',
155
+ sessionKey: 'authkit',
156
+ globalRolesClaim: 'roles',
157
+ })
158
+ const ctx = { auth: fakeAuthenticator({ identity: null }) } // anonymous request fake
159
+ await served.close()
160
+ ```
161
+
162
+ Also available: `createTestIdentity(overrides?)` for valid `Identity` defaults,
163
+ `fakeAccountStore({ withMfa: true, ... })` for capability-probed store fakes.
164
+
165
+ Source: `packages/authkit-testing/README.md`.
166
+
167
+ ## Common mistakes
168
+
169
+ ### CRITICAL — Forgetting to register the interaction routes
170
+
171
+ ```ts
172
+ // Wrong — only the protocol endpoints exist
173
+ registerOidcRoutes(router)
174
+ // no GET /auth/interaction/:uid anywhere
175
+ ```
176
+
177
+ ```ts
178
+ // Correct — the three host-owned routes are registered next to the OIDC mount
179
+ registerOidcRoutes(router)
180
+ router.get('/auth/interaction/:uid', [AuthInteractionController, 'show'])
181
+ router.post('/auth/interaction/:uid/login', [AuthInteractionController, 'login'])
182
+ router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'consent'])
183
+ ```
184
+
185
+ Nothing crashes at boot; the failure surfaces mid-flow — the user's browser lands
186
+ on `/auth/interaction/:uid` and gets a 404, so no client can ever complete login.
187
+
188
+ Source: `packages/authkit-server/README.md` § Rotas de interaction ("Sem essas rotas
189
+ o fluxo de autorização cai num 404 ao chegar na tela de login").
190
+
191
+ ### HIGH — Writing login/consent logic inside the ejected controller shell
192
+
193
+ ```ts
194
+ // Wrong — reimplementing prompt handling/grants in the ejected shell
195
+ async consent(ctx) {
196
+ // hand-rolling grant persistence against oidc-provider internals...
197
+ }
198
+ ```
199
+
200
+ ```ts
201
+ // Correct — shell delegates; the service owns the flow
202
+ async consent(ctx) {
203
+ const service = await ctx.containerResolver.make('authkit.server')
204
+ await service.interactions.consent(ctx) // handles the grant, returns the redirect
205
+ }
206
+ ```
207
+
208
+ The shell is regenerated by `configure` and has no access to the provider's
209
+ interaction plumbing; duplicating logic there silently drifts from prompt/consent
210
+ semantics the provider expects.
211
+
212
+ Source: `packages/authkit-server/README.md` § UI de login/consent ("Você edita só a
213
+ parte de render/redirect").
214
+
215
+ ### MEDIUM — Choosing `--ui=react` without the Inertia stack installed
216
+
217
+ ```bash
218
+ # Wrong — react preset in a bare API-only AdonisJS app
219
+ node ace configure @adonis-agora/authkit-server --ui=react
220
+ ```
221
+
222
+ ```bash
223
+ # Correct — match the preset to the app stack
224
+ node ace configure @adonis-agora/authkit-server --ui=edge # server-rendered views
225
+ node ace configure @adonis-agora/authkit-server --ui=headless # build your own front
226
+ ```
227
+
228
+ The `react` preset requires `@adonisjs/inertia` + Vite + React in the host app —
229
+ `configure` validates the stack before publishing, so the command aborts instead of
230
+ half-configuring your app.
231
+
232
+ Source: `packages/authkit-server/README.md` § UI de login/consent ("Exige
233
+ @adonisjs/inertia + Vite + React no app — o configure valida essa stack").
234
+
235
+ See also: `authkit-rp-client/SKILL.md` — the consuming side that ends up holding
236
+ the session these screens create.