@adonis-agora/authkit-client 0.18.4 → 0.18.6

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.
package/README.md CHANGED
@@ -12,6 +12,30 @@ O `configure` publica `config/authkit_client.ts`, o controller `app/controllers/
12
12
  (login/callback/logout) e registra o provider + o middleware `authkit_middleware`.
13
13
 
14
14
  ## Rotas de sessão
15
+
16
+ O caminho **recomendado** é `registerOidcClient(router)`: uma chamada que monta
17
+ `/auth/login`, `/auth/callback`, `/auth/logout` e o back-channel logout
18
+ (`POST /auth/backchannel-logout`), já usando `startSession`/`endSession` e o
19
+ RP-initiated logout. Substitui o boilerplate do controller ejetado.
20
+ ```ts
21
+ // start/routes.ts
22
+ import { registerOidcClient } from '@adonis-agora/authkit-client'
23
+
24
+ registerOidcClient(router, {
25
+ prefix: '/auth', // default
26
+ loginMiddleware: middleware.guest(),
27
+ redirects: { byGlobalRole: { ADMIN: '/admin' }, default: '/' },
28
+ afterLogin: async (ctx, identity) => undefined, // retornar string redireciona
29
+ postLogoutRedirect: '/', // default: origem do redirectUri + '/'
30
+ backchannelLogout: true, // default
31
+ })
32
+ ```
33
+ Opções: `prefix`, `afterLogin`, `redirects`, `postLogoutRedirect`, `backchannelLogout`,
34
+ `loginMiddleware` e `passthroughParams`. `AUTHKIT_REDIRECT_URI` deve apontar para a rota de callback.
35
+
36
+ ### Customização (controller ejetado)
37
+ Se precisar de rotas próprias, o `configure` publica `app/controllers/oidc_session_controller.ts`
38
+ (login/callback/logout) para você adaptar:
15
39
  ```ts
16
40
  // start/routes.ts
17
41
  import OidcSessionController from '#controllers/oidc_session_controller'
@@ -19,7 +43,12 @@ router.get('/auth/login', [OidcSessionController, 'login'])
19
43
  router.get('/auth/callback', [OidcSessionController, 'callback'])
20
44
  router.post('/auth/logout', [OidcSessionController, 'logout'])
21
45
  ```
22
- `AUTHKIT_REDIRECT_URI` deve apontar para a rota de callback.
46
+ > **Ao editar o controller, use o manager — não escreva a sessão cru.** No callback chame
47
+ > `manager.startSession(ctx, tokenSet)` e no logout `manager.endSession(ctx)`; **nunca**
48
+ > `session.put(sessionKey)` / `session.forget(sessionKey)`. A escrita crua não limpa o
49
+ > `impersonationBinding` nem a credencial de impersonação parqueada — o refresh token do ator
50
+ > continua serializado no cookie da próxima identidade, e o logout deixa a credencial viva.
51
+ > `startSession`/`endSession` são os caminhos que mantêm a invariante.
23
52
 
24
53
  ## Uso por request
25
54
  `ctx.auth` é populado pelo `authkit_middleware`:
@@ -18,6 +18,13 @@ export function registerOidcClient(router, options = {}) {
18
18
  const prefix = options.prefix ?? '/auth';
19
19
  const passthrough = options.passthroughParams ?? ['audience'];
20
20
  const pkceKey = 'authkit_pkce';
21
+ // Todo redirect desta função vai para uma URL que a PRÓPRIA lib monta (authorize,
22
+ // /login, destino do app, end-session). O Adonis encaminha a query string da
23
+ // request atual por padrão (`redirect.forwardQueryString`), então `redirect(dest)`
24
+ // sem o `false` explícito arrasta o `code`/`state`/`iss` do callback para o
25
+ // destino — o app terminava em `/?code=…&state=…&iss=…` depois do login, e o
26
+ // `/auth/login` de um callback falho carregava o code antigo para o authorize
27
+ // seguinte. Nenhum desses redirects deve encaminhar query: o destino já a tem.
21
28
  const loginRoute = router.get(`${prefix}/login`, async (ctx) => {
22
29
  const manager = await ctx.containerResolver.make('authkit.client');
23
30
  const cfg = manager.clientConfig;
@@ -39,7 +46,7 @@ export function registerOidcClient(router, options = {}) {
39
46
  codeChallenge: challenge,
40
47
  ...(Object.keys(extraParams).length ? { extraParams } : {}),
41
48
  });
42
- return ctx.response.redirect(url);
49
+ return ctx.response.redirect(url, false);
43
50
  });
44
51
  if (options.loginMiddleware)
45
52
  loginRoute.use(options.loginMiddleware);
@@ -53,7 +60,7 @@ export function registerOidcClient(router, options = {}) {
53
60
  // Callback velho/expirado (state perdido ou code ausente) → recomeça o login.
54
61
  if (!pkce || pkce.state !== state || !code) {
55
62
  ctx.session?.forget(pkceKey);
56
- return ctx.response.redirect(`${prefix}/login`);
63
+ return ctx.response.redirect(`${prefix}/login`, false);
57
64
  }
58
65
  const tokenSet = await exchangeCode({
59
66
  issuer: cfg.issuer,
@@ -72,10 +79,10 @@ export function registerOidcClient(router, options = {}) {
72
79
  // 1) Hook do app tem prioridade quando retorna uma rota.
73
80
  const hook = await options.afterLogin?.(ctx, identity);
74
81
  if (typeof hook === 'string')
75
- return ctx.response.redirect(hook);
82
+ return ctx.response.redirect(hook, false);
76
83
  // 2) Redirect por role global (do token).
77
84
  const dest = resolveDestination(identity, options.redirects);
78
- return ctx.response.redirect(dest);
85
+ return ctx.response.redirect(dest, false);
79
86
  })
80
87
  .as('auth.callback');
81
88
  router
@@ -95,7 +102,7 @@ export function registerOidcClient(router, options = {}) {
95
102
  postLogoutRedirectUri,
96
103
  clientId: cfg.clientId,
97
104
  });
98
- return ctx.response.redirect(endSessionUrl);
105
+ return ctx.response.redirect(endSessionUrl, false);
99
106
  })
100
107
  .as('auth.logout');
101
108
  if (options.backchannelLogout !== false) {
@@ -29,14 +29,14 @@ export default class OidcSessionController {
29
29
  issuer: cfg.issuer, clientId: cfg.clientId, clientSecret: cfg.clientSecret,
30
30
  redirectUri: cfg.redirectUri, code, codeVerifier: pkce.verifier,
31
31
  })
32
- ctx.session.put(cfg.sessionKey, tokenSet)
32
+ manager.startSession(ctx, tokenSet)
33
33
  ctx.session.forget('authkit_pkce')
34
34
  return ctx.response.redirect('/')
35
35
  }
36
36
 
37
37
  async logout(ctx: HttpContext) {
38
38
  const manager = await ctx.containerResolver.make('authkit.client')
39
- ctx.session.forget(manager.clientConfig.sessionKey)
39
+ manager.endSession(ctx)
40
40
  return ctx.response.redirect('/')
41
41
  }
42
42
  }
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@adonis-agora/authkit-client",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
4
4
  "description": "AdonisJS OIDC/OAuth2 relying-party (client) toolkit: session-based authentication against an OpenID Connect identity provider, with JWT/PAT user resolvers and OpenTelemetry metrics.",
5
5
  "license": "MIT",
6
6
  "author": "dudousxd",
7
- "homepage": "https://github.com/DavideCarvalho/adonis-agora-authkit/tree/main/packages/authkit-client#readme",
8
7
  "repository": {
9
8
  "type": "git",
10
9
  "url": "https://github.com/DavideCarvalho/adonis-agora-authkit.git",
11
10
  "directory": "packages/authkit-client"
12
11
  },
12
+ "homepage": "https://davidecarvalho.github.io/agora/docs/authkit",
13
13
  "bugs": {
14
14
  "url": "https://github.com/DavideCarvalho/adonis-agora-authkit/issues"
15
15
  },
@@ -62,10 +62,10 @@
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@adonis-agora/resilience": ">=0.1.0 <1.0.0",
65
- "@adonisjs/auth": "^10.1.0",
66
- "@adonisjs/core": "^7.5.0",
67
- "@adonisjs/lucid": "^22.4.2",
68
- "@adonisjs/session": "^8.1.0"
65
+ "@adonisjs/auth": "10.1.0",
66
+ "@adonisjs/core": "7.5.0",
67
+ "@adonisjs/lucid": "22.4.2",
68
+ "@adonisjs/session": "8.1.0"
69
69
  },
70
70
  "peerDependenciesMeta": {
71
71
  "@adonisjs/auth": {
@@ -83,8 +83,8 @@
83
83
  "jose": "6.2.12"
84
84
  },
85
85
  "devDependencies": {
86
- "@adonis-agora/authkit-server": "0.66.0",
87
- "@adonis-agora/resilience": "0.3.6",
86
+ "@adonis-agora/authkit-server": "0.68.2",
87
+ "@adonis-agora/resilience": "0.3.7",
88
88
  "@adonisjs/auth": "10.1.0",
89
89
  "@adonisjs/core": "7.5.0",
90
90
  "@adonisjs/lucid": "22.4.2",
@@ -93,8 +93,8 @@
93
93
  "@japa/assert": "4.2.0",
94
94
  "@japa/runner": "5.3.0",
95
95
  "@poppinss/ts-exec": "1.4.4",
96
- "@tanstack/intent": "^0.4.0",
97
- "@types/node": "26.5.0",
96
+ "@tanstack/intent": "0.4.0",
97
+ "@types/node": "26.5.1",
98
98
  "ioredis-mock": "8.13.1",
99
99
  "tempura": "0.4.1",
100
100
  "typescript": "7.0.2"
@@ -29,14 +29,14 @@ export default class OidcSessionController {
29
29
  issuer: cfg.issuer, clientId: cfg.clientId, clientSecret: cfg.clientSecret,
30
30
  redirectUri: cfg.redirectUri, code, codeVerifier: pkce.verifier,
31
31
  })
32
- ctx.session.put(cfg.sessionKey, tokenSet)
32
+ manager.startSession(ctx, tokenSet)
33
33
  ctx.session.forget('authkit_pkce')
34
34
  return ctx.response.redirect('/')
35
35
  }
36
36
 
37
37
  async logout(ctx: HttpContext) {
38
38
  const manager = await ctx.containerResolver.make('authkit.client')
39
- ctx.session.forget(manager.clientConfig.sessionKey)
39
+ manager.endSession(ctx)
40
40
  return ctx.response.redirect('/')
41
41
  }
42
42
  }