@adonis-agora/authkit-server 1.0.0-rc.2 → 1.0.0-rc.3

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 (35) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/build/commands/clients_create.d.ts +4 -0
  3. package/build/commands/clients_create.js +97 -0
  4. package/build/commands/commands.json +14 -0
  5. package/build/index.d.ts +3 -0
  6. package/build/index.js +1 -0
  7. package/build/src/audit/audit_sink.d.ts +1 -1
  8. package/build/src/audit/audit_sink.js +5 -0
  9. package/build/src/define_config.d.ts +16 -0
  10. package/build/src/define_config.js +2 -0
  11. package/build/src/host/access_token_verifier.js +7 -0
  12. package/build/src/host/admin_api/api_clients_controller.d.ts +37 -0
  13. package/build/src/host/admin_api/api_clients_controller.js +31 -1
  14. package/build/src/host/admin_api/dto.d.ts +3 -1
  15. package/build/src/host/admin_api/dto.js +2 -0
  16. package/build/src/host/admin_clients_service.d.ts +20 -0
  17. package/build/src/host/admin_clients_service.js +55 -0
  18. package/build/src/host/admin_console/console_clients_controller.d.ts +41 -0
  19. package/build/src/host/admin_console/console_clients_controller.js +34 -1
  20. package/build/src/host/admin_validators.d.ts +29 -0
  21. package/build/src/host/admin_validators.js +30 -0
  22. package/build/src/host/register_auth_host.js +4 -0
  23. package/build/src/host/ui-dist/assets/index-u0bMxkLg.js +67 -0
  24. package/build/src/host/ui-dist/index.html +1 -1
  25. package/build/src/provider/build_provider.js +37 -6
  26. package/build/src/service_tenants/client_metadata.d.ts +39 -0
  27. package/build/src/service_tenants/client_metadata.js +80 -0
  28. package/build/src/service_tenants/config.d.ts +44 -0
  29. package/build/src/service_tenants/config.js +44 -0
  30. package/build/src/service_tenants/provider_hooks.d.ts +52 -0
  31. package/build/src/service_tenants/provider_hooks.js +124 -0
  32. package/build/src/service_tenants/tenant_verifier.d.ts +73 -0
  33. package/build/src/service_tenants/tenant_verifier.js +104 -0
  34. package/package.json +2 -2
  35. package/build/src/host/ui-dist/assets/index-BqyJYRVX.js +0 -67
@@ -9,8 +9,11 @@ import type { HttpContext } from '@adonisjs/core/http';
9
9
  * PATCH {prefix}/api/clients/:id → atualizar metadata
10
10
  * DELETE {prefix}/api/clients/:id → remover client
11
11
  * POST {prefix}/api/clients/:id/regenerate-secret → gerar novo secret
12
+ * POST {prefix}/api/clients/:id/disable → stop issuing tokens to the client
13
+ * POST {prefix}/api/clients/:id/enable → issue tokens again
12
14
  */
13
15
  export default class ConsoleClientsController {
16
+ #private;
14
17
  /** GET {prefix}/api/clients */
15
18
  index(ctx: HttpContext): Promise<{
16
19
  data: {
@@ -25,6 +28,8 @@ export default class ConsoleClientsController {
25
28
  backchannelLogoutSessionRequired: boolean;
26
29
  clientName: string | null;
27
30
  logoUri: string | null;
31
+ disabled: boolean;
32
+ serviceTenant: import("../../service_tenants/client_metadata.ts").ServiceTenantInfo | null;
28
33
  }[];
29
34
  canList: boolean;
30
35
  }>;
@@ -41,6 +46,8 @@ export default class ConsoleClientsController {
41
46
  backchannelLogoutSessionRequired: boolean;
42
47
  clientName: string | null;
43
48
  logoUri: string | null;
49
+ disabled: boolean;
50
+ serviceTenant: import("../../service_tenants/client_metadata.ts").ServiceTenantInfo | null;
44
51
  }>;
45
52
  /** POST {prefix}/api/clients */
46
53
  store(ctx: HttpContext): Promise<void | {
@@ -60,12 +67,46 @@ export default class ConsoleClientsController {
60
67
  backchannelLogoutSessionRequired: boolean;
61
68
  clientName: string | null;
62
69
  logoUri: string | null;
70
+ disabled: boolean;
71
+ serviceTenant: import("../../service_tenants/client_metadata.ts").ServiceTenantInfo | null;
63
72
  }>;
64
73
  /** DELETE {prefix}/api/clients/:id */
65
74
  destroy(ctx: HttpContext): Promise<void | {
66
75
  ok: boolean;
67
76
  deleted: string;
68
77
  }>;
78
+ /** POST {prefix}/api/clients/:id/disable */
79
+ disable(ctx: HttpContext): Promise<void | {
80
+ clientId: string;
81
+ confidential: boolean;
82
+ grantTypes: string[];
83
+ redirectUris: string[];
84
+ postLogoutRedirectUris: string[];
85
+ tokenEndpointAuthMethod: string;
86
+ applicationType: import("../client_metadata.js").ApplicationType;
87
+ backchannelLogoutUri: string | null;
88
+ backchannelLogoutSessionRequired: boolean;
89
+ clientName: string | null;
90
+ logoUri: string | null;
91
+ disabled: boolean;
92
+ serviceTenant: import("../../service_tenants/client_metadata.ts").ServiceTenantInfo | null;
93
+ }>;
94
+ /** POST {prefix}/api/clients/:id/enable */
95
+ enable(ctx: HttpContext): Promise<void | {
96
+ clientId: string;
97
+ confidential: boolean;
98
+ grantTypes: string[];
99
+ redirectUris: string[];
100
+ postLogoutRedirectUris: string[];
101
+ tokenEndpointAuthMethod: string;
102
+ applicationType: import("../client_metadata.js").ApplicationType;
103
+ backchannelLogoutUri: string | null;
104
+ backchannelLogoutSessionRequired: boolean;
105
+ clientName: string | null;
106
+ logoUri: string | null;
107
+ disabled: boolean;
108
+ serviceTenant: import("../../service_tenants/client_metadata.ts").ServiceTenantInfo | null;
109
+ }>;
69
110
  /** POST {prefix}/api/clients/:id/regenerate-secret */
70
111
  regenerateSecret(ctx: HttpContext): Promise<void | {
71
112
  clientId: string;
@@ -19,6 +19,8 @@ function invalidMetadata(ctx, err) {
19
19
  * PATCH {prefix}/api/clients/:id → atualizar metadata
20
20
  * DELETE {prefix}/api/clients/:id → remover client
21
21
  * POST {prefix}/api/clients/:id/regenerate-secret → gerar novo secret
22
+ * POST {prefix}/api/clients/:id/disable → stop issuing tokens to the client
23
+ * POST {prefix}/api/clients/:id/enable → issue tokens again
22
24
  */
23
25
  export default class ConsoleClientsController {
24
26
  /** GET {prefix}/api/clients */
@@ -107,6 +109,34 @@ export default class ConsoleClientsController {
107
109
  });
108
110
  return { ok: true, deleted: id };
109
111
  }
112
+ /** POST {prefix}/api/clients/:id/disable */
113
+ async disable(ctx) {
114
+ return this.#setDisabled(ctx, true);
115
+ }
116
+ /** POST {prefix}/api/clients/:id/enable */
117
+ async enable(ctx) {
118
+ return this.#setDisabled(ctx, false);
119
+ }
120
+ /** Disabled clients get `invalid_client` from the next request on. */
121
+ async #setDisabled(ctx, disabled) {
122
+ const service = await ctx.containerResolver.make('authkit.server');
123
+ const svc = new AdminClientsService(service);
124
+ const id = ctx.request.param('id');
125
+ if (!(await svc.setDisabled(id, disabled))) {
126
+ return ctx.response.notFound(apiError('not_found', 'Client não encontrado.'));
127
+ }
128
+ const client = await svc.find(id);
129
+ await service.config.audit?.record({
130
+ type: disabled ? 'client.disabled' : 'client.enabled',
131
+ clientId: id,
132
+ ip: ctx.request.ip?.() ?? null,
133
+ metadata: {
134
+ actor: 'admin-console',
135
+ ...(client?.serviceTenant ? { partition: client.serviceTenant.partition } : {}),
136
+ },
137
+ });
138
+ return clientDto(client);
139
+ }
110
140
  /** POST {prefix}/api/clients/:id/regenerate-secret */
111
141
  async regenerateSecret(ctx) {
112
142
  const service = await ctx.containerResolver.make('authkit.server');
@@ -129,7 +159,10 @@ export default class ConsoleClientsController {
129
159
  type: 'client.secret_regenerated',
130
160
  clientId: id,
131
161
  ip: ctx.request.ip?.() ?? null,
132
- metadata: { actor: 'admin-console' },
162
+ metadata: {
163
+ actor: 'admin-console',
164
+ ...(existing.serviceTenant ? { partition: existing.serviceTenant.partition } : {}),
165
+ },
133
166
  });
134
167
  return { clientId: id, clientSecret: newSecret };
135
168
  }
@@ -17,6 +17,19 @@ export declare const clientInputValidator: import("@vinejs/vine").VineValidator<
17
17
  backchannelLogoutSessionRequired: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine").VineBoolean>;
18
18
  clientName: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine/schema/base/literal").NullableModifier<import("@vinejs/vine").VineString>>;
19
19
  logoUri: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine/schema/base/literal").NullableModifier<import("@vinejs/vine").VineString>>;
20
+ serviceTenant: import("@vinejs/vine").OptionalModifier<import("@vinejs/vine").NullableModifier<import("@vinejs/vine").VineObject<{
21
+ partition: import("@vinejs/vine").VineString;
22
+ capabilities: import("@vinejs/vine").OptionalModifier<import("@vinejs/vine").VineArray<import("@vinejs/vine").VineString>>;
23
+ }, {
24
+ capabilities?: string[] | null | undefined;
25
+ partition: string;
26
+ }, {
27
+ capabilities?: string[] | undefined;
28
+ partition: string;
29
+ }, {
30
+ capabilities?: string[] | undefined;
31
+ partition: string;
32
+ }>>>;
20
33
  }, {
21
34
  applicationType?: "native" | "web" | null | undefined;
22
35
  backchannelLogoutSessionRequired?: string | number | boolean | null | undefined;
@@ -27,6 +40,10 @@ export declare const clientInputValidator: import("@vinejs/vine").VineValidator<
27
40
  logoUri?: string | null | undefined;
28
41
  postLogoutRedirectUris?: string[] | null | undefined;
29
42
  redirectUris?: string[] | null | undefined;
43
+ serviceTenant?: {
44
+ capabilities?: string[] | null | undefined;
45
+ partition: string;
46
+ } | null | undefined;
30
47
  tokenEndpointAuthMethod?: "client_secret_basic" | "client_secret_post" | "none" | null | undefined;
31
48
  }, {
32
49
  applicationType?: "native" | "web" | undefined;
@@ -38,6 +55,10 @@ export declare const clientInputValidator: import("@vinejs/vine").VineValidator<
38
55
  logoUri?: string | null | undefined;
39
56
  postLogoutRedirectUris?: string[] | undefined;
40
57
  redirectUris?: string[] | undefined;
58
+ serviceTenant?: {
59
+ capabilities?: string[] | undefined;
60
+ partition: string;
61
+ } | null | undefined;
41
62
  tokenEndpointAuthMethod?: "client_secret_basic" | "client_secret_post" | "none" | undefined;
42
63
  }, {
43
64
  applicationType?: "native" | "web" | undefined;
@@ -49,6 +70,10 @@ export declare const clientInputValidator: import("@vinejs/vine").VineValidator<
49
70
  logoUri?: string | null | undefined;
50
71
  postLogoutRedirectUris?: string[] | undefined;
51
72
  redirectUris?: string[] | undefined;
73
+ serviceTenant?: {
74
+ capabilities?: string[] | undefined;
75
+ partition: string;
76
+ } | null | undefined;
52
77
  tokenEndpointAuthMethod?: "client_secret_basic" | "client_secret_post" | "none" | undefined;
53
78
  }>, Record<string, any> | undefined>;
54
79
  /** Forma validada de um client (saída do {@link clientInputValidator}). */
@@ -63,6 +88,10 @@ export type ClientInputFields = {
63
88
  backchannelLogoutSessionRequired?: boolean;
64
89
  clientName?: string | null;
65
90
  logoUri?: string | null;
91
+ serviceTenant?: {
92
+ partition: string;
93
+ capabilities?: string[];
94
+ } | null;
66
95
  };
67
96
  /**
68
97
  * Mapeia o input validado para um {@link ClientInput} COMPLETO (create), com defaults.
@@ -1,4 +1,5 @@
1
1
  import vine from '@vinejs/vine';
2
+ import { CAPABILITY_PATTERN, MAX_CAPABILITIES, PARTITION_PATTERN, } from '../service_tenants/client_metadata.js';
2
3
  import { APPLICATION_TYPES, redirectUriProblem } from './client_metadata.js';
3
4
  import { normalizeEmailIdentifier } from './email_identifier.js';
4
5
  /**
@@ -103,6 +104,18 @@ export const clientInputValidator = vine.compile(vine.object({
103
104
  // `null` (update) removes them.
104
105
  clientName: vine.string().trim().maxLength(200).nullable().optional(),
105
106
  logoUri: vine.string().trim().url(URL_OPTS).nullable().optional(),
107
+ // Service tenant (`client_credentials` + partition claim). `null` (update) turns it
108
+ // back into a regular client.
109
+ serviceTenant: vine
110
+ .object({
111
+ partition: vine.string().trim().regex(PARTITION_PATTERN),
112
+ capabilities: vine
113
+ .array(vine.string().trim().regex(CAPABILITY_PATTERN))
114
+ .maxLength(MAX_CAPABILITIES)
115
+ .optional(),
116
+ })
117
+ .nullable()
118
+ .optional(),
106
119
  }));
107
120
  /**
108
121
  * Mapeia o input validado para um {@link ClientInput} COMPLETO (create), com defaults.
@@ -111,6 +124,21 @@ export const clientInputValidator = vine.compile(vine.object({
111
124
  */
112
125
  export function clientCreateInput(v) {
113
126
  const applicationType = v.applicationType ?? 'web';
127
+ // A service tenant only uses client_credentials: that is its default grant.
128
+ if (v.serviceTenant) {
129
+ return {
130
+ clientId: v.clientId?.trim() || undefined,
131
+ applicationType,
132
+ redirectUris: v.redirectUris ?? [],
133
+ postLogoutRedirectUris: v.postLogoutRedirectUris ?? [],
134
+ grantTypes: v.grantTypes ?? ['client_credentials'],
135
+ tokenEndpointAuthMethod: v.tokenEndpointAuthMethod ?? 'client_secret_basic',
136
+ backchannelLogoutUri: v.backchannelLogoutUri || undefined,
137
+ clientName: v.clientName || undefined,
138
+ logoUri: v.logoUri || undefined,
139
+ serviceTenant: v.serviceTenant,
140
+ };
141
+ }
114
142
  return {
115
143
  clientId: v.clientId?.trim() || undefined,
116
144
  applicationType,
@@ -148,6 +176,8 @@ export function clientPartialInput(v) {
148
176
  out.clientName = v.clientName?.trim() || null;
149
177
  if (v.logoUri !== undefined)
150
178
  out.logoUri = v.logoUri?.trim() || null;
179
+ if (v.serviceTenant !== undefined)
180
+ out.serviceTenant = v.serviceTenant;
151
181
  return out;
152
182
  }
153
183
  // ─── Usuários ───────────────────────────────────────────────────────────────
@@ -997,6 +997,8 @@ export function registerAuthHost(router, opts = {}) {
997
997
  router.get(`${ap}/api/clients/:id`, [C.consoleClients, 'show']);
998
998
  router.patch(`${ap}/api/clients/:id`, [C.consoleClients, 'update']);
999
999
  router.delete(`${ap}/api/clients/:id`, [C.consoleClients, 'destroy']);
1000
+ router.post(`${ap}/api/clients/:id/disable`, [C.consoleClients, 'disable']);
1001
+ router.post(`${ap}/api/clients/:id/enable`, [C.consoleClients, 'enable']);
1000
1002
  router.post(`${ap}/api/clients/:id/regenerate-secret`, [
1001
1003
  C.consoleClients,
1002
1004
  'regenerateSecret',
@@ -1096,6 +1098,8 @@ export function registerAuthHost(router, opts = {}) {
1096
1098
  withApiThrottle(router.patch('/clients/:id', [C.apiClients, 'update']));
1097
1099
  withApiThrottle(router.post('/clients/:id/regenerate-secret', [C.apiClients, 'regenerateSecret']));
1098
1100
  withApiThrottle(router.delete('/clients/:id', [C.apiClients, 'destroy']));
1101
+ withApiThrottle(router.post('/clients/:id/disable', [C.apiClients, 'disable']));
1102
+ withApiThrottle(router.post('/clients/:id/enable', [C.apiClients, 'enable']));
1099
1103
  // Organizações.
1100
1104
  withApiThrottle(router.get('/organizations', [C.apiOrgs, 'index']));
1101
1105
  withApiThrottle(router.post('/organizations', [C.apiOrgs, 'store']));