@spfn/auth 0.2.0-beta.66 → 0.2.0-beta.68

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/dist/server.js CHANGED
@@ -4501,7 +4501,7 @@ var init_types = __esm({
4501
4501
  KEY_ALGORITHM = ["ES256", "RS256"];
4502
4502
  INVITATION_STATUSES = ["pending", "accepted", "expired", "cancelled"];
4503
4503
  USER_STATUSES = ["active", "inactive", "suspended"];
4504
- SOCIAL_PROVIDERS = ["google", "github", "kakao", "naver", "superself"];
4504
+ SOCIAL_PROVIDERS = ["google", "apple", "github", "kakao", "naver", "superself"];
4505
4505
  }
4506
4506
  });
4507
4507
 
@@ -8104,8 +8104,8 @@ async function updateUserProfileService(userId, params) {
8104
8104
 
8105
8105
  // src/server/services/oauth.service.ts
8106
8106
  init_repositories();
8107
- import { env as env9 } from "@spfn/auth/config";
8108
- import { ValidationError as ValidationError3 } from "@spfn/core/errors";
8107
+ import { env as env11 } from "@spfn/auth/config";
8108
+ import { ValidationError as ValidationError5 } from "@spfn/core/errors";
8109
8109
 
8110
8110
  // src/server/lib/oauth/google.ts
8111
8111
  import { env as env7 } from "@spfn/auth/config";
@@ -8255,7 +8255,59 @@ function getRegisteredProviders() {
8255
8255
  return [...registry.values()];
8256
8256
  }
8257
8257
 
8258
+ // src/server/lib/oauth/jwks-verify.ts
8259
+ import { createRemoteJWKSet, jwtVerify } from "jose";
8260
+ import { InvalidSocialTokenError } from "@spfn/auth/errors";
8261
+ var CLOCK_TOLERANCE_SECONDS = 30;
8262
+ var jwksByUri = /* @__PURE__ */ new Map();
8263
+ function getRemoteJwks(jwksUri) {
8264
+ const cached = jwksByUri.get(jwksUri);
8265
+ if (cached) {
8266
+ return cached;
8267
+ }
8268
+ const jwks = createRemoteJWKSet(new URL(jwksUri));
8269
+ jwksByUri.set(jwksUri, jwks);
8270
+ return jwks;
8271
+ }
8272
+ async function verifyIdToken(params) {
8273
+ const payload = await verifySignature(params);
8274
+ if (payload.nonce !== params.expectedNonce) {
8275
+ throw new InvalidSocialTokenError({ message: "id_token nonce mismatch" });
8276
+ }
8277
+ if (typeof payload.sub !== "string" || payload.sub.length === 0) {
8278
+ throw new InvalidSocialTokenError({ message: "id_token is missing the subject (sub) claim" });
8279
+ }
8280
+ return payload;
8281
+ }
8282
+ async function verifySignature(params) {
8283
+ try {
8284
+ const { payload } = await jwtVerify(params.idToken, getRemoteJwks(params.jwksUri), {
8285
+ issuer: params.issuer,
8286
+ audience: params.audiences,
8287
+ algorithms: params.algorithms,
8288
+ clockTolerance: CLOCK_TOLERANCE_SECONDS
8289
+ });
8290
+ return payload;
8291
+ } catch (err) {
8292
+ authLogger.service.warn("id_token signature/claims verification failed", {
8293
+ reason: err instanceof Error ? err.message : "unknown"
8294
+ });
8295
+ throw new InvalidSocialTokenError();
8296
+ }
8297
+ }
8298
+
8258
8299
  // src/server/lib/oauth/google-provider.ts
8300
+ import { env as env9 } from "@spfn/auth/config";
8301
+ import { ValidationError as ValidationError3 } from "@spfn/core/errors";
8302
+ var GOOGLE_JWKS_URI = "https://www.googleapis.com/oauth2/v3/certs";
8303
+ var GOOGLE_ISSUERS = ["https://accounts.google.com", "accounts.google.com"];
8304
+ function getGoogleNativeAudiences() {
8305
+ const ids = (env9.SPFN_AUTH_GOOGLE_NATIVE_CLIENT_IDS || "").split(",").map((s) => s.trim()).filter(Boolean);
8306
+ if (env9.SPFN_AUTH_GOOGLE_CLIENT_ID) {
8307
+ ids.push(env9.SPFN_AUTH_GOOGLE_CLIENT_ID);
8308
+ }
8309
+ return ids;
8310
+ }
8259
8311
  var googleProvider = {
8260
8312
  id: "google",
8261
8313
  isEnabled: isGoogleOAuthEnabled,
@@ -8285,20 +8337,98 @@ var googleProvider = {
8285
8337
  refreshToken: tokens.refresh_token,
8286
8338
  expiresIn: tokens.expires_in
8287
8339
  };
8340
+ },
8341
+ async verifyNativeIdToken(idToken, options) {
8342
+ const audiences = getGoogleNativeAudiences();
8343
+ if (audiences.length === 0) {
8344
+ throw new ValidationError3({
8345
+ message: "Google native sign-in is not configured. Set SPFN_AUTH_GOOGLE_NATIVE_CLIENT_IDS."
8346
+ });
8347
+ }
8348
+ const payload = await verifyIdToken({
8349
+ idToken,
8350
+ jwksUri: GOOGLE_JWKS_URI,
8351
+ issuer: GOOGLE_ISSUERS,
8352
+ audiences,
8353
+ algorithms: ["RS256"],
8354
+ expectedNonce: options.nonce
8355
+ });
8356
+ return {
8357
+ providerUserId: payload.sub,
8358
+ email: payload.email ?? null,
8359
+ emailVerified: payload.email_verified === true || payload.email_verified === "true",
8360
+ name: payload.name,
8361
+ avatar: payload.picture
8362
+ };
8288
8363
  }
8289
8364
  };
8290
8365
  registerOAuthProvider(googleProvider);
8291
8366
 
8367
+ // src/server/lib/oauth/apple-provider.ts
8368
+ import { createHash as createHash2 } from "crypto";
8369
+ import { env as env10 } from "@spfn/auth/config";
8370
+ import { ValidationError as ValidationError4 } from "@spfn/core/errors";
8371
+ var APPLE_JWKS_URI = "https://appleid.apple.com/auth/keys";
8372
+ var APPLE_ISSUER = "https://appleid.apple.com";
8373
+ function getAppleClientIds() {
8374
+ return (env10.SPFN_AUTH_APPLE_CLIENT_IDS || "").split(",").map((s) => s.trim()).filter(Boolean);
8375
+ }
8376
+ function hashNonce(rawNonce) {
8377
+ return createHash2("sha256").update(rawNonce).digest("hex");
8378
+ }
8379
+ function unsupportedWebFlow() {
8380
+ throw new ValidationError4({
8381
+ message: "Apple provider supports native id_token sign-in only. Use POST /_auth/oauth/apple/native."
8382
+ });
8383
+ }
8384
+ var appleProvider = {
8385
+ id: "apple",
8386
+ isEnabled() {
8387
+ return getAppleClientIds().length > 0;
8388
+ },
8389
+ getAuthUrl() {
8390
+ unsupportedWebFlow();
8391
+ },
8392
+ async exchangeCodeForTokens() {
8393
+ unsupportedWebFlow();
8394
+ },
8395
+ async getUserInfo() {
8396
+ unsupportedWebFlow();
8397
+ },
8398
+ async verifyNativeIdToken(idToken, options) {
8399
+ const audiences = getAppleClientIds();
8400
+ if (audiences.length === 0) {
8401
+ throw new ValidationError4({
8402
+ message: "Apple native sign-in is not configured. Set SPFN_AUTH_APPLE_CLIENT_IDS."
8403
+ });
8404
+ }
8405
+ const payload = await verifyIdToken({
8406
+ idToken,
8407
+ jwksUri: APPLE_JWKS_URI,
8408
+ issuer: APPLE_ISSUER,
8409
+ audiences,
8410
+ algorithms: ["RS256"],
8411
+ expectedNonce: hashNonce(options.nonce)
8412
+ });
8413
+ return {
8414
+ providerUserId: payload.sub,
8415
+ email: payload.email ?? null,
8416
+ emailVerified: payload.email_verified === true || payload.email_verified === "true"
8417
+ };
8418
+ }
8419
+ };
8420
+ registerOAuthProvider(appleProvider);
8421
+
8292
8422
  // src/server/services/oauth.service.ts
8293
8423
  function requireEnabledProvider(provider) {
8294
8424
  const oauthProvider = getOAuthProvider(provider);
8295
8425
  if (!oauthProvider) {
8296
- throw new ValidationError3({
8426
+ throw new ValidationError5({
8297
8427
  message: `Unsupported OAuth provider: ${provider}. No provider is registered for this id.`
8298
8428
  });
8299
8429
  }
8300
8430
  if (!oauthProvider.isEnabled()) {
8301
- throw new ValidationError3({
8431
+ throw new ValidationError5({
8302
8432
  message: `OAuth provider '${provider}' is registered but not configured. Check its required environment variables.`
8303
8433
  });
8304
8434
  }
@@ -8306,7 +8436,7 @@ function requireEnabledProvider(provider) {
8306
8436
  }
8307
8437
  function tokenExpiryDate(expiresIn) {
8308
8438
  if (!Number.isFinite(expiresIn)) {
8309
- throw new ValidationError3({
8439
+ throw new ValidationError5({
8310
8440
  message: `Invalid token expiry returned from OAuth provider: ${expiresIn}`
8311
8441
  });
8312
8442
  }
@@ -8330,7 +8460,7 @@ async function oauthCallbackService(params) {
8330
8460
  const { provider, code, state } = params;
8331
8461
  const stateData = await verifyOAuthState(state);
8332
8462
  if (stateData.provider !== provider) {
8333
- throw new ValidationError3({
8463
+ throw new ValidationError5({
8334
8464
  message: "OAuth state provider mismatch"
8335
8465
  });
8336
8466
  }
@@ -8363,8 +8493,8 @@ async function oauthCallbackService(params) {
8363
8493
  algorithm: stateData.algorithm
8364
8494
  });
8365
8495
  await updateLastLoginService(userId);
8366
- const appUrl = env9.NEXT_PUBLIC_SPFN_APP_URL || env9.SPFN_APP_URL;
8367
- const callbackPath = env9.SPFN_AUTH_OAUTH_SUCCESS_URL || "/auth/callback";
8496
+ const appUrl = env11.NEXT_PUBLIC_SPFN_APP_URL || env11.SPFN_APP_URL;
8497
+ const callbackPath = env11.SPFN_AUTH_OAUTH_SUCCESS_URL || "/auth/callback";
8368
8498
  const callbackUrl = callbackPath.startsWith("http") ? callbackPath : `${appUrl}${callbackPath}`;
8369
8499
  const redirectUrl = buildRedirectUrl(callbackUrl, {
8370
8500
  userId: String(userId),
@@ -8398,7 +8528,7 @@ async function createOrLinkUser(provider, identity, tokens) {
8398
8528
  let isNewUser = false;
8399
8529
  if (existingUser) {
8400
8530
  if (!identity.emailVerified) {
8401
- throw new ValidationError3({
8531
+ throw new ValidationError5({
8402
8532
  message: "Cannot link to existing account with unverified email. Please verify your email with the provider first."
8403
8533
  });
8404
8534
  }
@@ -8432,9 +8562,9 @@ async function createOrLinkUser(provider, identity, tokens) {
8432
8562
  provider,
8433
8563
  providerUserId: identity.providerUserId,
8434
8564
  providerEmail: identity.email,
8435
- accessToken: tokens.accessToken,
8436
- refreshToken: tokens.refreshToken ?? null,
8437
- tokenExpiresAt: tokenExpiryDate(tokens.expiresIn)
8565
+ accessToken: tokens?.accessToken ?? null,
8566
+ refreshToken: tokens?.refreshToken ?? null,
8567
+ tokenExpiresAt: tokens ? tokenExpiryDate(tokens.expiresIn) : null
8438
8568
  });
8439
8569
  return { userId, isNewUser };
8440
8570
  }
@@ -8449,7 +8579,7 @@ function buildRedirectUrl(baseUrl, params) {
8449
8579
  return `${url.pathname}${url.search}`;
8450
8580
  }
8451
8581
  function buildOAuthErrorUrl(error) {
8452
- const errorUrl = env9.SPFN_AUTH_OAUTH_ERROR_URL || "/auth/error?error={error}";
8582
+ const errorUrl = env11.SPFN_AUTH_OAUTH_ERROR_URL || "/auth/error?error={error}";
8453
8583
  return errorUrl.replace("{error}", encodeURIComponent(error));
8454
8584
  }
8455
8585
  function isOAuthProviderEnabled(provider) {
@@ -8462,7 +8592,7 @@ var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
8462
8592
  async function getGoogleAccessToken(userId) {
8463
8593
  const account = await socialAccountsRepository.findByUserIdAndProvider(userId, "google");
8464
8594
  if (!account) {
8465
- throw new ValidationError3({
8595
+ throw new ValidationError5({
8466
8596
  message: "No Google account linked. User must sign in with Google first."
8467
8597
  });
8468
8598
  }
@@ -8471,7 +8601,7 @@ async function getGoogleAccessToken(userId) {
8471
8601
  return account.accessToken;
8472
8602
  }
8473
8603
  if (!account.refreshToken) {
8474
- throw new ValidationError3({
8604
+ throw new ValidationError5({
8475
8605
  message: "Google refresh token not available. User must re-authenticate with Google."
8476
8606
  });
8477
8607
  }
@@ -8484,6 +8614,57 @@ async function getGoogleAccessToken(userId) {
8484
8614
  return tokens.access_token;
8485
8615
  }
8486
8616
 
8617
+ // src/server/services/oauth-native.service.ts
8618
+ init_repositories();
8619
+ import { ValidationError as ValidationError6 } from "@spfn/core/errors";
8620
+ import { runInTransaction, onAfterCommit } from "@spfn/core/db";
8621
+ async function oauthNativeService(params) {
8622
+ const oauthProvider = getOAuthProvider(params.provider);
8623
+ if (!oauthProvider?.verifyNativeIdToken) {
8624
+ throw new ValidationError6({
8625
+ message: `Provider '${params.provider}' does not support native id_token sign-in.`
8626
+ });
8627
+ }
8628
+ const identity = await oauthProvider.verifyNativeIdToken(params.idToken, { nonce: params.nonce });
8629
+ if (params.profile?.name && !identity.name) {
8630
+ identity.name = params.profile.name;
8631
+ }
8632
+ return persistNativeLogin(identity, params);
8633
+ }
8634
+ async function persistNativeLogin(identity, params) {
8635
+ return runInTransaction(async () => {
8636
+ const existing = await socialAccountsRepository.findByProviderAndProviderId(
8637
+ params.provider,
8638
+ identity.providerUserId
8639
+ );
8640
+ let userId;
8641
+ let isNewUser = false;
8642
+ if (existing) {
8643
+ userId = existing.userId;
8644
+ } else {
8645
+ const result = await createOrLinkUser(params.provider, identity);
8646
+ userId = result.userId;
8647
+ isNewUser = result.isNewUser;
8648
+ }
8649
+ await registerPublicKeyService({
8650
+ userId,
8651
+ keyId: params.keyId,
8652
+ publicKey: params.publicKey,
8653
+ fingerprint: params.fingerprint,
8654
+ algorithm: params.algorithm
8655
+ });
8656
+ await updateLastLoginService(userId);
8657
+ const eventPayload = {
8658
+ userId: String(userId),
8659
+ provider: params.provider,
8660
+ email: identity.email || void 0,
8661
+ metadata: params.metadata
8662
+ };
8663
+ onAfterCommit(() => (isNewUser ? authRegisterEvent : authLoginEvent).emit(eventPayload));
8664
+ return { userId: String(userId), keyId: params.keyId, isNewUser };
8665
+ }, { context: "auth:oauth-native" });
8666
+ }
8667
+
8487
8668
  // src/server/routes/auth/index.ts
8488
8669
  init_esm();
8489
8670
  import { Transactional } from "@spfn/core/db";
@@ -8975,6 +9156,7 @@ function extractOTTHeader(header) {
8975
9156
  // src/server/routes/invitations/index.ts
8976
9157
  init_types();
8977
9158
  init_esm();
9159
+ import { Transactional as Transactional2 } from "@spfn/core/db";
8978
9160
  import { defineRouter as defineRouter2, route as route2 } from "@spfn/core/route";
8979
9161
  var INVITATION_STATUSES2 = ["pending", "accepted", "expired", "cancelled"];
8980
9162
  var getInvitation = route2.get("/_auth/invitations/:token").input({
@@ -9022,7 +9204,7 @@ var acceptInvitation2 = route2.post("/_auth/invitations/accept").input({
9022
9204
  fingerprint: Type.String({ description: "Key fingerprint" }),
9023
9205
  algorithm: Type.Union(KEY_ALGORITHM.map((algo) => Type.Literal(algo)), { description: "Signature algorithm" })
9024
9206
  })
9025
- }).skip(["auth"]).handler(async (c) => {
9207
+ }).use([Transactional2()]).skip(["auth"]).handler(async (c) => {
9026
9208
  const { body } = await c.data();
9027
9209
  return await acceptInvitation({
9028
9210
  token: body.token,
@@ -9238,8 +9420,8 @@ var userRouter = defineRouter3({
9238
9420
  // src/server/routes/oauth/index.ts
9239
9421
  init_esm();
9240
9422
  init_types();
9241
- import { Transactional as Transactional2 } from "@spfn/core/db";
9242
- import { ValidationError as ValidationError4 } from "@spfn/core/errors";
9423
+ import { Transactional as Transactional3 } from "@spfn/core/db";
9424
+ import { ValidationError as ValidationError7 } from "@spfn/core/errors";
9243
9425
  import { defineRouter as defineRouter4, route as route4 } from "@spfn/core/route";
9244
9426
  var providerParams = Type.Object({
9245
9427
  provider: Type.Union(SOCIAL_PROVIDERS.map((p) => Type.Literal(p)), {
@@ -9275,7 +9457,7 @@ var oauthGoogleCallback = route4.get("/_auth/oauth/google/callback").input({
9275
9457
  description: "Error description from Google"
9276
9458
  }))
9277
9459
  })
9278
- }).use([Transactional2()]).skip(["auth"]).handler(async (c) => {
9460
+ }).use([Transactional3()]).skip(["auth"]).handler(async (c) => {
9279
9461
  const { query } = await c.data();
9280
9462
  if (query.error) {
9281
9463
  const errorMessage = query.error_description || query.error;
@@ -9342,10 +9524,10 @@ var getGoogleOAuthUrl = route4.post("/_auth/oauth/google/url").input({
9342
9524
  }).skip(["auth"]).handler(async (c) => {
9343
9525
  const { body } = await c.data();
9344
9526
  if (!isGoogleOAuthEnabled()) {
9345
- throw new ValidationError4({ message: "Google OAuth is not configured" });
9527
+ throw new ValidationError7({ message: "Google OAuth is not configured" });
9346
9528
  }
9347
9529
  if (!body.state) {
9348
- throw new ValidationError4({
9530
+ throw new ValidationError7({
9349
9531
  message: "OAuth state is required. Ensure the OAuth interceptor is configured."
9350
9532
  });
9351
9533
  }
@@ -9397,7 +9579,7 @@ var oauthProviderCallback = route4.get("/_auth/oauth/:provider/callback").input(
9397
9579
  description: "Error description from provider"
9398
9580
  }))
9399
9581
  })
9400
- }).use([Transactional2()]).skip(["auth"]).handler(async (c) => {
9582
+ }).use([Transactional3()]).skip(["auth"]).handler(async (c) => {
9401
9583
  const { params, query } = await c.data();
9402
9584
  if (query.error) {
9403
9585
  const errorMessage = query.error_description || query.error;
@@ -9432,12 +9614,36 @@ var getProviderOAuthUrl = route4.post("/_auth/oauth/:provider/url").input({
9432
9614
  const { params, body } = await c.data();
9433
9615
  const provider = requireEnabledProvider(params.provider);
9434
9616
  if (!body.state) {
9435
- throw new ValidationError4({
9617
+ throw new ValidationError7({
9436
9618
  message: "OAuth state is required. Ensure the OAuth interceptor is configured."
9437
9619
  });
9438
9620
  }
9439
9621
  return { authUrl: provider.getAuthUrl(body.state) };
9440
9622
  });
9623
+ var oauthNative = route4.post("/_auth/oauth/:provider/native").input({
9624
+ params: providerParams,
9625
+ body: Type.Object({
9626
+ idToken: Type.String({ description: "id_token from native/web social SDK" }),
9627
+ nonce: Type.String({ description: "Raw nonce used when requesting the id_token" }),
9628
+ publicKey: Type.String({ description: "Client public key (Base64 DER)" }),
9629
+ keyId: Type.String({ description: "Key identifier (UUID)" }),
9630
+ fingerprint: Type.String({ description: "Key fingerprint (SHA-256 hex)" }),
9631
+ algorithm: Type.Union(KEY_ALGORITHM.map((a) => Type.Literal(a)), {
9632
+ description: "Key algorithm (ES256 or RS256)"
9633
+ }),
9634
+ profile: Type.Optional(Type.Object({
9635
+ name: Type.Optional(Type.String())
9636
+ }, {
9637
+ description: "Optional profile. Apple provides name only on first sign-in."
9638
+ })),
9639
+ metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown(), {
9640
+ description: "Custom metadata passed to auth events (e.g. referral code, UTM params)"
9641
+ }))
9642
+ })
9643
+ }).skip(["auth"]).handler(async (c) => {
9644
+ const { params, body } = await c.data();
9645
+ return await oauthNativeService({ provider: params.provider, ...body });
9646
+ });
9441
9647
  var oauthRouter = defineRouter4({
9442
9648
  oauthGoogleStart,
9443
9649
  oauthGoogleCallback,
@@ -9447,7 +9653,8 @@ var oauthRouter = defineRouter4({
9447
9653
  oauthFinalize,
9448
9654
  oauthProviderStart,
9449
9655
  oauthProviderCallback,
9450
- getProviderOAuthUrl
9656
+ getProviderOAuthUrl,
9657
+ oauthNative
9451
9658
  });
9452
9659
 
9453
9660
  // src/server/routes/admin/index.ts
@@ -9570,6 +9777,7 @@ var mainAuthRouter = defineRouter5({
9570
9777
  oauthProviderStart,
9571
9778
  oauthProviderCallback,
9572
9779
  getProviderOAuthUrl,
9780
+ oauthNative,
9573
9781
  // Invitation routes
9574
9782
  getInvitation,
9575
9783
  acceptInvitation: acceptInvitation2,
@@ -9700,10 +9908,10 @@ function shouldRotateKey(createdAt, rotationDays = 90) {
9700
9908
 
9701
9909
  // src/server/lib/session.ts
9702
9910
  import * as jose2 from "jose";
9703
- import { env as env10 } from "@spfn/auth/config";
9911
+ import { env as env12 } from "@spfn/auth/config";
9704
9912
  import { env as coreEnv } from "@spfn/core/config";
9705
9913
  async function getSessionSecretKey() {
9706
- const secret = env10.SPFN_AUTH_SESSION_SECRET;
9914
+ const secret = env12.SPFN_AUTH_SESSION_SECRET;
9707
9915
  const encoder = new TextEncoder();
9708
9916
  const data = encoder.encode(secret);
9709
9917
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
@@ -9785,14 +9993,14 @@ async function shouldRefreshSession(jwt4, thresholdHours = 24) {
9785
9993
  }
9786
9994
 
9787
9995
  // src/server/setup.ts
9788
- import { env as env11 } from "@spfn/auth/config";
9996
+ import { env as env13 } from "@spfn/auth/config";
9789
9997
  import { getRoleByName as getRoleByName2 } from "@spfn/auth/server";
9790
9998
  init_repositories();
9791
9999
  function parseAdminAccounts() {
9792
10000
  const accounts = [];
9793
- if (env11.SPFN_AUTH_ADMIN_ACCOUNTS) {
10001
+ if (env13.SPFN_AUTH_ADMIN_ACCOUNTS) {
9794
10002
  try {
9795
- const accountsJson = env11.SPFN_AUTH_ADMIN_ACCOUNTS;
10003
+ const accountsJson = env13.SPFN_AUTH_ADMIN_ACCOUNTS;
9796
10004
  const parsed = JSON.parse(accountsJson);
9797
10005
  if (!Array.isArray(parsed)) {
9798
10006
  authLogger.setup.error("\u274C SPFN_AUTH_ADMIN_ACCOUNTS must be an array");
@@ -9819,11 +10027,11 @@ function parseAdminAccounts() {
9819
10027
  return accounts;
9820
10028
  }
9821
10029
  }
9822
- const adminEmails = env11.SPFN_AUTH_ADMIN_EMAILS;
10030
+ const adminEmails = env13.SPFN_AUTH_ADMIN_EMAILS;
9823
10031
  if (adminEmails) {
9824
10032
  const emails = adminEmails.split(",").map((s) => s.trim());
9825
- const passwords = (env11.SPFN_AUTH_ADMIN_PASSWORDS || "").split(",").map((s) => s.trim());
9826
- const roles2 = (env11.SPFN_AUTH_ADMIN_ROLES || "").split(",").map((s) => s.trim());
10033
+ const passwords = (env13.SPFN_AUTH_ADMIN_PASSWORDS || "").split(",").map((s) => s.trim());
10034
+ const roles2 = (env13.SPFN_AUTH_ADMIN_ROLES || "").split(",").map((s) => s.trim());
9827
10035
  if (passwords.length !== emails.length) {
9828
10036
  authLogger.setup.error("\u274C SPFN_AUTH_ADMIN_EMAILS and SPFN_AUTH_ADMIN_PASSWORDS length mismatch");
9829
10037
  return accounts;
@@ -9845,8 +10053,8 @@ function parseAdminAccounts() {
9845
10053
  }
9846
10054
  return accounts;
9847
10055
  }
9848
- const adminEmail = env11.SPFN_AUTH_ADMIN_EMAIL;
9849
- const adminPassword = env11.SPFN_AUTH_ADMIN_PASSWORD;
10056
+ const adminEmail = env13.SPFN_AUTH_ADMIN_EMAIL;
10057
+ const adminPassword = env13.SPFN_AUTH_ADMIN_PASSWORD;
9850
10058
  if (adminEmail && adminPassword) {
9851
10059
  accounts.push({
9852
10060
  email: adminEmail,
@@ -9952,6 +10160,7 @@ export {
9952
10160
  VerificationPurposeSchema,
9953
10161
  acceptInvitation,
9954
10162
  addPermissionToRole,
10163
+ appleProvider,
9955
10164
  authLogger,
9956
10165
  authLoginEvent,
9957
10166
  authMetadata,
@@ -10031,6 +10240,7 @@ export {
10031
10240
  loginService,
10032
10241
  logoutService,
10033
10242
  oauthCallbackService,
10243
+ oauthNativeService,
10034
10244
  oauthStartService,
10035
10245
  oneTimeTokenAuth,
10036
10246
  optionalAuth,
@@ -10082,6 +10292,7 @@ export {
10082
10292
  verificationCodesRepository,
10083
10293
  verifyClientToken,
10084
10294
  verifyCodeService,
10295
+ verifyIdToken,
10085
10296
  verifyKeyFingerprint,
10086
10297
  verifyOAuthState,
10087
10298
  verifyOneTimeTokenService,