@vunexa/lixa 0.0.1-alpha.26 → 0.0.1-alpha.28

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
@@ -545,6 +545,200 @@ const strategy: SessionStrategy = {
545
545
  };
546
546
  ```
547
547
 
548
+ ## User Info Utilities
549
+
550
+ Lixa provides utilities to extract user information from OAuth tokens, making it easier to work with user data across different providers.
551
+
552
+ ### `extractUserInfo()`
553
+
554
+ High-level function that automatically extracts user information from OAuth token data:
555
+
556
+ ```typescript
557
+ import { extractUserInfo, type UserInfo } from "@vunexa/lixa";
558
+
559
+ // In your session strategy
560
+ const sessionStrategy = {
561
+ createSession: async (tokenData) => {
562
+ // Automatically extracts user info from ID token or fetches from API
563
+ const { userInfo, provider } = await extractUserInfo(
564
+ tokenData,
565
+ providerConfig.userInfoEndpoint, // Optional: from IProvider
566
+ 'google' // Optional: provider name for error messages
567
+ );
568
+
569
+ console.log(`User ${userInfo.email} authenticated via ${provider}`);
570
+
571
+ // Create user in database
572
+ const user = await db.users.upsert({
573
+ email: userInfo.email,
574
+ name: userInfo.name,
575
+ givenName: userInfo.given_name,
576
+ familyName: userInfo.family_name,
577
+ picture: userInfo.picture,
578
+ });
579
+
580
+ return {
581
+ token: generateSessionId(),
582
+ raw: { ...tokenData, userId: user.id }
583
+ };
584
+ }
585
+ };
586
+ ```
587
+
588
+ **Parameters:**
589
+ - `tokenData` (OAuthTokenResponse) - OAuth token response from provider
590
+ - `userInfoEndpoint` (string, optional) - Provider's userinfo endpoint URL (required if no ID token)
591
+ - `providerName` (string, optional) - Provider name for error messages
592
+
593
+ **Returns:**
594
+ - `{ userInfo: UserInfo, provider: string }` - User information and detected provider name
595
+
596
+ **Behavior:**
597
+ 1. If ID token present: Decodes JWT and extracts user info
598
+ 2. If only access token: Fetches from userinfo endpoint
599
+ 3. Provider detection: From ID token issuer, token data, or parameter
600
+ 4. Throws clear errors if provider cannot be determined
601
+
602
+ ### `decodeIdToken()`
603
+
604
+ Decode JWT ID tokens to extract user information:
605
+
606
+ ```typescript
607
+ import { decodeIdToken, type UserInfo } from "@vunexa/lixa";
608
+
609
+ const userInfo: UserInfo = decodeIdToken(tokenData.id_token);
610
+ console.log(userInfo.email, userInfo.name);
611
+ ```
612
+
613
+ **Use case:** When you know the provider returns an ID token (OIDC providers like Google)
614
+
615
+ ### `fetchUserInfo()`
616
+
617
+ Fetch user information from a provider's userinfo endpoint:
618
+
619
+ ```typescript
620
+ import { fetchUserInfo, type UserInfo } from "@vunexa/lixa";
621
+
622
+ const userInfo: UserInfo = await fetchUserInfo(
623
+ tokenData.access_token,
624
+ 'https://www.googleapis.com/oauth2/v2/userinfo',
625
+ 'google' // Optional: for error messages
626
+ );
627
+ ```
628
+
629
+ **Use case:** When you need to fetch user info from the API (OAuth-only providers like GitHub, or when ID token is not available)
630
+
631
+ ### `determineProviderFromIssuer()`
632
+
633
+ Detect OAuth provider from ID token issuer field:
634
+
635
+ ```typescript
636
+ import { determineProviderFromIssuer, decodeIdToken } from "@vunexa/lixa";
637
+
638
+ const userInfo = decodeIdToken(tokenData.id_token);
639
+ const provider = determineProviderFromIssuer(userInfo);
640
+ // Returns: 'google', 'github', or null if unknown
641
+ ```
642
+
643
+ **Supported providers:**
644
+ - Google: Detects `accounts.google.com` in issuer
645
+ - GitHub: Detects `github` in issuer
646
+ - Returns `null` for unknown issuers
647
+
648
+ ### `UserInfo` Type
649
+
650
+ Standard user information structure across all providers:
651
+
652
+ ```typescript
653
+ interface UserInfo {
654
+ email: string; // Required: User's email address
655
+ id?: string; // Optional: Provider-specific user ID
656
+ sub?: string; // Optional: Subject identifier (OIDC)
657
+ given_name?: string; // Optional: First name
658
+ family_name?: string; // Optional: Last name
659
+ name?: string; // Optional: Full name
660
+ picture?: string; // Optional: Profile picture URL
661
+ email_verified?: boolean; // Optional: Email verification status
662
+ iss?: string; // Optional: Token issuer (OIDC)
663
+ }
664
+ ```
665
+
666
+ ### Complete Example with User Info Utilities
667
+
668
+ ```typescript
669
+ import { Lixa, extractUserInfo, type UserInfo } from "@vunexa/lixa";
670
+ import { GoogleProvider, GithubProvider } from "@vunexa/lixa-providers";
671
+
672
+ const lixa = new Lixa({
673
+ providers: {
674
+ google: {
675
+ provider: new GoogleProvider(),
676
+ clientId: process.env.GOOGLE_CLIENT_ID!,
677
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
678
+ redirectUri: "https://yourapp.com/auth/google/callback",
679
+ scopes: ["openid", "email", "profile"],
680
+ },
681
+ github: {
682
+ provider: new GithubProvider(),
683
+ clientId: process.env.GITHUB_CLIENT_ID!,
684
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
685
+ redirectUri: "https://yourapp.com/auth/github/callback",
686
+ scopes: ["user:email"],
687
+ }
688
+ },
689
+
690
+ sessionStrategy: {
691
+ createSession: async (tokenData) => {
692
+ // Extract user info - works for both Google (ID token) and GitHub (API fetch)
693
+ const { userInfo, provider } = await extractUserInfo(tokenData);
694
+
695
+ console.log(`User ${userInfo.email} authenticated via ${provider}`);
696
+
697
+ // Create or update user in database
698
+ const user = await db.users.upsert({
699
+ email: userInfo.email,
700
+ name: userInfo.name || `${userInfo.given_name} ${userInfo.family_name}`.trim(),
701
+ givenName: userInfo.given_name,
702
+ familyName: userInfo.family_name,
703
+ picture: userInfo.picture,
704
+ emailVerified: userInfo.email_verified,
705
+ });
706
+
707
+ // Create session
708
+ const sessionId = generateUniqueId();
709
+ await db.sessions.create({
710
+ id: sessionId,
711
+ userId: user.id,
712
+ provider,
713
+ accessToken: tokenData.access_token,
714
+ refreshToken: tokenData.refresh_token,
715
+ expiresAt: tokenData.expires_in
716
+ ? new Date(Date.now() + tokenData.expires_in * 1000)
717
+ : null,
718
+ });
719
+
720
+ return {
721
+ token: sessionId,
722
+ raw: {
723
+ ...tokenData,
724
+ userId: user.id,
725
+ provider,
726
+ }
727
+ };
728
+ }
729
+ }
730
+ });
731
+ ```
732
+
733
+ ### Benefits of User Info Utilities
734
+
735
+ ✅ **Provider-agnostic** - Works with any OAuth provider
736
+ ✅ **Automatic detection** - Determines provider from token data
737
+ ✅ **Type-safe** - Full TypeScript support with UserInfo interface
738
+ ✅ **Flexible** - Supports both ID token and API fetching
739
+ ✅ **Error handling** - Clear error messages when provider cannot be determined
740
+ ✅ **Uses IProvider** - Leverages userInfoEndpoint from provider configuration
741
+
548
742
  ## API Reference
549
743
 
550
744
  ### `Lixa` Class
@@ -21,6 +21,13 @@
21
21
  */
22
22
  declare type ConfiguredProviderKey<T extends LixaConfig<Record<string, ProviderConfig>>> = keyof T['providers'];
23
23
 
24
+ /**
25
+ * Decode JWT ID token to extract user information
26
+ *
27
+ * @public
28
+ */
29
+ export declare function decodeIdToken(idToken: string): UserInfo;
30
+
24
31
  /**
25
32
  * Default session strategy that works with any OAuth provider.
26
33
  * Extracts common token information and creates a standardized session.
@@ -33,11 +40,80 @@ export declare class DefaultSessionStrategy implements SessionStrategy {
33
40
  * Handles common OAuth token formats and extracts the access token.
34
41
  *
35
42
  * @param tokenData - The token data received from the OAuth provider
43
+ * @param providerMetadata - Provider metadata (not used in default implementation)
36
44
  * @returns A Promise that resolves to a Session object
37
45
  */
38
- createSession(tokenData: OAuthTokenResponse): Promise<Session>;
46
+ createSession(tokenData: OAuthTokenResponse, providerMetadata: ProviderMetadata): Promise<Session>;
39
47
  }
40
48
 
49
+ /**
50
+ * Determine OAuth provider from ID token issuer
51
+ *
52
+ * @public
53
+ */
54
+ export declare function determineProviderFromIssuer(userInfo: UserInfo): string | null;
55
+
56
+ /**
57
+ * Extract user info from OAuth token data
58
+ *
59
+ * @param tokenData - OAuth token response from provider
60
+ * @param userInfoEndpoint - Optional userinfo endpoint URL (required if no ID token)
61
+ * @param providerName - Optional provider name for error messages
62
+ * @returns User info and detected provider name
63
+ *
64
+ * @remarks
65
+ * This function attempts to extract user information in the following order:
66
+ * 1. Decode ID token if present (preferred method)
67
+ * 2. Fetch from userinfo endpoint using access token (requires userInfoEndpoint parameter)
68
+ *
69
+ * Provider detection:
70
+ * - Primary: Extract from ID token issuer field
71
+ * - Fallback: Use provider field in token data (if present)
72
+ * - Fallback: Use providerName parameter
73
+ * - Throws error if provider cannot be determined
74
+ *
75
+ * @throws Error if no ID token or access token is available
76
+ * @throws Error if provider cannot be determined
77
+ * @throws Error if userInfoEndpoint is required but not provided
78
+ *
79
+ * @example
80
+ * With ID token (provider auto-detected):
81
+ * ```typescript
82
+ * const { userInfo, provider } = await extractUserInfo(tokenData);
83
+ * console.log(`User ${userInfo.email} authenticated via ${provider}`);
84
+ * ```
85
+ *
86
+ * @example
87
+ * Without ID token (requires userInfoEndpoint):
88
+ * ```typescript
89
+ * const { userInfo, provider } = await extractUserInfo(
90
+ * tokenData,
91
+ * 'https://api.example.com/user',
92
+ * 'custom'
93
+ * );
94
+ * ```
95
+ *
96
+ * @public
97
+ */
98
+ export declare function extractUserInfo(tokenData: OAuthTokenResponse, userInfoEndpoint?: string, providerName?: string): Promise<{
99
+ userInfo: UserInfo;
100
+ provider: string;
101
+ }>;
102
+
103
+ /**
104
+ * Fetch user info from OAuth provider's userinfo endpoint
105
+ *
106
+ * @param accessToken - OAuth access token
107
+ * @param userInfoEndpoint - The provider's userinfo endpoint URL
108
+ * @param providerName - Provider name for error messages (optional)
109
+ * @returns User information from the provider
110
+ *
111
+ * @throws Error if the request fails or response is invalid
112
+ *
113
+ * @public
114
+ */
115
+ export declare function fetchUserInfo(accessToken: string, userInfoEndpoint: string, providerName?: string): Promise<UserInfo>;
116
+
41
117
  /**
42
118
  * Interface for OAuth 2.0 and OpenID Connect provider implementations.
43
119
  *
@@ -694,6 +770,26 @@ export declare type ProviderConfig = {
694
770
  provider: IProvider;
695
771
  });
696
772
 
773
+ /**
774
+ * Provider metadata passed to session strategy.
775
+ * Contains provider name and endpoints for user info extraction.
776
+ *
777
+ * @public
778
+ */
779
+ export declare interface ProviderMetadata {
780
+ /** The provider name (e.g., 'google', 'github') */
781
+ name: string;
782
+ /** Provider endpoints */
783
+ endpoints: {
784
+ /** Authorization endpoint URL */
785
+ authorization: string;
786
+ /** Token endpoint URL */
787
+ token: string;
788
+ /** UserInfo endpoint URL */
789
+ userInfo: string;
790
+ };
791
+ }
792
+
697
793
  /**
698
794
  * Helper type to create a configuration with only registered providers.
699
795
  * Use this with Lixa.createConfig() for type safety.
@@ -867,24 +963,27 @@ export declare interface SessionDao {
867
963
  * @example
868
964
  * Custom session strategy with database integration:
869
965
  * ```typescript
870
- * interface CustomSessionData extends OAuthTokenResponse {
966
+ * interface CustomSessionData {
871
967
  * userId: string;
872
968
  * email: string;
969
+ * provider: string;
970
+ * accessToken: string;
971
+ * refreshToken?: string;
972
+ * expiresAt: number;
873
973
  * }
874
974
  *
875
975
  * class DatabaseSessionStrategy implements SessionStrategy {
876
976
  * constructor(private db: Database) {}
877
977
  *
878
- * async createSession(tokenData: OAuthTokenResponse): Promise<Session<CustomSessionData>> {
879
- * // Decode ID token for OIDC providers
880
- * const idToken = tokenData.id_token;
881
- * const payload = decodeJwt(idToken);
978
+ * async createSession(oauthContext: OAuthContext): Promise<Session<CustomSessionData>> {
979
+ * // User info is already extracted by Lixa!
980
+ * const { userInfo, provider, tokenData } = oauthContext;
882
981
  *
883
982
  * // Create or update user in database
884
983
  * const user = await this.db.users.upsert({
885
- * email: payload.email,
886
- * name: payload.name,
887
- * picture: payload.picture
984
+ * email: userInfo.email,
985
+ * name: userInfo.name,
986
+ * picture: userInfo.picture
888
987
  * });
889
988
  *
890
989
  * // Generate session ID
@@ -904,7 +1003,10 @@ export declare interface SessionDao {
904
1003
  * raw: {
905
1004
  * userId: user.id,
906
1005
  * email: user.email,
907
- * ...tokenData
1006
+ * provider,
1007
+ * accessToken: tokenData.access_token,
1008
+ * refreshToken: tokenData.refresh_token,
1009
+ * expiresAt: Date.now() + (tokenData.expires_in || 3600) * 1000
908
1010
  * }
909
1011
  * };
910
1012
  * }
@@ -918,14 +1020,14 @@ export declare interface SessionStrategy {
918
1020
  * Creates a session from OAuth token data.
919
1021
  *
920
1022
  * @param tokenData - The token data received from the OAuth provider's token endpoint
1023
+ * @param providerMetadata - Provider metadata including name and endpoints
921
1024
  * @returns A Promise that resolves to a Session object
922
1025
  *
923
1026
  * @remarks
924
1027
  * This method is called after successfully exchanging the authorization code
925
- * for tokens. The tokenData parameter contains the raw response from the
926
- * provider's token endpoint.
1028
+ * for tokens. You receive:
927
1029
  *
928
- * Common token data fields:
1030
+ * Token Data:
929
1031
  * - access_token: OAuth access token
930
1032
  * - refresh_token: OAuth refresh token (optional)
931
1033
  * - expires_in: Token expiration time in seconds
@@ -933,6 +1035,28 @@ export declare interface SessionStrategy {
933
1035
  * - id_token: OpenID Connect ID token (for OIDC providers)
934
1036
  * - scope: Granted scopes
935
1037
  *
1038
+ * Provider Metadata:
1039
+ * - name: The provider name (e.g., 'google', 'github')
1040
+ * - endpoints: Provider endpoints (authorization, token, userInfo)
1041
+ *
1042
+ * The providerMetadata.endpoints.userInfo can be used with extractUserInfo():
1043
+ * ```typescript
1044
+ * import { extractUserInfo } from '@vunexa/lixa';
1045
+ *
1046
+ * const { userInfo } = await extractUserInfo(
1047
+ * tokenData,
1048
+ * providerMetadata.endpoints.userInfo,
1049
+ * providerMetadata.name
1050
+ * );
1051
+ * ```
1052
+ *
1053
+ * Your session strategy should:
1054
+ * 1. Extract user info (using extractUserInfo or decode ID token)
1055
+ * 2. Create or lookup users in your database
1056
+ * 3. Generate session identifiers
1057
+ * 4. Store session data as needed
1058
+ * 5. Return a Session object with token and raw data
1059
+ *
936
1060
  * @throws \{Error\} If session creation fails (e.g., database error, invalid token)
937
1061
  *
938
1062
  * @example
@@ -945,8 +1069,35 @@ export declare interface SessionStrategy {
945
1069
  * };
946
1070
  * }
947
1071
  * ```
1072
+ *
1073
+ * @example
1074
+ * Database integration with user info extraction:
1075
+ * ```typescript
1076
+ * async createSession(
1077
+ * tokenData: OAuthTokenResponse,
1078
+ * providerMetadata: ProviderMetadata
1079
+ * ): Promise<Session> {
1080
+ * // Extract user info from token or userinfo endpoint
1081
+ * const { userInfo } = await extractUserInfo(
1082
+ * tokenData,
1083
+ * providerMetadata.endpoints.userInfo,
1084
+ * providerMetadata.name
1085
+ * );
1086
+ *
1087
+ * // Create or update user in database
1088
+ * const user = await db.users.upsert({
1089
+ * email: userInfo.email,
1090
+ * name: userInfo.name
1091
+ * });
1092
+ *
1093
+ * return {
1094
+ * token: generateSessionId(),
1095
+ * raw: { userId: user.id, provider: providerMetadata.name, ...tokenData }
1096
+ * };
1097
+ * }
1098
+ * ```
948
1099
  */
949
- createSession(tokenData: OAuthTokenResponse): Promise<Session>;
1100
+ createSession(tokenData: OAuthTokenResponse, providerMetadata: ProviderMetadata): Promise<Session>;
950
1101
  }
951
1102
 
952
1103
  /**
@@ -1096,4 +1247,21 @@ export declare interface StateData {
1096
1247
  createdAt: number;
1097
1248
  }
1098
1249
 
1250
+ /**
1251
+ * User information extracted from OAuth provider
1252
+ *
1253
+ * @public
1254
+ */
1255
+ export declare interface UserInfo {
1256
+ email: string;
1257
+ id?: string | undefined;
1258
+ sub?: string | undefined;
1259
+ given_name?: string | undefined;
1260
+ family_name?: string | undefined;
1261
+ name?: string | undefined;
1262
+ picture?: string | undefined;
1263
+ email_verified?: boolean | undefined;
1264
+ iss?: string | undefined;
1265
+ }
1266
+
1099
1267
  export { }
package/dist/index.cjs CHANGED
@@ -31,7 +31,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  DefaultSessionStrategy: () => DefaultSessionStrategy,
34
- Lixa: () => Lixa
34
+ Lixa: () => Lixa,
35
+ decodeIdToken: () => decodeIdToken,
36
+ determineProviderFromIssuer: () => determineProviderFromIssuer,
37
+ extractUserInfo: () => extractUserInfo,
38
+ fetchUserInfo: () => fetchUserInfo
35
39
  });
36
40
  module.exports = __toCommonJS(src_exports);
37
41
 
@@ -84,9 +88,10 @@ var DefaultSessionStrategy = class {
84
88
  * Handles common OAuth token formats and extracts the access token.
85
89
  *
86
90
  * @param tokenData - The token data received from the OAuth provider
91
+ * @param providerMetadata - Provider metadata (not used in default implementation)
87
92
  * @returns A Promise that resolves to a Session object
88
93
  */
89
- async createSession(tokenData) {
94
+ async createSession(tokenData, providerMetadata) {
90
95
  if (!tokenData.access_token || typeof tokenData.access_token !== "string") {
91
96
  throw new Error("No valid access token found in OAuth response");
92
97
  }
@@ -545,7 +550,15 @@ var Lixa = class _Lixa {
545
550
  );
546
551
  this.log("INFO", "Token", "Token exchange successful");
547
552
  this.log("INFO", "Session", "Creating user session");
548
- const session = await this.sessionStrategy.createSession(tokens);
553
+ const providerMetadata = {
554
+ name: providerType,
555
+ endpoints: {
556
+ authorization: providerImpl.authorizationEndpoint,
557
+ token: providerImpl.tokenEndpoint,
558
+ userInfo: providerImpl.userInfoEndpoint
559
+ }
560
+ };
561
+ const session = await this.sessionStrategy.createSession(tokens, providerMetadata);
549
562
  const sessionId = (0, import_crypto.randomBytes)(32).toString("hex");
550
563
  this.log("INFO", "Session", "Storing session", { sessionId });
551
564
  await this.sesionDao.saveSession(sessionId, session, 86400);
@@ -601,9 +614,108 @@ var Lixa = class _Lixa {
601
614
  return void 0;
602
615
  }
603
616
  };
617
+
618
+ // src/utils/user-info.ts
619
+ function decodeIdToken(idToken) {
620
+ const parts = idToken.split(".");
621
+ if (parts.length !== 3) {
622
+ throw new Error("Invalid ID token format: expected 3 parts separated by dots");
623
+ }
624
+ const base64Payload = parts[1];
625
+ if (!base64Payload) {
626
+ throw new Error("Invalid ID token: missing payload section");
627
+ }
628
+ const payload = Buffer.from(base64Payload, "base64").toString();
629
+ try {
630
+ return JSON.parse(payload);
631
+ } catch (error) {
632
+ throw new Error("Invalid ID token: failed to parse payload JSON");
633
+ }
634
+ }
635
+ function determineProviderFromIssuer(userInfo) {
636
+ if (!userInfo.iss) {
637
+ return null;
638
+ }
639
+ const issuer = userInfo.iss.toLowerCase();
640
+ if (issuer.includes("accounts.google.com")) {
641
+ return "google";
642
+ }
643
+ if (issuer.includes("github")) {
644
+ return "github";
645
+ }
646
+ return null;
647
+ }
648
+ async function fetchUserInfo(accessToken, userInfoEndpoint, providerName) {
649
+ const response = await fetch(userInfoEndpoint, {
650
+ headers: {
651
+ Authorization: `Bearer ${accessToken}`,
652
+ Accept: "application/json"
653
+ }
654
+ });
655
+ if (!response.ok) {
656
+ const providerLabel = providerName ? ` from ${providerName}` : "";
657
+ throw new Error(`Failed to fetch user info${providerLabel}: ${response.status} ${response.statusText}`);
658
+ }
659
+ const data = await response.json();
660
+ if (!data || typeof data !== "object" || !("email" in data) || typeof data.email !== "string") {
661
+ const providerLabel = providerName ? ` from ${providerName}` : "";
662
+ throw new Error(`Invalid user info response${providerLabel}: missing or invalid email`);
663
+ }
664
+ return {
665
+ email: data.email,
666
+ id: "id" in data ? String(data.id) : void 0,
667
+ sub: "sub" in data ? String(data.sub) : void 0,
668
+ given_name: "given_name" in data ? String(data.given_name) : void 0,
669
+ family_name: "family_name" in data ? String(data.family_name) : void 0,
670
+ name: "name" in data ? String(data.name) : void 0,
671
+ picture: "picture" in data ? String(data.picture) : void 0,
672
+ email_verified: "email_verified" in data ? Boolean(data.email_verified) : void 0,
673
+ iss: "iss" in data ? String(data.iss) : void 0
674
+ };
675
+ }
676
+ async function extractUserInfo(tokenData, userInfoEndpoint, providerName) {
677
+ let userInfo;
678
+ let provider = null;
679
+ if (tokenData.id_token) {
680
+ userInfo = decodeIdToken(tokenData.id_token);
681
+ provider = determineProviderFromIssuer(userInfo);
682
+ if (!provider && providerName) {
683
+ provider = providerName;
684
+ }
685
+ } else if (tokenData.access_token) {
686
+ if ("provider" in tokenData && typeof tokenData.provider === "string") {
687
+ provider = tokenData.provider;
688
+ } else if (providerName) {
689
+ provider = providerName;
690
+ }
691
+ if (!provider) {
692
+ throw new Error(
693
+ "Cannot determine OAuth provider: No ID token with issuer information, no provider field in token data, and no providerName provided. Unable to fetch user info."
694
+ );
695
+ }
696
+ if (!userInfoEndpoint) {
697
+ throw new Error(
698
+ `Cannot fetch user info for provider '${provider}': No ID token available and no userInfoEndpoint provided. Either ensure the provider returns an ID token or provide the userInfoEndpoint parameter.`
699
+ );
700
+ }
701
+ userInfo = await fetchUserInfo(tokenData.access_token, userInfoEndpoint, provider);
702
+ } else {
703
+ throw new Error("No ID token or access token available to fetch user info");
704
+ }
705
+ if (!provider) {
706
+ throw new Error(
707
+ "Cannot determine OAuth provider: ID token issuer not recognized and no provider name provided."
708
+ );
709
+ }
710
+ return { userInfo, provider };
711
+ }
604
712
  // Annotate the CommonJS export names for ESM import in node:
605
713
  0 && (module.exports = {
606
714
  DefaultSessionStrategy,
607
- Lixa
715
+ Lixa,
716
+ decodeIdToken,
717
+ determineProviderFromIssuer,
718
+ extractUserInfo,
719
+ fetchUserInfo
608
720
  });
609
721
  //# sourceMappingURL=index.cjs.map