@rudderjs/socialite 1.0.1 → 2.0.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.
package/README.md CHANGED
@@ -27,11 +27,10 @@ export default {
27
27
  },
28
28
  }
29
29
 
30
- // bootstrap/providers.ts
31
- import { SocialiteProvider } from '@rudderjs/socialite'
32
- export default [SocialiteProvider]
33
30
  ```
34
31
 
32
+ `SocialiteProvider` is picked up by [auto-discovery](https://github.com/rudderjs/rudder/blob/main/docs/guide/service-providers.md#auto-discovery) — `pnpm rudder providers:discover` is all that's needed.
33
+
35
34
  ## Usage
36
35
 
37
36
  ```ts
@@ -64,6 +63,50 @@ Route.get('/auth/github/callback', async (req) => {
64
63
  })
65
64
  ```
66
65
 
66
+ ## CSRF state — stateful by default
67
+
68
+ Socialite mints a CSPRNG `state` parameter on every redirect, persists it
69
+ on the session, and validates the `state` returned in the callback before
70
+ exchanging the code. A mismatch (or a missing session) throws
71
+ `InvalidStateException` — same defense Laravel Socialite ships out of the
72
+ box. No code changes needed: the routes above are already protected, as
73
+ long as `@rudderjs/session`'s middleware is mounted (auto-installed on
74
+ the `web` group).
75
+
76
+ For flows that legitimately can't reach the session — mobile clients,
77
+ machine-to-machine token grants, server-side OAuth where the round-trip
78
+ happens entirely off-browser — opt out per call:
79
+
80
+ ```ts
81
+ Route.get('/auth/github', () => {
82
+ return Socialite.driver('github').stateless().redirect()
83
+ })
84
+
85
+ Route.get('/auth/github/callback', async (req) => {
86
+ const user = await Socialite.driver('github').stateless().user(req)
87
+ // …
88
+ })
89
+ ```
90
+
91
+ `InvalidStateException` is exported for `instanceof`-checks in your
92
+ exception handler:
93
+
94
+ ```ts
95
+ import { InvalidStateException } from '@rudderjs/socialite'
96
+
97
+ try {
98
+ await Socialite.driver('github').user(req)
99
+ } catch (err) {
100
+ if (err instanceof InvalidStateException) return abort(403, 'Auth failed.')
101
+ throw err
102
+ }
103
+ ```
104
+
105
+ State is namespaced per provider (`socialite_state:github`,
106
+ `socialite_state:google`, …) so concurrent OAuth flows on the same
107
+ session don't collide. State is one-time use — successful or failed
108
+ validation clears the slot, so a leaked value can't be replayed.
109
+
67
110
  ## Providers
68
111
 
69
112
  | Provider | Driver | Auth URL |
@@ -73,12 +116,46 @@ Route.get('/auth/github/callback', async (req) => {
73
116
  | Facebook | `facebook` | `facebook.com/v19.0/dialog/oauth` |
74
117
  | Apple | `apple` | `appleid.apple.com/auth/authorize` |
75
118
 
119
+ ### Sign-in-with-Apple — extra config
120
+
121
+ Apple's OAuth flow requires a freshly-signed ES256 JWT as `client_secret`
122
+ on every token exchange (a raw string is rejected with `invalid_client`).
123
+ Add three Apple-specific fields to your config:
124
+
125
+ ```ts
126
+ // config/socialite.ts
127
+ import { readFileSync } from 'node:fs'
128
+ import type { AppleSocialiteConfig } from '@rudderjs/socialite'
129
+
130
+ export default {
131
+ apple: {
132
+ clientId: Env.get('APPLE_CLIENT_ID', ''), // Service ID, e.g. com.example.app
133
+ redirectUrl: Env.get('APPLE_REDIRECT_URL', ''),
134
+ teamId: Env.get('APPLE_TEAM_ID', ''), // 10-char Team ID from developer.apple.com
135
+ keyId: Env.get('APPLE_KEY_ID', ''), // 10-char Key ID for the .p8
136
+ privateKey: readFileSync(Env.get('APPLE_PRIVATE_KEY_PATH', ''), 'utf8'),
137
+ clientSecret: '', // unused; left for type compat
138
+ } satisfies AppleSocialiteConfig,
139
+ }
140
+ ```
141
+
142
+ Download the `.p8` file once from the Apple Developer portal and either
143
+ read it from disk (as above) or pass its PEM contents directly. The
144
+ driver verifies returned `id_token`s against Apple's JWKS
145
+ (`https://appleid.apple.com/auth/keys`, cached for 1h) — signature, `iss`,
146
+ `aud`, and `exp` are all checked before any user data is trusted.
147
+
148
+ Apple's first-authorization callback POSTs the user's `name` once in the
149
+ form-post body. RudderJS reads it automatically when you pass the request
150
+ object to `user(req)`. Your route handler must include the `body` in the
151
+ request shape — `@rudderjs/server-hono` already does this.
152
+
76
153
  ## Custom Providers
77
154
 
78
155
  ```ts
79
- import { SocialiteProvider, SocialUser, Socialite } from '@rudderjs/socialite'
156
+ import { SocialiteDriver, SocialUser, Socialite } from '@rudderjs/socialite'
80
157
 
81
- class GitLabProvider extends SocialiteProvider {
158
+ class GitLabProvider extends SocialiteDriver {
82
159
  protected defaultScopes() { return ['read_user'] }
83
160
  protected authUrl() { return 'https://gitlab.com/oauth/authorize' }
84
161
  protected tokenUrl() { return 'https://gitlab.com/oauth/token' }
@@ -39,9 +39,11 @@ Route.get('/auth/github', () => {
39
39
  Route.get('/auth/github/callback', async (req) => {
40
40
  const socialUser = await Socialite.driver('github').user(req)
41
41
 
42
- // socialUser exposes: getId(), getName(), getEmail(), getAvatar(), getToken()
43
- const id = socialUser.getId()
44
- const email = socialUser.getEmail()
42
+ // socialUser methods: getId(), getName(), getEmail(), getAvatar(), getNickname(), getRaw()
43
+ // socialUser getters: .token, .refreshToken, .expiresIn
44
+ const id = socialUser.getId()
45
+ const email = socialUser.getEmail()
46
+ const accessToken = socialUser.token
45
47
 
46
48
  // Find or create a local user
47
49
  let user = await User.where('email', email).first()
@@ -58,31 +60,42 @@ Route.get('/auth/github/callback', async (req) => {
58
60
  ### Scopes + state
59
61
 
60
62
  ```ts
61
- Socialite.driver('github')
62
- .scopes(['user:email', 'read:org'])
63
- .with({ allow_signup: 'false' }) // extra query params
64
- .redirect()
63
+ // Replace defaults
64
+ Socialite.driver('github').setScopes(['user:email', 'read:org']).redirect()
65
+
66
+ // Or extend defaults — withScopes() merges, deduped
67
+ Socialite.driver('github').withScopes(['read:org']).redirect()
68
+
69
+ // Skip CSRF state (mobile / machine-to-machine flows that can't reach the session)
70
+ Socialite.driver('github').stateless().redirect()
65
71
  ```
66
72
 
67
- State (CSRF) is handled automatically — stored in the session and verified on callback.
73
+ State (CSRF) is handled automatically — stored in the session and verified on callback. To inject extra provider-specific query parameters (`prompt=consent`, Apple's `response_mode=form_post`, etc.), override `extraAuthParams()` on a custom driver subclass — there is no fluent `.with({...})` method.
68
74
 
69
75
  ### Custom providers
70
76
 
77
+ `SocialiteDriver` declares `authUrl`, `tokenUrl`, `userUrl`, `defaultScopes`, and `mapToUser` as abstract **methods** (not properties). Override each:
78
+
71
79
  ```ts
72
- import { Socialite, SocialiteDriver } from '@rudderjs/socialite'
80
+ import { Socialite, SocialiteDriver, SocialUser } from '@rudderjs/socialite'
73
81
 
74
82
  class DiscordDriver extends SocialiteDriver {
75
- protected authUrl = 'https://discord.com/api/oauth2/authorize'
76
- protected tokenUrl = 'https://discord.com/api/oauth2/token'
77
- protected userUrl = 'https://discord.com/api/users/@me'
78
-
79
- protected mapUser(raw: any) {
80
- return {
81
- id: raw.id,
82
- name: raw.username,
83
- email: raw.email,
84
- avatar: `https://cdn.discordapp.com/avatars/${raw.id}/${raw.avatar}.png`,
85
- }
83
+ protected defaultScopes() { return ['identify', 'email'] }
84
+ protected authUrl() { return 'https://discord.com/api/oauth2/authorize' }
85
+ protected tokenUrl() { return 'https://discord.com/api/oauth2/token' }
86
+ protected userUrl() { return 'https://discord.com/api/users/@me' }
87
+
88
+ protected mapToUser(raw: Record<string, unknown>, token: string, refreshToken: string | null): SocialUser {
89
+ return new SocialUser({
90
+ id: String(raw['id']),
91
+ name: (raw['username'] as string) ?? null,
92
+ email: (raw['email'] as string) ?? null,
93
+ avatar: raw['avatar'] ? `https://cdn.discordapp.com/avatars/${raw['id']}/${raw['avatar']}.png` : null,
94
+ nickname: null,
95
+ token,
96
+ refreshToken,
97
+ raw,
98
+ })
86
99
  }
87
100
  }
88
101
 
@@ -92,12 +105,18 @@ Socialite.extend('discord', (cfg) => new DiscordDriver(cfg))
92
105
  ### SocialUser interface
93
106
 
94
107
  ```ts
95
- socialUser.getId() // provider's user id
96
- socialUser.getName()
97
- socialUser.getEmail()
98
- socialUser.getAvatar()
99
- socialUser.getToken() // access token
100
- socialUser.getRaw() // full raw provider response
108
+ // Methods
109
+ socialUser.getId() // provider's user id (always string)
110
+ socialUser.getName() // string | null
111
+ socialUser.getEmail() // string | null
112
+ socialUser.getAvatar() // string | null
113
+ socialUser.getNickname() // string | null
114
+ socialUser.getRaw() // Record<string, unknown> — full raw provider response
115
+
116
+ // Getters (not methods)
117
+ socialUser.token // access token
118
+ socialUser.refreshToken // string | null
119
+ socialUser.expiresIn // number | null
101
120
  ```
102
121
 
103
122
  ## Common Pitfalls
package/dist/driver.d.ts CHANGED
@@ -4,10 +4,32 @@ export interface SocialiteDriverConfig {
4
4
  clientSecret: string;
5
5
  redirectUrl: string;
6
6
  scopes?: string[];
7
+ /** Per-request HTTP timeout in milliseconds (default 10_000). */
8
+ timeout?: number;
9
+ }
10
+ /** Detail attached to OAuth provider errors via `Error.cause`. */
11
+ export interface SocialiteHttpErrorCause {
12
+ status: number;
13
+ body: string;
14
+ }
15
+ /**
16
+ * Thrown when an OAuth callback's `state` parameter is missing, doesn't
17
+ * match the value the framework stored before redirect, or arrives without
18
+ * a session in context. Indicates a CSRF / state-fixation attempt — apps
19
+ * should treat as auth failure.
20
+ */
21
+ export declare class InvalidStateException extends Error {
22
+ constructor(message?: string);
23
+ }
24
+ /** Shape of the request object accepted by `user()` and `validateRequestState`. */
25
+ export interface SocialiteCallbackRequest {
26
+ query: Record<string, string>;
27
+ body?: unknown;
7
28
  }
8
29
  export declare abstract class SocialiteDriver {
9
30
  protected readonly config: SocialiteDriverConfig;
10
31
  protected scopes: string[];
32
+ private _stateless;
11
33
  constructor(config: SocialiteDriverConfig);
12
34
  /** Default scopes for this provider. */
13
35
  protected abstract defaultScopes(): string[];
@@ -19,14 +41,43 @@ export declare abstract class SocialiteDriver {
19
41
  protected abstract userUrl(): string;
20
42
  /** Parse the provider's user API response into a SocialUser. */
21
43
  protected abstract mapToUser(data: Record<string, unknown>, token: string, refreshToken: string | null): SocialUser;
44
+ /**
45
+ * Provider key used to namespace the session state slot. Defaults to the
46
+ * lowercase class name with a trailing `provider` stripped (e.g. `GitHubProvider`
47
+ * → `github`). Override on a subclass if a custom key is preferred.
48
+ */
49
+ protected providerName(): string;
22
50
  /** Add extra scopes. */
23
51
  withScopes(scopes: string[]): this;
24
52
  /** Set scopes (replacing defaults). */
25
53
  setScopes(scopes: string[]): this;
54
+ /**
55
+ * Disable state generation + validation (Laravel `->stateless()`).
56
+ *
57
+ * Use for OAuth flows that can't reach the session — e.g. mobile clients,
58
+ * machine-to-machine auth, or token grants where the round-trip happens
59
+ * entirely server-to-server. The default (stateful) generates a CSPRNG
60
+ * `state` on redirect, stores it in the session, and validates it on
61
+ * callback to prevent CSRF / state-fixation.
62
+ */
63
+ stateless(): this;
64
+ isStateless(): boolean;
65
+ /**
66
+ * Provider-specific extra params to merge into the authorize URL. Apple
67
+ * needs `response_mode=form_post`; other drivers may want `prompt=consent`
68
+ * etc. Override on subclasses — base returns `{}`.
69
+ */
70
+ protected extraAuthParams(): Record<string, string>;
26
71
  /** Get the redirect URL to the OAuth provider. */
27
72
  getRedirectUrl(state?: string): string;
28
73
  /** Redirect the response to the OAuth provider. */
29
74
  redirect(state?: string): Response;
75
+ /**
76
+ * Wrapper around `fetch` that injects an `AbortSignal.timeout` so a hung
77
+ * provider endpoint can't keep the request handler alive indefinitely.
78
+ * Subclasses (Apple, GitHub) call this for their own provider fetches.
79
+ */
80
+ protected fetchWithTimeout(input: Parameters<typeof fetch>[0], init?: RequestInit): Promise<Response>;
30
81
  /** Exchange the authorization code for an access token. */
31
82
  getAccessToken(code: string): Promise<{
32
83
  accessToken: string;
@@ -34,10 +85,32 @@ export declare abstract class SocialiteDriver {
34
85
  expiresIn: number | null;
35
86
  }>;
36
87
  /** Get the authenticated user from the OAuth callback. */
37
- user(codeOrRequest: string | {
38
- query: Record<string, string>;
39
- }): Promise<SocialUser>;
88
+ user(codeOrRequest: string | SocialiteCallbackRequest): Promise<SocialUser>;
40
89
  /** Get the user directly from an access token (e.g. for mobile apps). */
41
90
  getUserByToken(token: string, refreshToken?: string | null): Promise<SocialUser>;
91
+ private get stateKey();
92
+ /**
93
+ * Generate a CSPRNG state token, store it on the session, and return the
94
+ * value to embed in the authorize URL. Throws when no session is in
95
+ * context — the caller can opt out via `.stateless()`.
96
+ */
97
+ private generateAndStoreState;
98
+ /**
99
+ * Validate the `state` carried in a callback request against what was
100
+ * stored at redirect time. Pulls from `query.state` first, falling back
101
+ * to the request body's `state` (used by Apple's `form_post` callback).
102
+ * Always forgets the stored value after validation — the state is
103
+ * one-time use, so a leaked state can't be replayed.
104
+ */
105
+ protected validateRequestState(req: SocialiteCallbackRequest): void;
106
+ private extractState;
107
+ private constantTimeStringEqual;
108
+ /**
109
+ * Build an Error whose `message` carries only status + statusText (safe to
110
+ * surface in logs), with the response body attached on `cause` so callers
111
+ * that need it can still inspect — without leaking provider-echoed
112
+ * client_id / hints / PII into top-level error tracking.
113
+ */
114
+ protected httpError(prefix: string, res: Response): Promise<Error>;
42
115
  }
43
116
  //# sourceMappingURL=driver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAI7C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAM,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAG,MAAM,CAAA;IACpB,MAAM,CAAC,EAAO,MAAM,EAAE,CAAA;CACvB;AAED,8BAAsB,eAAe;IAGvB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAF5D,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAA;gBAEK,MAAM,EAAE,qBAAqB;IAI5D,wCAAwC;IACxC,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,MAAM,EAAE;IAE5C,2EAA2E;IAC3E,SAAS,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM;IAEpC,0EAA0E;IAC1E,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,MAAM;IAErC,wDAAwD;IACxD,SAAS,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM;IAEpC,gEAAgE;IAChE,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU;IAEnH,wBAAwB;IACxB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAKlC,uCAAuC;IACvC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAKjC,kDAAkD;IAClD,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAWtC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ;IAIlC,2DAA2D;IACrD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAmC3H,0DAA0D;IACpD,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAW1F,yEAAyE;IACnE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;CAgBvF"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
package/dist/driver.js CHANGED
@@ -1,10 +1,35 @@
1
+ import { randomBytes, timingSafeEqual } from 'node:crypto';
2
+ import { Session } from '@rudderjs/session';
3
+ const DEFAULT_TIMEOUT_MS = 10_000;
4
+ const STATE_BYTES = 20;
5
+ /**
6
+ * Thrown when an OAuth callback's `state` parameter is missing, doesn't
7
+ * match the value the framework stored before redirect, or arrives without
8
+ * a session in context. Indicates a CSRF / state-fixation attempt — apps
9
+ * should treat as auth failure.
10
+ */
11
+ export class InvalidStateException extends Error {
12
+ constructor(message = 'OAuth state mismatch — possible CSRF attack.') {
13
+ super(`[RudderJS Socialite] ${message}`);
14
+ this.name = 'InvalidStateException';
15
+ }
16
+ }
1
17
  export class SocialiteDriver {
2
18
  config;
3
19
  scopes;
20
+ _stateless = false;
4
21
  constructor(config) {
5
22
  this.config = config;
6
23
  this.scopes = config.scopes ?? this.defaultScopes();
7
24
  }
25
+ /**
26
+ * Provider key used to namespace the session state slot. Defaults to the
27
+ * lowercase class name with a trailing `provider` stripped (e.g. `GitHubProvider`
28
+ * → `github`). Override on a subclass if a custom key is preferred.
29
+ */
30
+ providerName() {
31
+ return this.constructor.name.toLowerCase().replace(/provider$/, '');
32
+ }
8
33
  /** Add extra scopes. */
9
34
  withScopes(scopes) {
10
35
  this.scopes = [...new Set([...this.scopes, ...scopes])];
@@ -15,14 +40,42 @@ export class SocialiteDriver {
15
40
  this.scopes = scopes;
16
41
  return this;
17
42
  }
43
+ /**
44
+ * Disable state generation + validation (Laravel `->stateless()`).
45
+ *
46
+ * Use for OAuth flows that can't reach the session — e.g. mobile clients,
47
+ * machine-to-machine auth, or token grants where the round-trip happens
48
+ * entirely server-to-server. The default (stateful) generates a CSPRNG
49
+ * `state` on redirect, stores it in the session, and validates it on
50
+ * callback to prevent CSRF / state-fixation.
51
+ */
52
+ stateless() {
53
+ this._stateless = true;
54
+ return this;
55
+ }
56
+ isStateless() {
57
+ return this._stateless;
58
+ }
59
+ /**
60
+ * Provider-specific extra params to merge into the authorize URL. Apple
61
+ * needs `response_mode=form_post`; other drivers may want `prompt=consent`
62
+ * etc. Override on subclasses — base returns `{}`.
63
+ */
64
+ extraAuthParams() {
65
+ return {};
66
+ }
18
67
  /** Get the redirect URL to the OAuth provider. */
19
68
  getRedirectUrl(state) {
69
+ // Caller-supplied state always wins (test-friendly + advanced override).
70
+ // When stateful and no state is supplied, generate + persist one.
71
+ const stateValue = state ?? (this._stateless ? undefined : this.generateAndStoreState());
20
72
  const params = new URLSearchParams({
21
73
  client_id: this.config.clientId,
22
74
  redirect_uri: this.config.redirectUrl,
23
75
  response_type: 'code',
24
76
  scope: this.scopes.join(' '),
25
- ...(state ? { state } : {}),
77
+ ...(stateValue ? { state: stateValue } : {}),
78
+ ...this.extraAuthParams(),
26
79
  });
27
80
  return `${this.authUrl()}?${params.toString()}`;
28
81
  }
@@ -30,15 +83,27 @@ export class SocialiteDriver {
30
83
  redirect(state) {
31
84
  return Response.redirect(this.getRedirectUrl(state), 302);
32
85
  }
86
+ /**
87
+ * Wrapper around `fetch` that injects an `AbortSignal.timeout` so a hung
88
+ * provider endpoint can't keep the request handler alive indefinitely.
89
+ * Subclasses (Apple, GitHub) call this for their own provider fetches.
90
+ */
91
+ fetchWithTimeout(input, init = {}) {
92
+ const timeoutMs = this.config.timeout ?? DEFAULT_TIMEOUT_MS;
93
+ return fetch(input, { ...init, signal: init.signal ?? AbortSignal.timeout(timeoutMs) });
94
+ }
33
95
  /** Exchange the authorization code for an access token. */
34
96
  async getAccessToken(code) {
35
- const res = await fetch(this.tokenUrl(), {
97
+ // RFC 6749 §4.1.3 mandates `application/x-www-form-urlencoded` for the
98
+ // token endpoint. GitHub, Google, and Facebook all reject JSON bodies
99
+ // (or accept them inconsistently); Apple's override already form-encodes.
100
+ const res = await this.fetchWithTimeout(this.tokenUrl(), {
36
101
  method: 'POST',
37
102
  headers: {
38
- 'Content-Type': 'application/json',
103
+ 'Content-Type': 'application/x-www-form-urlencoded',
39
104
  'Accept': 'application/json',
40
105
  },
41
- body: JSON.stringify({
106
+ body: new URLSearchParams({
42
107
  client_id: this.config.clientId,
43
108
  client_secret: this.config.clientSecret,
44
109
  code,
@@ -47,21 +112,28 @@ export class SocialiteDriver {
47
112
  }),
48
113
  });
49
114
  if (!res.ok) {
50
- const text = await res.text();
51
- throw new Error(`[RudderJS Socialite] Token exchange failed: ${res.status} ${text}`);
115
+ throw await this.httpError('Token exchange failed', res);
52
116
  }
53
117
  const data = await res.json();
54
- // Some providers return access_token, others return it in different shapes
55
- const accessToken = (data['access_token'] ?? data['accessToken']);
56
- const refreshToken = (data['refresh_token'] ?? data['refreshToken']);
57
- const expiresIn = (data['expires_in'] ?? data['expiresIn']);
58
- if (!accessToken) {
59
- throw new Error(`[RudderJS Socialite] No access_token in response: ${JSON.stringify(data)}`);
118
+ // Provider response is JSON of unknown shape type-check before trusting.
119
+ // Some providers use snake_case, some camelCase; either is fine, but the
120
+ // value must be a non-empty string. Anything else (number, null, object,
121
+ // empty string) is treated as a missing token.
122
+ const rawToken = data['access_token'] ?? data['accessToken'];
123
+ const rawRefresh = data['refresh_token'] ?? data['refreshToken'];
124
+ const rawExpiresIn = data['expires_in'] ?? data['expiresIn'];
125
+ if (typeof rawToken !== 'string' || rawToken.length === 0) {
126
+ throw new Error('[RudderJS Socialite] No access_token in token-exchange response.');
60
127
  }
61
- return { accessToken, refreshToken: refreshToken ?? null, expiresIn: expiresIn ?? null };
128
+ const refreshToken = typeof rawRefresh === 'string' && rawRefresh.length > 0 ? rawRefresh : null;
129
+ const expiresIn = typeof rawExpiresIn === 'number' && Number.isFinite(rawExpiresIn) ? rawExpiresIn : null;
130
+ return { accessToken: rawToken, refreshToken, expiresIn };
62
131
  }
63
132
  /** Get the authenticated user from the OAuth callback. */
64
133
  async user(codeOrRequest) {
134
+ if (typeof codeOrRequest !== 'string') {
135
+ this.validateRequestState(codeOrRequest);
136
+ }
65
137
  const code = typeof codeOrRequest === 'string'
66
138
  ? codeOrRequest
67
139
  : codeOrRequest.query['code'];
@@ -72,18 +144,89 @@ export class SocialiteDriver {
72
144
  }
73
145
  /** Get the user directly from an access token (e.g. for mobile apps). */
74
146
  async getUserByToken(token, refreshToken) {
75
- const res = await fetch(this.userUrl(), {
147
+ const res = await this.fetchWithTimeout(this.userUrl(), {
76
148
  headers: {
77
149
  'Authorization': `Bearer ${token}`,
78
150
  'Accept': 'application/json',
79
151
  },
80
152
  });
81
153
  if (!res.ok) {
82
- const text = await res.text();
83
- throw new Error(`[RudderJS Socialite] User info request failed: ${res.status} ${text}`);
154
+ throw await this.httpError('User info request failed', res);
84
155
  }
85
156
  const data = await res.json();
86
157
  return this.mapToUser(data, token, refreshToken ?? null);
87
158
  }
159
+ // ─── State (CSRF defense) ───────────────────────────────
160
+ get stateKey() {
161
+ return `socialite_state:${this.providerName()}`;
162
+ }
163
+ /**
164
+ * Generate a CSPRNG state token, store it on the session, and return the
165
+ * value to embed in the authorize URL. Throws when no session is in
166
+ * context — the caller can opt out via `.stateless()`.
167
+ */
168
+ generateAndStoreState() {
169
+ if (!Session.active()) {
170
+ throw new Error('[RudderJS Socialite] Cannot generate OAuth state: no session in context. ' +
171
+ 'Register session middleware (auto-installed on the web group), or call ' +
172
+ '`.stateless()` on the driver if state validation is intentionally skipped.');
173
+ }
174
+ const value = randomBytes(STATE_BYTES).toString('hex');
175
+ Session.put(this.stateKey, value);
176
+ return value;
177
+ }
178
+ /**
179
+ * Validate the `state` carried in a callback request against what was
180
+ * stored at redirect time. Pulls from `query.state` first, falling back
181
+ * to the request body's `state` (used by Apple's `form_post` callback).
182
+ * Always forgets the stored value after validation — the state is
183
+ * one-time use, so a leaked state can't be replayed.
184
+ */
185
+ validateRequestState(req) {
186
+ if (this._stateless)
187
+ return;
188
+ if (!Session.active()) {
189
+ throw new InvalidStateException('No session in context for state validation. Register session middleware ' +
190
+ 'or use `.stateless()` if state validation is intentionally skipped.');
191
+ }
192
+ const stored = Session.get(this.stateKey);
193
+ Session.forget(this.stateKey);
194
+ const provided = this.extractState(req);
195
+ if (typeof stored !== 'string' || stored.length === 0 ||
196
+ typeof provided !== 'string' || provided.length === 0 ||
197
+ !this.constantTimeStringEqual(stored, provided)) {
198
+ throw new InvalidStateException();
199
+ }
200
+ }
201
+ extractState(req) {
202
+ const fromQuery = req.query['state'];
203
+ if (typeof fromQuery === 'string' && fromQuery.length > 0)
204
+ return fromQuery;
205
+ const body = req.body;
206
+ if (body && typeof body === 'object') {
207
+ const fromBody = body['state'];
208
+ if (typeof fromBody === 'string' && fromBody.length > 0)
209
+ return fromBody;
210
+ }
211
+ return undefined;
212
+ }
213
+ constantTimeStringEqual(a, b) {
214
+ if (a.length !== b.length)
215
+ return false;
216
+ const ab = Buffer.from(a, 'utf8');
217
+ const bb = Buffer.from(b, 'utf8');
218
+ return timingSafeEqual(ab, bb);
219
+ }
220
+ /**
221
+ * Build an Error whose `message` carries only status + statusText (safe to
222
+ * surface in logs), with the response body attached on `cause` so callers
223
+ * that need it can still inspect — without leaking provider-echoed
224
+ * client_id / hints / PII into top-level error tracking.
225
+ */
226
+ async httpError(prefix, res) {
227
+ const body = await res.text().catch(() => '');
228
+ const cause = { status: res.status, body };
229
+ return new Error(`[RudderJS Socialite] ${prefix}: ${res.status} ${res.statusText}`.trimEnd(), { cause });
230
+ }
88
231
  }
89
232
  //# sourceMappingURL=driver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,55 @@
1
- import { SocialiteDriver } from '../driver.js';
1
+ import { SocialiteDriver, type SocialiteDriverConfig, type SocialiteCallbackRequest } from '../driver.js';
2
2
  import { SocialUser } from '../social-user.js';
3
+ /**
4
+ * Apple-specific config. The base `clientSecret` field is unused — Apple
5
+ * requires a freshly-signed ES256 JWT as `client_secret` on each token
6
+ * exchange. Provide `teamId`, `keyId`, and `privateKey` (PEM contents of the
7
+ * `.p8` file downloaded from the Apple Developer portal); the driver mints
8
+ * the JWT just-in-time.
9
+ */
10
+ export interface AppleSocialiteConfig extends SocialiteDriverConfig {
11
+ /** Apple Developer Team ID (10 chars). Used as the `iss` claim. */
12
+ teamId?: string;
13
+ /** Sign-in-with-Apple Key ID (10 chars). Embedded in the JWT header as `kid`. */
14
+ keyId?: string;
15
+ /** PEM-encoded EC P-256 private key (the `.p8` file contents). */
16
+ privateKey?: string;
17
+ /** Override the JWT lifetime in seconds. Apple max is 6 months; default 5 minutes. */
18
+ clientSecretTtl?: number;
19
+ }
3
20
  export declare class AppleProvider extends SocialiteDriver {
21
+ private static _jwksCache;
22
+ constructor(config: AppleSocialiteConfig);
4
23
  protected defaultScopes(): string[];
5
24
  protected authUrl(): string;
6
25
  protected tokenUrl(): string;
7
26
  protected userUrl(): string;
8
- getRedirectUrl(state?: string): string;
27
+ protected extraAuthParams(): Record<string, string>;
9
28
  protected mapToUser(data: Record<string, unknown>, token: string, refreshToken: string | null): SocialUser;
10
- /** Apple sends user data as form POST on callback. Parse the id_token JWT for user info. */
11
- user(codeOrRequest: string | {
12
- query: Record<string, string>;
13
- body?: unknown;
14
- }): Promise<SocialUser>;
15
- private getIdToken;
29
+ /**
30
+ * Exchange the auth code with Apple in a single POST, verify the returned
31
+ * id_token, and merge any first-authorization user details from the
32
+ * form_post body. Apple's auth codes are single-use, so this driver does
33
+ * NOT call the inherited `getAccessToken` — the token endpoint is hit
34
+ * exactly once per callback.
35
+ */
36
+ user(codeOrRequest: string | SocialiteCallbackRequest): Promise<SocialUser>;
37
+ private _exchange;
38
+ /**
39
+ * Build a freshly-signed ES256 JWT to use as `client_secret` for Apple's
40
+ * token endpoint. Apple requires JWS spec signatures — IEEE P-1363 raw
41
+ * (r||s, 64 bytes), NOT DER. node:crypto's `createSign` defaults to DER
42
+ * for EC keys, so `dsaEncoding: 'ieee-p1363'` is mandatory.
43
+ */
44
+ private _buildClientSecret;
45
+ /**
46
+ * Verify Apple's id_token: signature against the JWKS-resolved public key,
47
+ * then issuer / audience / expiration claims. Throws on any failure —
48
+ * never returns unverified data.
49
+ */
50
+ private _verifyIdToken;
51
+ private _resolveAppleJwk;
52
+ /** @internal — testing only. */
53
+ static _resetJwksCache(): void;
16
54
  }
17
55
  //# sourceMappingURL=apple.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apple.d.ts","sourceRoot":"","sources":["../../src/drivers/apple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,qBAAa,aAAc,SAAQ,eAAe;IAChD,SAAS,CAAC,aAAa,IAAI,MAAM,EAAE;IACnC,SAAS,CAAC,OAAO,IAAK,MAAM;IAC5B,SAAS,CAAC,QAAQ,IAAI,MAAM;IAC5B,SAAS,CAAC,OAAO,IAAK,MAAM;IAE5B,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAYtC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU;IAkB1G,4FAA4F;IACtF,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YA0B5F,UAAU;CAwBzB"}
1
+ {"version":3,"file":"apple.d.ts","sourceRoot":"","sources":["../../src/drivers/apple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IACjE,mEAAmE;IACnE,MAAM,CAAC,EAAM,MAAM,CAAA;IACnB,iFAAiF;IACjF,KAAK,CAAC,EAAO,MAAM,CAAA;IACnB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sFAAsF;IACtF,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AA+BD,qBAAa,aAAc,SAAQ,eAAe;IAGhD,OAAO,CAAC,MAAM,CAAC,UAAU,CAA8B;gBAE3C,MAAM,EAAE,oBAAoB;IAIxC,SAAS,CAAC,aAAa,IAAI,MAAM,EAAE;IACnC,SAAS,CAAC,OAAO,IAAK,MAAM;IAC5B,SAAS,CAAC,QAAQ,IAAI,MAAM;IAE5B,SAAS,CAAC,OAAO,IAAK,MAAM;cAET,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAO5D,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU;IAiB1G;;;;;;OAMG;IACY,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,wBAAwB,GAAG,OAAO,CAAC,UAAU,CAAC;YAuC5E,SAAS;IA4CvB;;;;;OAKG;YACW,kBAAkB;IAoDhC;;;;OAIG;YACW,cAAc;YA0Ed,gBAAgB;IAwB9B,gCAAgC;IAChC,MAAM,CAAC,eAAe,IAAI,IAAI;CAG/B"}
@@ -1,23 +1,28 @@
1
1
  import { SocialiteDriver } from '../driver.js';
2
2
  import { SocialUser } from '../social-user.js';
3
+ const APPLE_ISSUER = 'https://appleid.apple.com';
4
+ const APPLE_JWKS = 'https://appleid.apple.com/auth/keys';
5
+ const JWKS_TTL_MS = 60 * 60 * 1000; // 1 hour
6
+ const DEFAULT_JWT_TTL_SECONDS = 5 * 60;
3
7
  export class AppleProvider extends SocialiteDriver {
8
+ // Process-wide cache shared across AppleProvider instances. JWKS is small
9
+ // and Apple's keys rotate slowly, so a 1h cache is well within their guidance.
10
+ static _jwksCache = null;
11
+ constructor(config) {
12
+ super(config);
13
+ }
4
14
  defaultScopes() { return ['name', 'email']; }
5
15
  authUrl() { return 'https://appleid.apple.com/auth/authorize'; }
6
16
  tokenUrl() { return 'https://appleid.apple.com/auth/token'; }
7
- userUrl() { return ''; } // Apple sends user data in the callback, not a separate endpoint
8
- getRedirectUrl(state) {
9
- const params = new URLSearchParams({
10
- client_id: this.config.clientId,
11
- redirect_uri: this.config.redirectUrl,
12
- response_type: 'code',
13
- response_mode: 'form_post',
14
- scope: this.scopes.join(' '),
15
- ...(state ? { state } : {}),
16
- });
17
- return `${this.authUrl()}?${params.toString()}`;
17
+ // Apple sends user data in the id_token + first-auth form_post body, never a separate user endpoint.
18
+ userUrl() { return ''; }
19
+ extraAuthParams() {
20
+ // Apple requires form_post when the requested scopes include `name` or
21
+ // `email` (anything beyond `openid`) — the user-info payload is sent as
22
+ // a POST body, not a query.
23
+ return { response_mode: 'form_post' };
18
24
  }
19
25
  mapToUser(data, token, refreshToken) {
20
- // Apple's id_token contains the user info as a JWT
21
26
  const sub = data['sub'] ?? '';
22
27
  const email = data['email'] ?? null;
23
28
  const name = data['name'];
@@ -32,55 +37,219 @@ export class AppleProvider extends SocialiteDriver {
32
37
  raw: data,
33
38
  });
34
39
  }
35
- /** Apple sends user data as form POST on callback. Parse the id_token JWT for user info. */
40
+ /**
41
+ * Exchange the auth code with Apple in a single POST, verify the returned
42
+ * id_token, and merge any first-authorization user details from the
43
+ * form_post body. Apple's auth codes are single-use, so this driver does
44
+ * NOT call the inherited `getAccessToken` — the token endpoint is hit
45
+ * exactly once per callback.
46
+ */
36
47
  async user(codeOrRequest) {
48
+ if (typeof codeOrRequest !== 'string') {
49
+ // Apple's `state` arrives in the form_post body, not the query — the
50
+ // base validator already checks both, no Apple-specific override needed.
51
+ this.validateRequestState(codeOrRequest);
52
+ }
37
53
  const code = typeof codeOrRequest === 'string'
38
54
  ? codeOrRequest
39
55
  : (codeOrRequest.query['code'] ?? codeOrRequest.body?.['code']);
40
56
  if (!code)
41
57
  throw new Error('[RudderJS Socialite] Missing authorization code.');
42
- const { accessToken, refreshToken } = await this.getAccessToken(code);
43
- // Decode id_token (JWT) for user info — no verification needed here,
44
- // Apple's token endpoint is trusted.
45
- const idToken = (await this.getIdToken(code)) ?? {};
46
- const userData = { ...idToken };
47
- // Apple sends user name only on first authorization (as form POST body)
58
+ const { accessToken, refreshToken, idToken } = await this._exchange(code);
59
+ const claims = await this._verifyIdToken(idToken);
60
+ const userData = { ...claims };
61
+ // First authorization only Apple sends `name` once, in the form_post body.
48
62
  if (typeof codeOrRequest !== 'string' && codeOrRequest.body) {
49
63
  const body = codeOrRequest.body;
50
- if (body['user']) {
51
- const user = typeof body['user'] === 'string' ? JSON.parse(body['user']) : body['user'];
52
- userData['name'] = user;
64
+ const userField = body['user'];
65
+ if (userField !== undefined) {
66
+ try {
67
+ const parsed = typeof userField === 'string' ? JSON.parse(userField) : userField;
68
+ if (parsed && typeof parsed === 'object' && 'name' in parsed) {
69
+ userData['name'] = parsed['name'];
70
+ }
71
+ }
72
+ catch {
73
+ // Malformed body.user — ignore, name simply won't be set.
74
+ }
53
75
  }
54
76
  }
55
77
  return this.mapToUser(userData, accessToken, refreshToken);
56
78
  }
57
- async getIdToken(code) {
79
+ // ─── Token exchange ────────────────────────────────────
80
+ async _exchange(code) {
81
+ const clientSecret = await this._buildClientSecret();
82
+ const res = await this.fetchWithTimeout(this.tokenUrl(), {
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/x-www-form-urlencoded',
86
+ 'Accept': 'application/json',
87
+ },
88
+ body: new URLSearchParams({
89
+ client_id: this.config.clientId,
90
+ client_secret: clientSecret,
91
+ code,
92
+ redirect_uri: this.config.redirectUrl,
93
+ grant_type: 'authorization_code',
94
+ }),
95
+ });
96
+ if (!res.ok) {
97
+ throw await this.httpError('Apple token exchange failed', res);
98
+ }
99
+ const data = await res.json();
100
+ const accessToken = data['access_token'];
101
+ const refreshToken = data['refresh_token'];
102
+ const idToken = data['id_token'];
103
+ if (typeof accessToken !== 'string' || accessToken.length === 0) {
104
+ throw new Error('[RudderJS Socialite] Apple token-exchange response missing access_token.');
105
+ }
106
+ if (typeof idToken !== 'string' || idToken.length === 0) {
107
+ throw new Error('[RudderJS Socialite] Apple token-exchange response missing id_token.');
108
+ }
109
+ return {
110
+ accessToken,
111
+ refreshToken: typeof refreshToken === 'string' && refreshToken.length > 0 ? refreshToken : null,
112
+ idToken,
113
+ };
114
+ }
115
+ // ─── O2: ES256 client_secret JWT ───────────────────────
116
+ /**
117
+ * Build a freshly-signed ES256 JWT to use as `client_secret` for Apple's
118
+ * token endpoint. Apple requires JWS spec signatures — IEEE P-1363 raw
119
+ * (r||s, 64 bytes), NOT DER. node:crypto's `createSign` defaults to DER
120
+ * for EC keys, so `dsaEncoding: 'ieee-p1363'` is mandatory.
121
+ */
122
+ async _buildClientSecret() {
123
+ const cfg = this.config;
124
+ if (!cfg.teamId || !cfg.keyId || !cfg.privateKey) {
125
+ throw new Error('[RudderJS Socialite] Apple requires `teamId`, `keyId`, and `privateKey` ' +
126
+ 'in config to sign the client_secret JWT. See https://developer.apple.com/sign-in-with-apple/.');
127
+ }
128
+ const { createPrivateKey, createSign } = await import('node:crypto');
129
+ const now = Math.floor(Date.now() / 1000);
130
+ const ttl = cfg.clientSecretTtl ?? DEFAULT_JWT_TTL_SECONDS;
131
+ const header = { alg: 'ES256', kid: cfg.keyId, typ: 'JWT' };
132
+ const payload = {
133
+ iss: cfg.teamId,
134
+ iat: now,
135
+ exp: now + ttl,
136
+ aud: APPLE_ISSUER,
137
+ sub: this.config.clientId,
138
+ };
139
+ const headerB64 = Buffer.from(JSON.stringify(header)).toString('base64url');
140
+ const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64url');
141
+ const signingInput = `${headerB64}.${payloadB64}`;
142
+ let key;
143
+ try {
144
+ key = createPrivateKey({ key: cfg.privateKey, format: 'pem' });
145
+ }
146
+ catch (err) {
147
+ throw new Error('[RudderJS Socialite] Apple `privateKey` is not a valid PEM-encoded EC private key. ' +
148
+ '(See `.p8` file from Apple Developer portal.)', { cause: err });
149
+ }
150
+ if (key.asymmetricKeyType !== 'ec') {
151
+ throw new Error(`[RudderJS Socialite] Apple expects an EC P-256 private key; got ${key.asymmetricKeyType ?? 'unknown'}.`);
152
+ }
153
+ const signer = createSign('SHA256');
154
+ signer.update(signingInput);
155
+ const signature = signer.sign({ key, dsaEncoding: 'ieee-p1363' }, 'base64url');
156
+ return `${signingInput}.${signature}`;
157
+ }
158
+ // ─── O3: id_token verification ─────────────────────────
159
+ /**
160
+ * Verify Apple's id_token: signature against the JWKS-resolved public key,
161
+ * then issuer / audience / expiration claims. Throws on any failure —
162
+ * never returns unverified data.
163
+ */
164
+ async _verifyIdToken(idToken) {
165
+ const parts = idToken.split('.');
166
+ if (parts.length !== 3) {
167
+ throw new Error('[RudderJS Socialite] Apple id_token: malformed (expected 3 segments).');
168
+ }
169
+ const [headerB64, payloadB64, signatureB64] = parts;
170
+ let header;
58
171
  try {
59
- const res = await fetch(this.tokenUrl(), {
60
- method: 'POST',
61
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
62
- body: new URLSearchParams({
63
- client_id: this.config.clientId,
64
- client_secret: this.config.clientSecret,
65
- code,
66
- redirect_uri: this.config.redirectUrl,
67
- grant_type: 'authorization_code',
68
- }),
69
- });
70
- if (!res.ok)
71
- return null;
72
- const data = await res.json();
73
- if (!data.id_token)
74
- return null;
75
- // Decode JWT payload (base64url)
76
- const payload = data.id_token.split('.')[1];
77
- if (!payload)
78
- return null;
79
- return JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
172
+ header = JSON.parse(Buffer.from(headerB64, 'base64url').toString('utf8'));
80
173
  }
81
174
  catch {
82
- return null;
175
+ throw new Error('[RudderJS Socialite] Apple id_token: header is not valid JSON.');
176
+ }
177
+ if (header.alg !== 'RS256') {
178
+ throw new Error(`[RudderJS Socialite] Apple id_token: unexpected alg "${header.alg ?? ''}" (expected RS256).`);
179
+ }
180
+ if (typeof header.kid !== 'string' || header.kid.length === 0) {
181
+ throw new Error('[RudderJS Socialite] Apple id_token: header missing `kid`.');
182
+ }
183
+ const jwk = await this._resolveAppleJwk(header.kid);
184
+ if (!jwk) {
185
+ throw new Error(`[RudderJS Socialite] Apple id_token: no signing key for kid "${header.kid}".`);
83
186
  }
187
+ const { createPublicKey, createVerify } = await import('node:crypto');
188
+ let publicKey;
189
+ try {
190
+ // node:crypto's createPublicKey accepts a JsonWebKey from lib.dom; this
191
+ // package targets Node and doesn't include DOM lib, so widen via
192
+ // `as never` (bottom type, assignable to the parameter's expected type).
193
+ publicKey = createPublicKey({ key: jwk, format: 'jwk' });
194
+ }
195
+ catch (err) {
196
+ throw new Error('[RudderJS Socialite] Apple id_token: failed to import JWKS public key.', { cause: err });
197
+ }
198
+ const verifier = createVerify('SHA256');
199
+ verifier.update(`${headerB64}.${payloadB64}`);
200
+ if (!verifier.verify(publicKey, signatureB64, 'base64url')) {
201
+ throw new Error('[RudderJS Socialite] Apple id_token: signature verification failed.');
202
+ }
203
+ let claims;
204
+ try {
205
+ claims = JSON.parse(Buffer.from(payloadB64, 'base64url').toString('utf8'));
206
+ }
207
+ catch {
208
+ throw new Error('[RudderJS Socialite] Apple id_token: payload is not valid JSON.');
209
+ }
210
+ if (claims.iss !== APPLE_ISSUER) {
211
+ throw new Error(`[RudderJS Socialite] Apple id_token: iss "${claims.iss ?? ''}" does not match "${APPLE_ISSUER}".`);
212
+ }
213
+ const expectedAud = this.config.clientId;
214
+ const audMatches = Array.isArray(claims.aud)
215
+ ? claims.aud.includes(expectedAud)
216
+ : claims.aud === expectedAud;
217
+ if (!audMatches) {
218
+ throw new Error('[RudderJS Socialite] Apple id_token: aud does not match clientId.');
219
+ }
220
+ if (typeof claims.exp !== 'number' || claims.exp * 1000 <= Date.now()) {
221
+ throw new Error('[RudderJS Socialite] Apple id_token: token expired or missing exp.');
222
+ }
223
+ if (typeof claims.sub !== 'string' || claims.sub.length === 0) {
224
+ throw new Error('[RudderJS Socialite] Apple id_token: missing sub.');
225
+ }
226
+ return claims;
227
+ }
228
+ async _resolveAppleJwk(kid) {
229
+ const cache = AppleProvider._jwksCache;
230
+ if (cache && Date.now() - cache.fetchedAt < JWKS_TTL_MS) {
231
+ const hit = cache.keys.get(kid);
232
+ if (hit)
233
+ return hit;
234
+ // Fall through — kid not in cache. Apple may have rotated; refetch.
235
+ }
236
+ const res = await this.fetchWithTimeout(APPLE_JWKS, { headers: { Accept: 'application/json' } });
237
+ if (!res.ok) {
238
+ throw await this.httpError('Apple JWKS fetch failed', res);
239
+ }
240
+ const body = await res.json();
241
+ const keys = Array.isArray(body.keys) ? body.keys : [];
242
+ const map = new Map();
243
+ for (const k of keys) {
244
+ if (typeof k.kid === 'string')
245
+ map.set(k.kid, k);
246
+ }
247
+ AppleProvider._jwksCache = { fetchedAt: Date.now(), keys: map };
248
+ return map.get(kid);
249
+ }
250
+ /** @internal — testing only. */
251
+ static _resetJwksCache() {
252
+ AppleProvider._jwksCache = null;
84
253
  }
85
254
  }
86
255
  //# sourceMappingURL=apple.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apple.js","sourceRoot":"","sources":["../../src/drivers/apple.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apple.js","sourceRoot":"","sources":["../../src/drivers/apple.ts"],"names":[],"mappings":"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"}
@@ -39,7 +39,7 @@ export class GitHubProvider extends SocialiteDriver {
39
39
  }
40
40
  async fetchPrimaryEmail(token) {
41
41
  try {
42
- const res = await fetch('https://api.github.com/user/emails', {
42
+ const res = await this.fetchWithTimeout('https://api.github.com/user/emails', {
43
43
  headers: { 'Authorization': `Bearer ${token}`, 'Accept': 'application/json' },
44
44
  });
45
45
  if (!res.ok)
@@ -1 +1 @@
1
- {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/drivers/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,OAAO,cAAe,SAAQ,eAAe;IACvC,aAAa,KAAe,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA,CAAC,CAAC;IAChE,OAAO,KAAc,OAAO,0CAA0C,CAAA,CAAC,CAAC;IACxE,QAAQ,KAAa,OAAO,6CAA6C,CAAA,CAAC,CAAC;IAC3E,OAAO,KAAc,OAAO,6BAA6B,CAAA,CAAC,CAAC;IAE3D,SAAS,CAAC,IAA6B,EAAE,KAAa,EAAE,YAA2B;QAC3F,OAAO,IAAI,UAAU,CAAC;YACpB,EAAE,EAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,EAAO,IAAI,CAAC,MAAM,CAAmB,IAAI,IAAI;YACjD,KAAK,EAAM,IAAI,CAAC,OAAO,CAAmB,IAAI,IAAI;YAClD,MAAM,EAAK,IAAI,CAAC,YAAY,CAAmB,IAAI,IAAI;YACvD,QAAQ,EAAG,IAAI,CAAC,OAAO,CAAmB,IAAI,IAAI;YAClD,KAAK;YACL,YAAY;YACZ,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,IAAI,CAAC,aAAyD;QAClE,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YAC5D,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,IAAI,UAAU,CAAC;oBACpB,EAAE,EAAQ,UAAU,CAAC,KAAK,EAAE;oBAC5B,IAAI,EAAM,UAAU,CAAC,OAAO,EAAE;oBAC9B,KAAK;oBACL,MAAM,EAAI,UAAU,CAAC,SAAS,EAAE;oBAChC,QAAQ,EAAE,UAAU,CAAC,WAAW,EAAE;oBAClC,KAAK,EAAK,UAAU,CAAC,KAAK;oBAC1B,YAAY,EAAE,UAAU,CAAC,YAAY;oBACrC,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE;iBACvC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAA;IACnB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,KAAa;QAC3C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oCAAoC,EAAE;gBAC5D,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,KAAK,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC9E,CAAC,CAAA;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAA;YACxB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAA8D,CAAA;YAC3F,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAA;YACzD,OAAO,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/drivers/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,OAAO,cAAe,SAAQ,eAAe;IACvC,aAAa,KAAe,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA,CAAC,CAAC;IAChE,OAAO,KAAc,OAAO,0CAA0C,CAAA,CAAC,CAAC;IACxE,QAAQ,KAAa,OAAO,6CAA6C,CAAA,CAAC,CAAC;IAC3E,OAAO,KAAc,OAAO,6BAA6B,CAAA,CAAC,CAAC;IAE3D,SAAS,CAAC,IAA6B,EAAE,KAAa,EAAE,YAA2B;QAC3F,OAAO,IAAI,UAAU,CAAC;YACpB,EAAE,EAAQ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,EAAO,IAAI,CAAC,MAAM,CAAmB,IAAI,IAAI;YACjD,KAAK,EAAM,IAAI,CAAC,OAAO,CAAmB,IAAI,IAAI;YAClD,MAAM,EAAK,IAAI,CAAC,YAAY,CAAmB,IAAI,IAAI;YACvD,QAAQ,EAAG,IAAI,CAAC,OAAO,CAAmB,IAAI,IAAI;YAClD,KAAK;YACL,YAAY;YACZ,GAAG,EAAE,IAAI;SACV,CAAC,CAAA;IACJ,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,IAAI,CAAC,aAAyD;QAClE,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;YAC5D,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,IAAI,UAAU,CAAC;oBACpB,EAAE,EAAQ,UAAU,CAAC,KAAK,EAAE;oBAC5B,IAAI,EAAM,UAAU,CAAC,OAAO,EAAE;oBAC9B,KAAK;oBACL,MAAM,EAAI,UAAU,CAAC,SAAS,EAAE;oBAChC,QAAQ,EAAE,UAAU,CAAC,WAAW,EAAE;oBAClC,KAAK,EAAK,UAAU,CAAC,KAAK;oBAC1B,YAAY,EAAE,UAAU,CAAC,YAAY;oBACrC,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE;iBACvC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAA;IACnB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,KAAa;QAC3C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,oCAAoC,EAAE;gBAC5E,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,KAAK,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;aAC9E,CAAC,CAAA;YACF,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAA;YACxB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAA8D,CAAA;YAC3F,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAA;YACzD,OAAO,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ServiceProvider } from '@rudderjs/core';
2
2
  import { SocialiteDriver, type SocialiteDriverConfig } from './driver.js';
3
3
  export { SocialUser } from './social-user.js';
4
- export { SocialiteDriver } from './driver.js';
4
+ export { SocialiteDriver, InvalidStateException } from './driver.js';
5
5
  export { GitHubProvider } from './drivers/github.js';
6
6
  export { GoogleProvider } from './drivers/google.js';
7
7
  export { FacebookProvider } from './drivers/facebook.js';
8
8
  export { AppleProvider } from './drivers/apple.js';
9
- export type { SocialiteDriverConfig } from './driver.js';
9
+ export type { SocialiteDriverConfig, SocialiteCallbackRequest, SocialiteHttpErrorCause } from './driver.js';
10
+ export type { AppleSocialiteConfig } from './drivers/apple.js';
10
11
  type DriverFactory = (config: SocialiteDriverConfig) => SocialiteDriver;
11
12
  export declare class Socialite {
12
13
  private static _config;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAQzE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAIxD,KAAK,aAAa,GAAG,CAAC,MAAM,EAAE,qBAAqB,KAAK,eAAe,CAAA;AAWvE,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAmC;IACzD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAqC;IAE9D,+CAA+C;IAC/C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAe5C,sCAAsC;IACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAIzD,wDAAwD;IACxD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAK/C,qCAAqC;IACrC,MAAM,CAAC,KAAK,IAAI,IAAI;CAKrB;AAID,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;AAInE;;;;;;;;;;GAUG;AACH,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,QAAQ,IAAI,IAAI;IAEV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAU,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAQzE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAC3G,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAI9D,KAAK,aAAa,GAAG,CAAC,MAAM,EAAE,qBAAqB,KAAK,eAAe,CAAA;AAWvE,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAsB;IAC5C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAmC;IACzD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAqC;IAE9D,+CAA+C;IAC/C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAe5C,sCAAsC;IACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAQzD,wDAAwD;IACxD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAK/C,qCAAqC;IACrC,MAAM,CAAC,KAAK,IAAI,IAAI;CAKrB;AAID,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;AAInE;;;;;;;;;;GAUG;AACH,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,QAAQ,IAAI,IAAI;IAEV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { FacebookProvider } from './drivers/facebook.js';
5
5
  import { AppleProvider } from './drivers/apple.js';
6
6
  // ─── Re-exports ───────────────────────────────────────────
7
7
  export { SocialUser } from './social-user.js';
8
- export { SocialiteDriver } from './driver.js';
8
+ export { SocialiteDriver, InvalidStateException } from './driver.js';
9
9
  export { GitHubProvider } from './drivers/github.js';
10
10
  export { GoogleProvider } from './drivers/google.js';
11
11
  export { FacebookProvider } from './drivers/facebook.js';
@@ -39,6 +39,10 @@ export class Socialite {
39
39
  /** Register a custom OAuth driver. */
40
40
  static extend(name, factory) {
41
41
  this._custom.set(name, factory);
42
+ // Drop any previously cached instance so the next driver(name) call uses
43
+ // the new factory. Without this, calling extend() after driver() is silent
44
+ // no-op and the old driver lingers (bites hot-reload + runtime override).
45
+ this._instances.delete(name);
42
46
  }
43
47
  /** @internal — set config from the service provider. */
44
48
  static configure(config) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rudderjs/socialite",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "rudderjs": {
5
5
  "provider": "SocialiteProvider",
6
6
  "stage": "feature"
@@ -25,11 +25,20 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@rudderjs/core": "^1.1.2"
28
+ "@rudderjs/core": "^1.1.4"
29
+ },
30
+ "peerDependencies": {
31
+ "@rudderjs/session": "^2.0.0"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "@rudderjs/session": {
35
+ "optional": false
36
+ }
29
37
  },
30
38
  "devDependencies": {
31
39
  "@types/node": "^20.0.0",
32
- "typescript": "^5.4.0"
40
+ "typescript": "^5.4.0",
41
+ "@rudderjs/session": "^2.0.0"
33
42
  },
34
43
  "author": "Suleiman Shahbari",
35
44
  "scripts": {