@phalanx-engine/client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +1037 -0
  2. package/dist/DesyncDetector.d.ts +80 -0
  3. package/dist/DesyncDetector.d.ts.map +1 -0
  4. package/dist/DesyncDetector.js +93 -0
  5. package/dist/DesyncDetector.js.map +1 -0
  6. package/dist/DeterministicRandom.d.ts +78 -0
  7. package/dist/DeterministicRandom.d.ts.map +1 -0
  8. package/dist/DeterministicRandom.js +122 -0
  9. package/dist/DeterministicRandom.js.map +1 -0
  10. package/dist/EventEmitter.d.ts +65 -0
  11. package/dist/EventEmitter.d.ts.map +1 -0
  12. package/dist/EventEmitter.js +102 -0
  13. package/dist/EventEmitter.js.map +1 -0
  14. package/dist/FixedMath.d.ts +22 -0
  15. package/dist/FixedMath.d.ts.map +1 -0
  16. package/dist/FixedMath.js +26 -0
  17. package/dist/FixedMath.js.map +1 -0
  18. package/dist/PhalanxClient.d.ts +335 -0
  19. package/dist/PhalanxClient.d.ts.map +1 -0
  20. package/dist/PhalanxClient.js +844 -0
  21. package/dist/PhalanxClient.js.map +1 -0
  22. package/dist/RenderLoop.d.ts +95 -0
  23. package/dist/RenderLoop.d.ts.map +1 -0
  24. package/dist/RenderLoop.js +192 -0
  25. package/dist/RenderLoop.js.map +1 -0
  26. package/dist/SocketManager.d.ts +228 -0
  27. package/dist/SocketManager.d.ts.map +1 -0
  28. package/dist/SocketManager.js +584 -0
  29. package/dist/SocketManager.js.map +1 -0
  30. package/dist/StateHasher.d.ts +76 -0
  31. package/dist/StateHasher.d.ts.map +1 -0
  32. package/dist/StateHasher.js +129 -0
  33. package/dist/StateHasher.js.map +1 -0
  34. package/dist/auth/AuthManager.d.ts +188 -0
  35. package/dist/auth/AuthManager.d.ts.map +1 -0
  36. package/dist/auth/AuthManager.js +462 -0
  37. package/dist/auth/AuthManager.js.map +1 -0
  38. package/dist/auth/adapters/GoogleOAuthAdapter.d.ts +164 -0
  39. package/dist/auth/adapters/GoogleOAuthAdapter.d.ts.map +1 -0
  40. package/dist/auth/adapters/GoogleOAuthAdapter.js +521 -0
  41. package/dist/auth/adapters/GoogleOAuthAdapter.js.map +1 -0
  42. package/dist/auth/index.d.ts +45 -0
  43. package/dist/auth/index.d.ts.map +1 -0
  44. package/dist/auth/index.js +54 -0
  45. package/dist/auth/index.js.map +1 -0
  46. package/dist/auth/storage.d.ts +56 -0
  47. package/dist/auth/storage.d.ts.map +1 -0
  48. package/dist/auth/storage.js +78 -0
  49. package/dist/auth/storage.js.map +1 -0
  50. package/dist/auth/types.d.ts +212 -0
  51. package/dist/auth/types.d.ts.map +1 -0
  52. package/dist/auth/types.js +7 -0
  53. package/dist/auth/types.js.map +1 -0
  54. package/dist/index.d.ts +70 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +83 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/recovery/BrowserLifecycle.d.ts +33 -0
  59. package/dist/recovery/BrowserLifecycle.d.ts.map +1 -0
  60. package/dist/recovery/BrowserLifecycle.js +62 -0
  61. package/dist/recovery/BrowserLifecycle.js.map +1 -0
  62. package/dist/recovery/GuestPlayerIdStore.d.ts +17 -0
  63. package/dist/recovery/GuestPlayerIdStore.d.ts.map +1 -0
  64. package/dist/recovery/GuestPlayerIdStore.js +31 -0
  65. package/dist/recovery/GuestPlayerIdStore.js.map +1 -0
  66. package/dist/recovery/KeyValueStorage.d.ts +32 -0
  67. package/dist/recovery/KeyValueStorage.d.ts.map +1 -0
  68. package/dist/recovery/KeyValueStorage.js +58 -0
  69. package/dist/recovery/KeyValueStorage.js.map +1 -0
  70. package/dist/recovery/MobileTransport.d.ts +12 -0
  71. package/dist/recovery/MobileTransport.d.ts.map +1 -0
  72. package/dist/recovery/MobileTransport.js +24 -0
  73. package/dist/recovery/MobileTransport.js.map +1 -0
  74. package/dist/recovery/NetworkQuality.d.ts +22 -0
  75. package/dist/recovery/NetworkQuality.d.ts.map +1 -0
  76. package/dist/recovery/NetworkQuality.js +35 -0
  77. package/dist/recovery/NetworkQuality.js.map +1 -0
  78. package/dist/recovery/RoomPersistence.d.ts +55 -0
  79. package/dist/recovery/RoomPersistence.d.ts.map +1 -0
  80. package/dist/recovery/RoomPersistence.js +68 -0
  81. package/dist/recovery/RoomPersistence.js.map +1 -0
  82. package/dist/recovery/RoomRecoveryController.d.ts +146 -0
  83. package/dist/recovery/RoomRecoveryController.d.ts.map +1 -0
  84. package/dist/recovery/RoomRecoveryController.js +348 -0
  85. package/dist/recovery/RoomRecoveryController.js.map +1 -0
  86. package/dist/recovery/index.d.ts +13 -0
  87. package/dist/recovery/index.d.ts.map +1 -0
  88. package/dist/recovery/index.js +8 -0
  89. package/dist/recovery/index.js.map +1 -0
  90. package/dist/types.d.ts +501 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +6 -0
  93. package/dist/types.js.map +1 -0
  94. package/package.json +66 -0
@@ -0,0 +1,521 @@
1
+ /**
2
+ * Google OAuth Adapter
3
+ *
4
+ * OAuth 2.0 adapter for Google Sign-In using PKCE flow.
5
+ * This is a client-side only implementation that doesn't require a backend.
6
+ */
7
+ // ============================================
8
+ // Google OAuth Adapter
9
+ // ============================================
10
+ /**
11
+ * Google OAuth adapter using PKCE flow.
12
+ *
13
+ * Features:
14
+ * - PKCE (Proof Key for Code Exchange) for security
15
+ * - State parameter for CSRF protection
16
+ * - Nonce for replay protection
17
+ * - ID token validation
18
+ * - Automatic token refresh
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const adapter = new GoogleOAuthAdapter({
23
+ * clientId: 'your-client-id.apps.googleusercontent.com'
24
+ * });
25
+ *
26
+ * // Generate login URL
27
+ * const loginUrl = adapter.getLoginUrl();
28
+ * window.location.href = loginUrl;
29
+ *
30
+ * // Handle callback (on /auth/callback page)
31
+ * const result = await adapter.handleCallback({
32
+ * code: new URLSearchParams(location.search).get('code'),
33
+ * state: new URLSearchParams(location.search).get('state')
34
+ * });
35
+ * ```
36
+ */
37
+ export class GoogleOAuthAdapter {
38
+ provider = 'google';
39
+ config;
40
+ // Storage keys for PKCE
41
+ VERIFIER_KEY = 'phalanx_google_verifier';
42
+ CHALLENGE_KEY = 'phalanx_google_challenge';
43
+ STATE_KEY = 'phalanx_google_state';
44
+ NONCE_KEY = 'phalanx_google_nonce';
45
+ /**
46
+ * Create a new Google OAuth adapter.
47
+ * @param config - Google OAuth configuration
48
+ */
49
+ constructor(config) {
50
+ this.config = {
51
+ scopes: ['openid', 'profile', 'email'],
52
+ ...config,
53
+ };
54
+ }
55
+ // ─────────────────────────────────────────────────────────────────
56
+ // AuthAdapter Interface
57
+ // ─────────────────────────────────────────────────────────────────
58
+ /**
59
+ * Generate the Google OAuth authorization URL.
60
+ *
61
+ * This method:
62
+ * 1. Generates PKCE code verifier and challenge
63
+ * 2. Generates state for CSRF protection
64
+ * 3. Generates nonce for ID token validation
65
+ * 4. Stores values in sessionStorage for callback validation
66
+ * 5. Returns the authorization URL
67
+ *
68
+ * Note: Call preparePKCE() before this if you need async SHA-256 challenge.
69
+ * If not called, uses plain verifier as challenge (works with some providers).
70
+ *
71
+ * @param options - Optional login options
72
+ * @returns Authorization URL to redirect user to
73
+ */
74
+ getLoginUrl(options) {
75
+ // Check if PKCE was pre-computed
76
+ let codeVerifier = typeof sessionStorage !== 'undefined'
77
+ ? sessionStorage.getItem(this.VERIFIER_KEY)
78
+ : null;
79
+ let codeChallenge = typeof sessionStorage !== 'undefined'
80
+ ? sessionStorage.getItem(this.CHALLENGE_KEY)
81
+ : null;
82
+ // Generate new PKCE values if not pre-computed
83
+ if (!codeVerifier || !codeChallenge) {
84
+ codeVerifier = this.generateCodeVerifier();
85
+ // For sync operation, use plain method (S256 requires async)
86
+ // We'll compute proper S256 challenge inline using a workaround
87
+ codeChallenge = codeVerifier; // Fallback - will be replaced if preparePKCE was called
88
+ }
89
+ const state = options?.state || this.generateRandomString();
90
+ const nonce = options?.nonce || this.generateRandomString();
91
+ // Store for callback validation
92
+ if (typeof sessionStorage !== 'undefined') {
93
+ sessionStorage.setItem(this.VERIFIER_KEY, codeVerifier);
94
+ sessionStorage.setItem(this.STATE_KEY, state);
95
+ sessionStorage.setItem(this.NONCE_KEY, nonce);
96
+ // Clear challenge key (will be regenerated on next preparePKCE)
97
+ sessionStorage.removeItem(this.CHALLENGE_KEY);
98
+ }
99
+ // Merge scopes
100
+ const scopes = options?.scopes
101
+ ? [...new Set([...this.config.scopes, ...options.scopes])]
102
+ : this.config.scopes;
103
+ // Build authorization URL
104
+ // Use 'plain' method if challenge equals verifier, otherwise 'S256'
105
+ const challengeMethod = codeChallenge === codeVerifier ? 'plain' : 'S256';
106
+ const params = new URLSearchParams({
107
+ client_id: this.config.clientId,
108
+ redirect_uri: options?.redirectUri || this.getRedirectUri(),
109
+ response_type: 'code',
110
+ scope: scopes.join(' '),
111
+ code_challenge: codeChallenge,
112
+ code_challenge_method: challengeMethod,
113
+ state: state,
114
+ nonce: nonce,
115
+ access_type: 'offline', // Request refresh token
116
+ include_granted_scopes: 'true',
117
+ });
118
+ // Optional parameters
119
+ if (options?.prompt) {
120
+ params.set('prompt', options.prompt);
121
+ }
122
+ if (options?.loginHint) {
123
+ params.set('login_hint', options.loginHint);
124
+ }
125
+ if (this.config.hostedDomain) {
126
+ params.set('hd', this.config.hostedDomain);
127
+ }
128
+ return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
129
+ }
130
+ /**
131
+ * Prepare PKCE values asynchronously before calling getLoginUrl().
132
+ * This computes the proper SHA-256 code challenge.
133
+ *
134
+ * Call this before login() for proper S256 PKCE:
135
+ * ```typescript
136
+ * await adapter.preparePKCE();
137
+ * const url = adapter.getLoginUrl();
138
+ * ```
139
+ */
140
+ async preparePKCE() {
141
+ const codeVerifier = this.generateCodeVerifier();
142
+ const codeChallenge = await this.computeCodeChallenge(codeVerifier);
143
+ if (typeof sessionStorage !== 'undefined') {
144
+ sessionStorage.setItem(this.VERIFIER_KEY, codeVerifier);
145
+ sessionStorage.setItem(this.CHALLENGE_KEY, codeChallenge);
146
+ }
147
+ }
148
+ /**
149
+ * Compute SHA-256 code challenge from verifier (async).
150
+ */
151
+ async computeCodeChallenge(verifier) {
152
+ const encoder = new TextEncoder();
153
+ const data = encoder.encode(verifier);
154
+ const digest = await crypto.subtle.digest('SHA-256', data);
155
+ return this.base64UrlEncode(new Uint8Array(digest));
156
+ }
157
+ /**
158
+ * Handle the OAuth callback from Google.
159
+ *
160
+ * This method:
161
+ * 1. Validates the state parameter (CSRF protection)
162
+ * 2. Retrieves the stored PKCE verifier
163
+ * 3. Exchanges the authorization code for tokens
164
+ * 4. Validates the ID token
165
+ * 5. Returns the auth result
166
+ *
167
+ * @param params - Callback parameters from URL
168
+ * @returns Auth result with user info and tokens
169
+ */
170
+ async handleCallback(params) {
171
+ // Validate state (CSRF protection)
172
+ const storedState = typeof sessionStorage !== 'undefined'
173
+ ? sessionStorage.getItem(this.STATE_KEY)
174
+ : null;
175
+ if (!storedState || storedState !== params.state) {
176
+ return {
177
+ valid: false,
178
+ error: 'Invalid state parameter. Possible CSRF attack.',
179
+ errorCode: 'invalid_state',
180
+ };
181
+ }
182
+ // Get stored PKCE verifier
183
+ const codeVerifier = typeof sessionStorage !== 'undefined'
184
+ ? sessionStorage.getItem(this.VERIFIER_KEY)
185
+ : null;
186
+ if (!codeVerifier) {
187
+ return {
188
+ valid: false,
189
+ error: 'Code verifier not found. Please start authentication again.',
190
+ errorCode: 'missing_verifier',
191
+ };
192
+ }
193
+ // Get stored nonce
194
+ const nonce = typeof sessionStorage !== 'undefined'
195
+ ? sessionStorage.getItem(this.NONCE_KEY)
196
+ : null;
197
+ // Clear stored values
198
+ if (typeof sessionStorage !== 'undefined') {
199
+ sessionStorage.removeItem(this.VERIFIER_KEY);
200
+ sessionStorage.removeItem(this.STATE_KEY);
201
+ sessionStorage.removeItem(this.NONCE_KEY);
202
+ }
203
+ // Handle error from Google
204
+ if (params.error) {
205
+ return {
206
+ valid: false,
207
+ error: params.errorDescription || params.error,
208
+ errorCode: params.error,
209
+ };
210
+ }
211
+ if (!params.code) {
212
+ return {
213
+ valid: false,
214
+ error: 'No authorization code received',
215
+ errorCode: 'missing_code',
216
+ };
217
+ }
218
+ try {
219
+ // Exchange code for tokens
220
+ const tokens = await this.exchangeCodeForTokens(params.code, codeVerifier, this.getRedirectUri());
221
+ // Decode and validate ID token
222
+ const idTokenPayload = this.decodeIdToken(tokens.id_token);
223
+ // Validate ID token claims
224
+ const validationError = this.validateIdToken(idTokenPayload, nonce);
225
+ if (validationError) {
226
+ return {
227
+ valid: false,
228
+ error: validationError,
229
+ errorCode: 'invalid_id_token',
230
+ };
231
+ }
232
+ return {
233
+ valid: true,
234
+ playerId: idTokenPayload.sub,
235
+ username: idTokenPayload.name,
236
+ email: idTokenPayload.email,
237
+ avatarUrl: idTokenPayload.picture,
238
+ provider: 'google',
239
+ token: tokens.id_token,
240
+ accessToken: tokens.access_token,
241
+ refreshToken: tokens.refresh_token,
242
+ expiresAt: Date.now() + tokens.expires_in * 1000,
243
+ };
244
+ }
245
+ catch (error) {
246
+ return {
247
+ valid: false,
248
+ error: error instanceof Error ? error.message : 'Token exchange failed',
249
+ errorCode: 'token_exchange_failed',
250
+ };
251
+ }
252
+ }
253
+ /**
254
+ * Refresh an expired token using the refresh token.
255
+ *
256
+ * @param refreshToken - The refresh token to use
257
+ * @returns New auth result or null if refresh failed
258
+ */
259
+ async refreshToken(refreshToken) {
260
+ try {
261
+ const response = await fetch('https://oauth2.googleapis.com/token', {
262
+ method: 'POST',
263
+ headers: {
264
+ 'Content-Type': 'application/x-www-form-urlencoded',
265
+ },
266
+ body: new URLSearchParams({
267
+ client_id: this.config.clientId,
268
+ refresh_token: refreshToken,
269
+ grant_type: 'refresh_token',
270
+ }),
271
+ });
272
+ if (!response.ok) {
273
+ const error = await response.json();
274
+ console.error('[GoogleOAuth] Refresh failed:', error);
275
+ return null;
276
+ }
277
+ const tokens = (await response.json());
278
+ const idTokenPayload = this.decodeIdToken(tokens.id_token);
279
+ return {
280
+ valid: true,
281
+ playerId: idTokenPayload.sub,
282
+ username: idTokenPayload.name,
283
+ email: idTokenPayload.email,
284
+ avatarUrl: idTokenPayload.picture,
285
+ provider: 'google',
286
+ token: tokens.id_token,
287
+ accessToken: tokens.access_token,
288
+ // Note: Google doesn't return new refresh_token on refresh
289
+ expiresAt: Date.now() + tokens.expires_in * 1000,
290
+ };
291
+ }
292
+ catch (error) {
293
+ console.error('[GoogleOAuth] Refresh error:', error);
294
+ return null;
295
+ }
296
+ }
297
+ /**
298
+ * Revoke a token (logout from Google).
299
+ *
300
+ * @param token - The token to revoke
301
+ */
302
+ async revokeToken(token) {
303
+ try {
304
+ await fetch(`https://oauth2.googleapis.com/revoke?token=${token}`, {
305
+ method: 'POST',
306
+ headers: {
307
+ 'Content-Type': 'application/x-www-form-urlencoded',
308
+ },
309
+ });
310
+ }
311
+ catch (error) {
312
+ console.warn('[GoogleOAuth] Revoke failed:', error);
313
+ }
314
+ }
315
+ /**
316
+ * Check if this adapter can handle the given token.
317
+ *
318
+ * @param token - Token to check
319
+ * @returns True if token is a Google ID token
320
+ */
321
+ canHandle(token) {
322
+ try {
323
+ const payload = this.decodeIdToken(token);
324
+ return (payload.iss === 'https://accounts.google.com' ||
325
+ payload.iss === 'accounts.google.com');
326
+ }
327
+ catch {
328
+ return false;
329
+ }
330
+ }
331
+ // ─────────────────────────────────────────────────────────────────
332
+ // Private Methods
333
+ // ─────────────────────────────────────────────────────────────────
334
+ /**
335
+ * Exchange authorization code for tokens.
336
+ * Uses backend endpoint if configured, otherwise calls Google directly.
337
+ */
338
+ async exchangeCodeForTokens(code, codeVerifier, redirectUri) {
339
+ // Use backend token exchange if configured (recommended for security)
340
+ if (this.config.tokenExchangeUrl) {
341
+ return this.exchangeCodeViaBackend(code, codeVerifier, redirectUri);
342
+ }
343
+ // Direct exchange with Google (requires client_secret on server or native app)
344
+ return this.exchangeCodeDirect(code, codeVerifier, redirectUri);
345
+ }
346
+ /**
347
+ * Exchange code via our backend server (secure - keeps client_secret on server)
348
+ */
349
+ async exchangeCodeViaBackend(code, codeVerifier, redirectUri) {
350
+ const response = await fetch(this.config.tokenExchangeUrl, {
351
+ method: 'POST',
352
+ headers: {
353
+ 'Content-Type': 'application/json',
354
+ },
355
+ body: JSON.stringify({
356
+ code,
357
+ codeVerifier,
358
+ redirectUri,
359
+ provider: 'google',
360
+ }),
361
+ });
362
+ if (!response.ok) {
363
+ const error = await response.json();
364
+ throw new Error(error.error || error.message || 'Token exchange failed');
365
+ }
366
+ const result = await response.json();
367
+ if (!result.success) {
368
+ throw new Error(result.error || 'Token exchange failed');
369
+ }
370
+ // Map backend response to GoogleTokenResponse format
371
+ return {
372
+ id_token: result.idToken,
373
+ access_token: result.accessToken,
374
+ expires_in: result.expiresIn || 3600,
375
+ scope: 'openid profile email',
376
+ token_type: 'Bearer',
377
+ refresh_token: result.refreshToken,
378
+ };
379
+ }
380
+ /**
381
+ * Exchange code directly with Google (won't work for Web apps without client_secret)
382
+ */
383
+ async exchangeCodeDirect(code, codeVerifier, redirectUri) {
384
+ const response = await fetch('https://oauth2.googleapis.com/token', {
385
+ method: 'POST',
386
+ headers: {
387
+ 'Content-Type': 'application/x-www-form-urlencoded',
388
+ },
389
+ body: new URLSearchParams({
390
+ client_id: this.config.clientId,
391
+ code,
392
+ code_verifier: codeVerifier,
393
+ grant_type: 'authorization_code',
394
+ redirect_uri: redirectUri,
395
+ }),
396
+ });
397
+ if (!response.ok) {
398
+ const error = await response.json();
399
+ throw new Error(error.error_description || error.error || 'Token exchange failed');
400
+ }
401
+ return response.json();
402
+ }
403
+ /**
404
+ * Decode a JWT ID token (without verification - verification done via claims).
405
+ */
406
+ decodeIdToken(idToken) {
407
+ const parts = idToken.split('.');
408
+ if (parts.length !== 3 || !parts[1]) {
409
+ throw new Error('Invalid ID token format');
410
+ }
411
+ const payloadBase64 = parts[1];
412
+ const payloadJson = this.base64UrlDecode(payloadBase64);
413
+ return JSON.parse(payloadJson);
414
+ }
415
+ /**
416
+ * Validate ID token claims.
417
+ */
418
+ validateIdToken(payload, nonce) {
419
+ // Check issuer
420
+ if (payload.iss !== 'https://accounts.google.com' &&
421
+ payload.iss !== 'accounts.google.com') {
422
+ return 'Invalid issuer';
423
+ }
424
+ // Check audience
425
+ if (payload.aud !== this.config.clientId) {
426
+ return 'Invalid audience';
427
+ }
428
+ // Check expiration (with 5 minute leeway)
429
+ if (payload.exp * 1000 < Date.now() - 5 * 60 * 1000) {
430
+ return 'Token expired';
431
+ }
432
+ // Check nonce (replay protection)
433
+ if (nonce && payload.nonce !== nonce) {
434
+ return 'Invalid nonce';
435
+ }
436
+ // Check hosted domain if configured
437
+ if (this.config.hostedDomain && payload.hd !== this.config.hostedDomain) {
438
+ return `User must be from ${this.config.hostedDomain} domain`;
439
+ }
440
+ return null;
441
+ }
442
+ /**
443
+ * Get the redirect URI.
444
+ */
445
+ getRedirectUri() {
446
+ if (this.config.redirectUri) {
447
+ return this.config.redirectUri;
448
+ }
449
+ if (typeof window !== 'undefined') {
450
+ return `${window.location.origin}/auth/callback`;
451
+ }
452
+ return '/auth/callback';
453
+ }
454
+ // ─────────────────────────────────────────────────────────────────
455
+ // PKCE Helpers
456
+ // ─────────────────────────────────────────────────────────────────
457
+ /**
458
+ * Generate a random code verifier for PKCE.
459
+ * 43-128 characters from unreserved URI characters.
460
+ */
461
+ generateCodeVerifier() {
462
+ const array = new Uint8Array(32);
463
+ crypto.getRandomValues(array);
464
+ return this.base64UrlEncode(array);
465
+ }
466
+ /**
467
+ * Generate a random string for state/nonce.
468
+ */
469
+ generateRandomString() {
470
+ const array = new Uint8Array(16);
471
+ crypto.getRandomValues(array);
472
+ return this.base64UrlEncode(array);
473
+ }
474
+ /**
475
+ * Base64URL encode a Uint8Array.
476
+ */
477
+ base64UrlEncode(buffer) {
478
+ let binary = '';
479
+ for (let i = 0; i < buffer.length; i++) {
480
+ binary += String.fromCharCode(buffer[i] ?? 0);
481
+ }
482
+ const base64 = btoa(binary);
483
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
484
+ }
485
+ /**
486
+ * Base64URL decode a string.
487
+ */
488
+ base64UrlDecode(input) {
489
+ // Convert base64url to base64
490
+ let base64 = input.replace(/-/g, '+').replace(/_/g, '/');
491
+ // Add padding if needed
492
+ const padding = base64.length % 4;
493
+ if (padding) {
494
+ base64 += '='.repeat(4 - padding);
495
+ }
496
+ return atob(base64);
497
+ }
498
+ }
499
+ // ============================================
500
+ // Async PKCE Helper (for production use)
501
+ // ============================================
502
+ /**
503
+ * Compute SHA-256 code challenge asynchronously.
504
+ * Use this for production-ready PKCE implementation.
505
+ *
506
+ * @param verifier - The code verifier
507
+ * @returns Base64URL-encoded SHA-256 hash
508
+ */
509
+ export async function computeCodeChallenge(verifier) {
510
+ const encoder = new TextEncoder();
511
+ const data = encoder.encode(verifier);
512
+ const digest = await crypto.subtle.digest('SHA-256', data);
513
+ const array = new Uint8Array(digest);
514
+ let binary = '';
515
+ for (let i = 0; i < array.length; i++) {
516
+ binary += String.fromCharCode(array[i] ?? 0);
517
+ }
518
+ const base64 = btoa(binary);
519
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
520
+ }
521
+ //# sourceMappingURL=GoogleOAuthAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleOAuthAdapter.js","sourceRoot":"","sources":["../../../src/auth/adapters/GoogleOAuthAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Phalanx Auth Module
3
+ *
4
+ * Managed OAuth authentication for Phalanx games.
5
+ * Provides drop-in authentication with Google, Discord, and Steam.
6
+ *
7
+ * ## Quick Start
8
+ *
9
+ * ```typescript
10
+ * import { AuthManager } from '@phalanx-engine/client/auth';
11
+ *
12
+ * const auth = new AuthManager({
13
+ * provider: 'google',
14
+ * google: {
15
+ * clientId: 'your-client-id.apps.googleusercontent.com'
16
+ * }
17
+ * });
18
+ *
19
+ * // Check for existing session
20
+ * const hasSession = await auth.checkSession();
21
+ *
22
+ * if (!hasSession) {
23
+ * // Login with popup
24
+ * await auth.loginWithPopup();
25
+ * }
26
+ *
27
+ * // Get token for Phalanx client
28
+ * const client = await PhalanxClient.create({
29
+ * serverUrl: 'http://localhost:3000',
30
+ * playerId: auth.getUser()!.id,
31
+ * username: auth.getUser()!.username || 'Player',
32
+ * authToken: auth.getToken()!
33
+ * });
34
+ * ```
35
+ *
36
+ * @packageDocumentation
37
+ */
38
+ export { AuthManager } from './AuthManager.js';
39
+ export type { AuthManagerConfig } from './AuthManager.js';
40
+ export { GoogleOAuthAdapter } from './adapters/GoogleOAuthAdapter.js';
41
+ export { computeCodeChallenge } from './adapters/GoogleOAuthAdapter.js';
42
+ export { LocalStorageAdapter, MemoryStorageAdapter } from './storage.js';
43
+ export type { AuthStorage } from './storage.js';
44
+ export type { AuthAdapter, LoginOptions, CallbackParams, AuthResult, AuthUser, AuthState, StoredAuthData, AuthError, GoogleOAuthConfig, DiscordOAuthConfig, SteamAuthConfig, } from './types.js';
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAMH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAM1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAUxE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAMhD,YAAY,EAEV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,EAGV,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,EAGT,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Phalanx Auth Module
3
+ *
4
+ * Managed OAuth authentication for Phalanx games.
5
+ * Provides drop-in authentication with Google, Discord, and Steam.
6
+ *
7
+ * ## Quick Start
8
+ *
9
+ * ```typescript
10
+ * import { AuthManager } from '@phalanx-engine/client/auth';
11
+ *
12
+ * const auth = new AuthManager({
13
+ * provider: 'google',
14
+ * google: {
15
+ * clientId: 'your-client-id.apps.googleusercontent.com'
16
+ * }
17
+ * });
18
+ *
19
+ * // Check for existing session
20
+ * const hasSession = await auth.checkSession();
21
+ *
22
+ * if (!hasSession) {
23
+ * // Login with popup
24
+ * await auth.loginWithPopup();
25
+ * }
26
+ *
27
+ * // Get token for Phalanx client
28
+ * const client = await PhalanxClient.create({
29
+ * serverUrl: 'http://localhost:3000',
30
+ * playerId: auth.getUser()!.id,
31
+ * username: auth.getUser()!.username || 'Player',
32
+ * authToken: auth.getToken()!
33
+ * });
34
+ * ```
35
+ *
36
+ * @packageDocumentation
37
+ */
38
+ // ============================================
39
+ // Main Auth Manager
40
+ // ============================================
41
+ export { AuthManager } from './AuthManager.js';
42
+ // ============================================
43
+ // OAuth Adapters
44
+ // ============================================
45
+ export { GoogleOAuthAdapter } from './adapters/GoogleOAuthAdapter.js';
46
+ export { computeCodeChallenge } from './adapters/GoogleOAuthAdapter.js';
47
+ // Future adapters:
48
+ // export { DiscordOAuthAdapter } from './adapters/DiscordOAuthAdapter.js';
49
+ // export { SteamAuthAdapter } from './adapters/SteamAuthAdapter.js';
50
+ // ============================================
51
+ // Storage
52
+ // ============================================
53
+ export { LocalStorageAdapter, MemoryStorageAdapter } from './storage.js';
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,+CAA+C;AAC/C,oBAAoB;AACpB,+CAA+C;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,+CAA+C;AAC/C,iBAAiB;AACjB,+CAA+C;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,mBAAmB;AACnB,2EAA2E;AAC3E,qEAAqE;AAErE,+CAA+C;AAC/C,UAAU;AACV,+CAA+C;AAE/C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}