@absolutejs/auth 0.74.0 → 0.75.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 (39) hide show
  1. package/README.md +8 -6
  2. package/dist/apikeys/routes.d.ts +1 -1
  3. package/dist/compliance/routes.d.ts +1 -1
  4. package/dist/credentials/emailVerification.d.ts +1 -1
  5. package/dist/credentials/login.d.ts +1 -1
  6. package/dist/credentials/passwordReset.d.ts +1 -1
  7. package/dist/credentials/register.d.ts +1 -1
  8. package/dist/htmx/configuredRoutes.d.ts +1 -1
  9. package/dist/htmx/routes.d.ts +1 -1
  10. package/dist/index.js +116 -57
  11. package/dist/index.js.map +5 -5
  12. package/dist/mfa/challenge.d.ts +1 -1
  13. package/dist/mfa/management.d.ts +1 -1
  14. package/dist/mfa/sms.d.ts +1 -1
  15. package/dist/mfa/totp.d.ts +1 -1
  16. package/dist/nativePush.d.ts +500 -20
  17. package/dist/organizations/routes.d.ts +1 -1
  18. package/dist/portal/routes.d.ts +1 -1
  19. package/dist/roles/routes.d.ts +1 -1
  20. package/dist/routes/authorize.d.ts +1 -1
  21. package/dist/routes/callback.d.ts +1 -1
  22. package/dist/routes/profile.d.ts +1 -1
  23. package/dist/routes/refresh.d.ts +1 -1
  24. package/dist/routes/revoke.d.ts +1 -1
  25. package/dist/routes/sessions.d.ts +1 -1
  26. package/dist/routes/signout.d.ts +1 -1
  27. package/dist/routes/userStatus.d.ts +1 -1
  28. package/dist/scim/routes.d.ts +1 -1
  29. package/dist/server.js +114 -57
  30. package/dist/server.js.map +5 -5
  31. package/dist/sso/discoveryRoute.d.ts +1 -1
  32. package/dist/sso/oidcRoutes.d.ts +1 -1
  33. package/dist/sso/samlIdpRoutes.d.ts +1 -1
  34. package/dist/sso/samlRoutes.d.ts +1 -1
  35. package/dist/types.d.ts +3 -1
  36. package/dist/vc/statusListRoutes.d.ts +1 -1
  37. package/dist/vc/vpRoutes.d.ts +1 -1
  38. package/dist/webauthn/routes.d.ts +1 -1
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -118,13 +118,14 @@ stacked and reversible, and web/server runtimes never install the registry.
118
118
  When portable push is enabled, Auth also owns its authenticated installation
119
119
  boundary. Pass the existing Dispatch push lifecycle directly; the server derives
120
120
  the principal, tenant, and authorized topics and returns an opaque installation
121
- identity. The native shell is the only code that sees the APNs/FCM token, and
122
- ordinary application/page code cannot read it:
121
+ identity. The native shell handles APNs/FCM tokens, while the generated PWA
122
+ runtime handles structured browser subscriptions; ordinary page code reads
123
+ neither provider credential:
123
124
 
124
125
  ```ts
125
126
  const authApplication = await auth({
126
127
  // ...normal Auth + OIDC configuration
127
- nativePush: {
128
+ push: {
128
129
  registrar: pushLifecycle,
129
130
  tenant: (principal) => principal.user.organizationId,
130
131
  topics: (principal) => topicsFor(principal.user)
@@ -132,9 +133,10 @@ const authApplication = await auth({
132
133
  });
133
134
  ```
134
135
 
135
- The fixed `/auth/mobile/push` route accepts bearer-authenticated native clients
136
- and cookie-authenticated web clients, but never accepts user ID, tenant, or
137
- topics from either. Token rotation and deletion require the server-issued
136
+ The fixed `/auth/push` route accepts bearer-authenticated native clients and
137
+ cookie-authenticated web clients, but never accepts user ID, tenant, or topics
138
+ from either. The prior `/auth/mobile/push` path remains an installed-client
139
+ compatibility alias. Credential rotation and deletion require the server-issued
138
140
  installation identity and Dispatch verifies that it belongs to the current
139
141
  principal. Native sign-out attempts removal while credentials still exist and
140
142
  always clears the local provider registration even when the network is down.
@@ -31,7 +31,7 @@ export declare const apiKeysRoutes: ({ accessTokenStore, accessTokenTtlMs, apiCl
31
31
  status?: number | keyof import("elysia").StatusMap;
32
32
  cookie?: Record<string, import("elysia").BaseCookie>;
33
33
  };
34
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
34
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
35
35
  readonly 100: "Continue";
36
36
  readonly 101: "Switching Protocols";
37
37
  readonly 102: "Processing";
@@ -62,7 +62,7 @@ export declare const complianceRoutes: <UserType>({ authSessionStore, compliance
62
62
  status?: number | keyof import("elysia").StatusMap;
63
63
  cookie?: Record<string, import("elysia").BaseCookie>;
64
64
  };
65
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
65
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
66
66
  readonly 100: "Continue";
67
67
  readonly 101: "Switching Protocols";
68
68
  readonly 102: "Processing";
@@ -46,7 +46,7 @@ export declare const credentialsEmailVerification: <UserType>({ credentialStore,
46
46
  status?: number | keyof import("elysia").StatusMap;
47
47
  cookie?: Record<string, import("elysia").BaseCookie>;
48
48
  };
49
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
49
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
50
50
  readonly 100: "Continue";
51
51
  readonly 101: "Switching Protocols";
52
52
  readonly 102: "Processing";
@@ -41,7 +41,7 @@ export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreac
41
41
  status?: number | keyof import("elysia").StatusMap;
42
42
  cookie?: Record<string, import("elysia").BaseCookie>;
43
43
  };
44
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
44
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
45
45
  readonly 100: "Continue";
46
46
  readonly 101: "Switching Protocols";
47
47
  readonly 102: "Processing";
@@ -52,7 +52,7 @@ export declare const credentialsPasswordReset: <UserType>({ credentialStore, onP
52
52
  status?: number | keyof import("elysia").StatusMap;
53
53
  cookie?: Record<string, import("elysia").BaseCookie>;
54
54
  };
55
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
55
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
56
56
  readonly 100: "Continue";
57
57
  readonly 101: "Switching Protocols";
58
58
  readonly 102: "Processing";
@@ -41,7 +41,7 @@ export declare const credentialsRegister: <UserType>({ authSessionStore, cookieS
41
41
  status?: number | keyof import("elysia").StatusMap;
42
42
  cookie?: Record<string, import("elysia").BaseCookie>;
43
43
  };
44
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
44
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
45
45
  readonly 100: "Continue";
46
46
  readonly 101: "Switching Protocols";
47
47
  readonly 102: "Processing";
@@ -511,7 +511,7 @@ export declare const createConfiguredAuthHtmxRoutes: <UserType>({ authSessionSto
511
511
  status?: number | keyof import("elysia").StatusMap;
512
512
  cookie?: Record<string, import("elysia").BaseCookie>;
513
513
  };
514
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
514
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
515
515
  readonly 100: "Continue";
516
516
  readonly 101: "Switching Protocols";
517
517
  readonly 102: "Processing";
@@ -506,7 +506,7 @@ export declare const createAuthHtmxRoutes: <UserType extends AuthHtmxUser>(confi
506
506
  status?: number | keyof import("elysia").StatusMap;
507
507
  cookie?: Record<string, import("elysia").BaseCookie>;
508
508
  };
509
- status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
509
+ status: <const Code extends number | keyof import("elysia").StatusMap, const T = Code extends 400 | 401 | 403 | 501 | 204 | 404 | 200 | 301 | 302 | 303 | 307 | 308 | 409 | 100 | 101 | 102 | 103 | 201 | 202 | 203 | 205 | 206 | 207 | 208 | 300 | 304 | 402 | 405 | 406 | 407 | 408 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 ? {
510
510
  readonly 100: "Continue";
511
511
  readonly 101: "Switching Protocols";
512
512
  readonly 102: "Processing";
package/dist/index.js CHANGED
@@ -6191,24 +6191,97 @@ var createMfaGate = ({ getUserId, mfaStore }) => async (user) => isMfaEnrolled(a
6191
6191
 
6192
6192
  // src/nativePush.ts
6193
6193
  import { Elysia as Elysia17, t as t11 } from "elysia";
6194
+ var DEFAULT_PUSH_ROUTE = "/auth/push";
6194
6195
  var DEFAULT_NATIVE_PUSH_ROUTE = "/auth/mobile/push";
6195
6196
  var requireServerText = (value, field) => {
6196
6197
  const normalized = value.trim();
6197
6198
  if (!normalized)
6198
- throw new TypeError(`Native push ${field} must not be empty.`);
6199
+ throw new TypeError(`Push ${field} must not be empty.`);
6199
6200
  return normalized;
6200
6201
  };
6201
6202
  var isInstallationOwnershipError = (error) => error instanceof Error && error.name === "PushInstallationOwnershipError";
6202
- var nativePushRoutes = ({
6203
+ var pushRoutes = ({
6203
6204
  accessTokens,
6204
6205
  authSessionStore,
6205
6206
  config
6206
6207
  }) => {
6207
- const resolveTenant = async (principal) => requireServerText(typeof config.tenant === "function" ? await config.tenant(principal) : config.tenant, "native tenant");
6208
+ const resolveTenant = async (principal) => requireServerText(typeof config.tenant === "function" ? await config.tenant(principal) : config.tenant, "tenant");
6208
6209
  const resolveTopics = async (principal) => [
6209
6210
  ...new Set((await config.topics?.(principal) ?? []).map((topic) => requireServerText(topic, "topic")))
6210
6211
  ].sort();
6211
- return new Elysia17({ name: "@absolutejs/auth/native-push" }).use(sessionStore()).guard({
6212
+ const register = async (body, principal) => {
6213
+ try {
6214
+ const registration = await config.registrar.registerInstallation({
6215
+ ...body.installationId ? { installationId: body.installationId } : {},
6216
+ ...body.locale ? { locale: body.locale } : {},
6217
+ ...body.platform === "webpush" ? {
6218
+ platform: body.platform,
6219
+ subscription: body.subscription
6220
+ } : { platform: body.platform, token: body.token },
6221
+ tenant: await resolveTenant(principal),
6222
+ topics: await resolveTopics(principal),
6223
+ userId: principal.subject
6224
+ });
6225
+ return {
6226
+ installationId: requireServerText(registration.installationId, "installation id"),
6227
+ registered: true
6228
+ };
6229
+ } catch (error) {
6230
+ if (isInstallationOwnershipError(error))
6231
+ return null;
6232
+ throw error;
6233
+ }
6234
+ };
6235
+ const remove = async (installationId, principal) => {
6236
+ try {
6237
+ await config.registrar.removeInstallation({
6238
+ installationId,
6239
+ tenant: await resolveTenant(principal),
6240
+ userId: principal.subject
6241
+ });
6242
+ } catch (error) {
6243
+ if (isInstallationOwnershipError(error))
6244
+ return false;
6245
+ throw error;
6246
+ }
6247
+ return true;
6248
+ };
6249
+ const commonRegistrationFields = {
6250
+ installationId: t11.Optional(t11.String({ maxLength: 128, minLength: 1 })),
6251
+ locale: t11.Optional(t11.String({ maxLength: 64, minLength: 1 }))
6252
+ };
6253
+ const registrationBody = t11.Union([
6254
+ t11.Object({
6255
+ ...commonRegistrationFields,
6256
+ platform: t11.Union([t11.Literal("apns"), t11.Literal("fcm")]),
6257
+ token: t11.String({ maxLength: 8192, minLength: 1 })
6258
+ }),
6259
+ t11.Object({
6260
+ ...commonRegistrationFields,
6261
+ platform: t11.Literal("webpush"),
6262
+ subscription: t11.Object({
6263
+ endpoint: t11.String({ maxLength: 8192, minLength: 1 }),
6264
+ keys: t11.Object({
6265
+ auth: t11.String({ maxLength: 8192, minLength: 1 }),
6266
+ p256dh: t11.String({ maxLength: 8192, minLength: 1 })
6267
+ })
6268
+ })
6269
+ })
6270
+ ]);
6271
+ const registrationOptions = {
6272
+ body: registrationBody,
6273
+ beforeHandle: ({
6274
+ pushPrincipal,
6275
+ status
6276
+ }) => pushPrincipal ? undefined : status("Unauthorized", "User is not authenticated")
6277
+ };
6278
+ const removalOptions = {
6279
+ body: t11.Object({
6280
+ installationId: t11.String({ maxLength: 128, minLength: 1 })
6281
+ }),
6282
+ beforeHandle: registrationOptions.beforeHandle
6283
+ };
6284
+ return new Elysia17({ name: "@absolutejs/auth/push" }).use(sessionStore()).guard({
6212
6285
  cookie: t11.Cookie({ user_session_id: userSessionIdTypebox }),
6213
6286
  schema: "merge"
6214
6287
  }).derive(async ({
@@ -6229,56 +6302,36 @@ var nativePushRoutes = ({
6229
6302
  authorization: headers.authorization,
6230
6303
  config: accessTokens
6231
6304
  });
6232
- return { nativePushPrincipal: principal };
6233
- }).post(DEFAULT_NATIVE_PUSH_ROUTE, {
6234
- body: t11.Object({
6235
- installationId: t11.Optional(t11.String({ maxLength: 128, minLength: 1 })),
6236
- locale: t11.Optional(t11.String({ maxLength: 64, minLength: 1 })),
6237
- platform: t11.Union([t11.Literal("apns"), t11.Literal("fcm")]),
6238
- token: t11.String({ maxLength: 8192, minLength: 1 })
6239
- }),
6240
- beforeHandle: ({ nativePushPrincipal, status }) => nativePushPrincipal ? undefined : status("Unauthorized", "User is not authenticated")
6241
- }, async ({ body, nativePushPrincipal, status }) => {
6242
- if (!nativePushPrincipal)
6305
+ return { pushPrincipal: principal };
6306
+ }).post(DEFAULT_PUSH_ROUTE, registrationOptions, async ({ body, pushPrincipal, status }) => {
6307
+ if (!pushPrincipal)
6243
6308
  return status("Unauthorized", "User is not authenticated");
6244
- let registration;
6245
- try {
6246
- registration = await config.registrar.registerInstallation({
6247
- ...body.installationId ? { installationId: body.installationId } : {},
6248
- ...body.locale ? { locale: body.locale } : {},
6249
- platform: body.platform,
6250
- tenant: await resolveTenant(nativePushPrincipal),
6251
- token: body.token,
6252
- topics: await resolveTopics(nativePushPrincipal),
6253
- userId: nativePushPrincipal.subject
6254
- });
6255
- } catch (error) {
6256
- if (isInstallationOwnershipError(error))
6257
- return status("Conflict", {
6258
- code: "installation-ownership"
6259
- });
6260
- throw error;
6261
- }
6262
- return {
6263
- installationId: requireServerText(registration.installationId, "installation id"),
6264
- registered: true
6265
- };
6266
- }).delete(DEFAULT_NATIVE_PUSH_ROUTE, {
6267
- body: t11.Object({
6268
- installationId: t11.String({ maxLength: 128, minLength: 1 })
6269
- }),
6270
- beforeHandle: ({ nativePushPrincipal, status }) => nativePushPrincipal ? undefined : status("Unauthorized", "User is not authenticated")
6271
- }, async ({ body, nativePushPrincipal, status }) => {
6272
- if (!nativePushPrincipal)
6309
+ const result = await register(body, pushPrincipal);
6310
+ return result ?? status("Conflict", {
6311
+ code: "installation-ownership"
6312
+ });
6313
+ }).post(DEFAULT_NATIVE_PUSH_ROUTE, registrationOptions, async ({ body, pushPrincipal, status }) => {
6314
+ if (!pushPrincipal)
6315
+ return status("Unauthorized", "User is not authenticated");
6316
+ const result = await register(body, pushPrincipal);
6317
+ return result ?? status("Conflict", {
6318
+ code: "installation-ownership"
6319
+ });
6320
+ }).delete(DEFAULT_PUSH_ROUTE, removalOptions, async ({ body, pushPrincipal, status }) => {
6321
+ if (!pushPrincipal)
6322
+ return status("Unauthorized", "User is not authenticated");
6323
+ return await remove(body.installationId, pushPrincipal) ? { removed: true } : status("Conflict", {
6324
+ code: "installation-ownership"
6325
+ });
6326
+ }).delete(DEFAULT_NATIVE_PUSH_ROUTE, removalOptions, async ({ body, pushPrincipal, status }) => {
6327
+ if (!pushPrincipal)
6273
6328
  return status("Unauthorized", "User is not authenticated");
6274
- await config.registrar.removeInstallation({
6275
- installationId: body.installationId,
6276
- tenant: await resolveTenant(nativePushPrincipal),
6277
- userId: nativePushPrincipal.subject
6329
+ return await remove(body.installationId, pushPrincipal) ? { removed: true } : status("Conflict", {
6330
+ code: "installation-ownership"
6278
6331
  });
6279
- return { removed: true };
6280
6332
  });
6281
6333
  };
6334
+ var nativePushRoutes = pushRoutes;
6282
6335
 
6283
6336
  // src/mfa/routes.ts
6284
6337
  import { Elysia as Elysia22 } from "elysia";
@@ -40047,6 +40100,7 @@ var buildAuthApplications = async (configuration) => {
40047
40100
  customProviders,
40048
40101
  mfa,
40049
40102
  nativePush: nativePush2,
40103
+ push,
40050
40104
  verificationProvider,
40051
40105
  passwordless,
40052
40106
  lockout,
@@ -40083,8 +40137,11 @@ var buildAuthApplications = async (configuration) => {
40083
40137
  onRevocationError,
40084
40138
  onSessionCleanup
40085
40139
  } = configuration;
40086
- if (nativePush2 && !oidc)
40087
- throw new Error("nativePush requires the OIDC provider");
40140
+ if (push && nativePush2)
40141
+ throw new Error("Configure `push`, not both `push` and `nativePush`");
40142
+ const pushConfig = push ?? nativePush2;
40143
+ if (pushConfig && !oidc)
40144
+ throw new Error("push requires the OIDC provider");
40088
40145
  if (agentAuth?.agentRegistration !== undefined) {
40089
40146
  if (oidc === undefined) {
40090
40147
  throw new Error("agentAuth.agentRegistration requires the OIDC provider");
@@ -40328,18 +40385,18 @@ var buildAuthApplications = async (configuration) => {
40328
40385
  emit: auditEmit
40329
40386
  }) : new Elysia48
40330
40387
  ]);
40331
- const nativePushApplication = new Elysia48;
40332
- if (nativePush2 && oidcConfig)
40333
- nativePushApplication.use(nativePushRoutes({
40388
+ const pushApplication = new Elysia48;
40389
+ if (pushConfig && oidcConfig)
40390
+ pushApplication.use(pushRoutes({
40334
40391
  accessTokens: {
40335
40392
  oidc: oidcConfig,
40336
40393
  getUser: async (subject) => await getUser(subject) ?? null
40337
40394
  },
40338
40395
  authSessionStore,
40339
- config: nativePush2
40396
+ config: pushConfig
40340
40397
  }));
40341
40398
  const extendedFeatureRoutes = new Elysia48().use([
40342
- nativePushApplication,
40399
+ pushApplication,
40343
40400
  portal ? portalRoutes({ ...portal, emit: auditEmit }) : new Elysia48,
40344
40401
  webauthn ? webauthnRoutes({
40345
40402
  ...webauthn,
@@ -40496,6 +40553,7 @@ export {
40496
40553
  readSessionRing,
40497
40554
  readSessionCookie,
40498
40555
  readAuthSyncPartition,
40556
+ pushRoutes,
40499
40557
  pushAuthorizationRequest,
40500
40558
  pruneInactiveUsers,
40501
40559
  providersFromEnv,
@@ -40886,6 +40944,7 @@ export {
40886
40944
  DEFAULT_SCIM_ROUTE,
40887
40945
  DEFAULT_ROLES_ROUTE,
40888
40946
  DEFAULT_RESET_TOKEN_TTL_MS,
40947
+ DEFAULT_PUSH_ROUTE,
40889
40948
  DEFAULT_PORTAL_ROUTE,
40890
40949
  DEFAULT_PASSWORDLESS_SESSION_TTL_MS,
40891
40950
  DEFAULT_PASSWORDLESS_ROUTE,
@@ -40914,5 +40973,5 @@ export {
40914
40973
  ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV
40915
40974
  };
40916
40975
 
40917
- //# debugId=3448A14AC106260464756E2164756E21
40976
+ //# debugId=A9E81CE91544BE6B64756E2164756E21
40918
40977
  //# sourceMappingURL=index.js.map