@blackcode_sa/metaestetics-api 1.12.10 → 1.12.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +122 -0
- package/dist/index.mjs +122 -0
- package/package.json +1 -1
- package/src/services/auth/auth.service.ts +160 -0
package/dist/index.d.mts
CHANGED
|
@@ -6191,6 +6191,17 @@ declare class AuthService extends BaseService {
|
|
|
6191
6191
|
* @returns The signed-in or newly created user.
|
|
6192
6192
|
*/
|
|
6193
6193
|
signInWithGoogleIdToken(idToken: string, initialRole?: UserRole): Promise<User>;
|
|
6194
|
+
/**
|
|
6195
|
+
* Signs in a user with a Google authorization code from a mobile client.
|
|
6196
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
6197
|
+
* with the platform-specific client ID (no client secret needed for native apps).
|
|
6198
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
6199
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
6200
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
6201
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
6202
|
+
* @returns The signed-in or newly created user.
|
|
6203
|
+
*/
|
|
6204
|
+
signInWithGoogleAuthCode(authorizationCode: string, redirectUri: string, clientId: string, initialRole?: UserRole): Promise<User>;
|
|
6194
6205
|
/**
|
|
6195
6206
|
* Links a Google account to the currently signed-in user using an ID token.
|
|
6196
6207
|
* This is used to upgrade an anonymous user or to allow an existing user
|
|
@@ -6199,6 +6210,16 @@ declare class AuthService extends BaseService {
|
|
|
6199
6210
|
* @returns The updated user profile.
|
|
6200
6211
|
*/
|
|
6201
6212
|
linkGoogleAccount(idToken: string): Promise<User>;
|
|
6213
|
+
/**
|
|
6214
|
+
* Links a Google account to the currently signed-in user using an authorization code.
|
|
6215
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
6216
|
+
* with the platform-specific client ID, then links the Google account to the current user.
|
|
6217
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
6218
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
6219
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
6220
|
+
* @returns The updated user profile.
|
|
6221
|
+
*/
|
|
6222
|
+
linkGoogleAccountWithAuthCode(authorizationCode: string, redirectUri: string, clientId: string): Promise<User>;
|
|
6202
6223
|
}
|
|
6203
6224
|
|
|
6204
6225
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -6191,6 +6191,17 @@ declare class AuthService extends BaseService {
|
|
|
6191
6191
|
* @returns The signed-in or newly created user.
|
|
6192
6192
|
*/
|
|
6193
6193
|
signInWithGoogleIdToken(idToken: string, initialRole?: UserRole): Promise<User>;
|
|
6194
|
+
/**
|
|
6195
|
+
* Signs in a user with a Google authorization code from a mobile client.
|
|
6196
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
6197
|
+
* with the platform-specific client ID (no client secret needed for native apps).
|
|
6198
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
6199
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
6200
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
6201
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
6202
|
+
* @returns The signed-in or newly created user.
|
|
6203
|
+
*/
|
|
6204
|
+
signInWithGoogleAuthCode(authorizationCode: string, redirectUri: string, clientId: string, initialRole?: UserRole): Promise<User>;
|
|
6194
6205
|
/**
|
|
6195
6206
|
* Links a Google account to the currently signed-in user using an ID token.
|
|
6196
6207
|
* This is used to upgrade an anonymous user or to allow an existing user
|
|
@@ -6199,6 +6210,16 @@ declare class AuthService extends BaseService {
|
|
|
6199
6210
|
* @returns The updated user profile.
|
|
6200
6211
|
*/
|
|
6201
6212
|
linkGoogleAccount(idToken: string): Promise<User>;
|
|
6213
|
+
/**
|
|
6214
|
+
* Links a Google account to the currently signed-in user using an authorization code.
|
|
6215
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
6216
|
+
* with the platform-specific client ID, then links the Google account to the current user.
|
|
6217
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
6218
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
6219
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
6220
|
+
* @returns The updated user profile.
|
|
6221
|
+
*/
|
|
6222
|
+
linkGoogleAccountWithAuthCode(authorizationCode: string, redirectUri: string, clientId: string): Promise<User>;
|
|
6202
6223
|
}
|
|
6203
6224
|
|
|
6204
6225
|
/**
|
package/dist/index.js
CHANGED
|
@@ -10395,6 +10395,68 @@ var AuthService = class extends BaseService {
|
|
|
10395
10395
|
throw handleFirebaseError(error);
|
|
10396
10396
|
}
|
|
10397
10397
|
}
|
|
10398
|
+
/**
|
|
10399
|
+
* Signs in a user with a Google authorization code from a mobile client.
|
|
10400
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
10401
|
+
* with the platform-specific client ID (no client secret needed for native apps).
|
|
10402
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
10403
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
10404
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
10405
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
10406
|
+
* @returns The signed-in or newly created user.
|
|
10407
|
+
*/
|
|
10408
|
+
async signInWithGoogleAuthCode(authorizationCode, redirectUri, clientId, initialRole = "patient" /* PATIENT */) {
|
|
10409
|
+
try {
|
|
10410
|
+
console.log("[AUTH] Signing in with Google authorization code (native flow)");
|
|
10411
|
+
console.log("[AUTH] Redirect URI:", redirectUri);
|
|
10412
|
+
console.log("[AUTH] Code length:", authorizationCode.length);
|
|
10413
|
+
if (!clientId) {
|
|
10414
|
+
throw new Error("Google client ID is required for authorization code exchange");
|
|
10415
|
+
}
|
|
10416
|
+
console.log("[AUTH] Using client ID:", `${clientId.substring(0, 20)}...`);
|
|
10417
|
+
const tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
10418
|
+
const params = new URLSearchParams({
|
|
10419
|
+
client_id: clientId,
|
|
10420
|
+
code: authorizationCode,
|
|
10421
|
+
grant_type: "authorization_code",
|
|
10422
|
+
redirect_uri: redirectUri
|
|
10423
|
+
// For native apps, we don't include client_secret
|
|
10424
|
+
});
|
|
10425
|
+
console.log("[AUTH] Making request to Google token endpoint...");
|
|
10426
|
+
const response = await fetch(tokenEndpoint, {
|
|
10427
|
+
method: "POST",
|
|
10428
|
+
headers: {
|
|
10429
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
10430
|
+
},
|
|
10431
|
+
body: params.toString()
|
|
10432
|
+
});
|
|
10433
|
+
if (!response.ok) {
|
|
10434
|
+
const errorText = await response.text();
|
|
10435
|
+
console.error("[AUTH] Google token exchange failed:", {
|
|
10436
|
+
status: response.status,
|
|
10437
|
+
statusText: response.statusText,
|
|
10438
|
+
error: errorText
|
|
10439
|
+
});
|
|
10440
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
10441
|
+
}
|
|
10442
|
+
const tokenData = await response.json();
|
|
10443
|
+
console.log("[AUTH] Token exchange response received:", {
|
|
10444
|
+
hasIdToken: !!tokenData.id_token,
|
|
10445
|
+
hasAccessToken: !!tokenData.access_token,
|
|
10446
|
+
hasRefreshToken: !!tokenData.refresh_token
|
|
10447
|
+
});
|
|
10448
|
+
if (!tokenData.id_token) {
|
|
10449
|
+
console.error("[AUTH] No ID token in response:", tokenData);
|
|
10450
|
+
throw new Error("No ID token received from Google token exchange");
|
|
10451
|
+
}
|
|
10452
|
+
console.log("[AUTH] Successfully obtained ID token from Google");
|
|
10453
|
+
console.log("[AUTH] ID token length:", tokenData.id_token.length);
|
|
10454
|
+
return await this.signInWithGoogleIdToken(tokenData.id_token, initialRole);
|
|
10455
|
+
} catch (error) {
|
|
10456
|
+
console.error("[AUTH] Error in signInWithGoogleAuthCode:", error);
|
|
10457
|
+
throw handleFirebaseError(error);
|
|
10458
|
+
}
|
|
10459
|
+
}
|
|
10398
10460
|
/**
|
|
10399
10461
|
* Links a Google account to the currently signed-in user using an ID token.
|
|
10400
10462
|
* This is used to upgrade an anonymous user or to allow an existing user
|
|
@@ -10428,6 +10490,66 @@ var AuthService = class extends BaseService {
|
|
|
10428
10490
|
throw handleFirebaseError(error);
|
|
10429
10491
|
}
|
|
10430
10492
|
}
|
|
10493
|
+
/**
|
|
10494
|
+
* Links a Google account to the currently signed-in user using an authorization code.
|
|
10495
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
10496
|
+
* with the platform-specific client ID, then links the Google account to the current user.
|
|
10497
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
10498
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
10499
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
10500
|
+
* @returns The updated user profile.
|
|
10501
|
+
*/
|
|
10502
|
+
async linkGoogleAccountWithAuthCode(authorizationCode, redirectUri, clientId) {
|
|
10503
|
+
try {
|
|
10504
|
+
console.log("[AUTH] Linking Google account with authorization code (native flow)");
|
|
10505
|
+
console.log("[AUTH] Redirect URI:", redirectUri);
|
|
10506
|
+
console.log("[AUTH] Code length:", authorizationCode.length);
|
|
10507
|
+
if (!clientId) {
|
|
10508
|
+
throw new Error("Google client ID is required for authorization code exchange");
|
|
10509
|
+
}
|
|
10510
|
+
console.log("[AUTH] Using client ID:", `${clientId.substring(0, 20)}...`);
|
|
10511
|
+
const tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
10512
|
+
const params = new URLSearchParams({
|
|
10513
|
+
client_id: clientId,
|
|
10514
|
+
code: authorizationCode,
|
|
10515
|
+
grant_type: "authorization_code",
|
|
10516
|
+
redirect_uri: redirectUri
|
|
10517
|
+
});
|
|
10518
|
+
console.log("[AUTH] Making request to Google token endpoint...");
|
|
10519
|
+
const response = await fetch(tokenEndpoint, {
|
|
10520
|
+
method: "POST",
|
|
10521
|
+
headers: {
|
|
10522
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
10523
|
+
},
|
|
10524
|
+
body: params.toString()
|
|
10525
|
+
});
|
|
10526
|
+
if (!response.ok) {
|
|
10527
|
+
const errorText = await response.text();
|
|
10528
|
+
console.error("[AUTH] Google token exchange failed:", {
|
|
10529
|
+
status: response.status,
|
|
10530
|
+
statusText: response.statusText,
|
|
10531
|
+
error: errorText
|
|
10532
|
+
});
|
|
10533
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
10534
|
+
}
|
|
10535
|
+
const tokenData = await response.json();
|
|
10536
|
+
console.log("[AUTH] Token exchange response received:", {
|
|
10537
|
+
hasIdToken: !!tokenData.id_token,
|
|
10538
|
+
hasAccessToken: !!tokenData.access_token,
|
|
10539
|
+
hasRefreshToken: !!tokenData.refresh_token
|
|
10540
|
+
});
|
|
10541
|
+
if (!tokenData.id_token) {
|
|
10542
|
+
console.error("[AUTH] No ID token in response:", tokenData);
|
|
10543
|
+
throw new Error("No ID token received from Google token exchange");
|
|
10544
|
+
}
|
|
10545
|
+
console.log("[AUTH] Successfully obtained ID token from Google");
|
|
10546
|
+
console.log("[AUTH] ID token length:", tokenData.id_token.length);
|
|
10547
|
+
return await this.linkGoogleAccount(tokenData.id_token);
|
|
10548
|
+
} catch (error) {
|
|
10549
|
+
console.error("[AUTH] Error in linkGoogleAccountWithAuthCode:", error);
|
|
10550
|
+
throw handleFirebaseError(error);
|
|
10551
|
+
}
|
|
10552
|
+
}
|
|
10431
10553
|
};
|
|
10432
10554
|
|
|
10433
10555
|
// src/services/calendar/calendar.v2.service.ts
|
package/dist/index.mjs
CHANGED
|
@@ -10499,6 +10499,68 @@ var AuthService = class extends BaseService {
|
|
|
10499
10499
|
throw handleFirebaseError(error);
|
|
10500
10500
|
}
|
|
10501
10501
|
}
|
|
10502
|
+
/**
|
|
10503
|
+
* Signs in a user with a Google authorization code from a mobile client.
|
|
10504
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
10505
|
+
* with the platform-specific client ID (no client secret needed for native apps).
|
|
10506
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
10507
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
10508
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
10509
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
10510
|
+
* @returns The signed-in or newly created user.
|
|
10511
|
+
*/
|
|
10512
|
+
async signInWithGoogleAuthCode(authorizationCode, redirectUri, clientId, initialRole = "patient" /* PATIENT */) {
|
|
10513
|
+
try {
|
|
10514
|
+
console.log("[AUTH] Signing in with Google authorization code (native flow)");
|
|
10515
|
+
console.log("[AUTH] Redirect URI:", redirectUri);
|
|
10516
|
+
console.log("[AUTH] Code length:", authorizationCode.length);
|
|
10517
|
+
if (!clientId) {
|
|
10518
|
+
throw new Error("Google client ID is required for authorization code exchange");
|
|
10519
|
+
}
|
|
10520
|
+
console.log("[AUTH] Using client ID:", `${clientId.substring(0, 20)}...`);
|
|
10521
|
+
const tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
10522
|
+
const params = new URLSearchParams({
|
|
10523
|
+
client_id: clientId,
|
|
10524
|
+
code: authorizationCode,
|
|
10525
|
+
grant_type: "authorization_code",
|
|
10526
|
+
redirect_uri: redirectUri
|
|
10527
|
+
// For native apps, we don't include client_secret
|
|
10528
|
+
});
|
|
10529
|
+
console.log("[AUTH] Making request to Google token endpoint...");
|
|
10530
|
+
const response = await fetch(tokenEndpoint, {
|
|
10531
|
+
method: "POST",
|
|
10532
|
+
headers: {
|
|
10533
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
10534
|
+
},
|
|
10535
|
+
body: params.toString()
|
|
10536
|
+
});
|
|
10537
|
+
if (!response.ok) {
|
|
10538
|
+
const errorText = await response.text();
|
|
10539
|
+
console.error("[AUTH] Google token exchange failed:", {
|
|
10540
|
+
status: response.status,
|
|
10541
|
+
statusText: response.statusText,
|
|
10542
|
+
error: errorText
|
|
10543
|
+
});
|
|
10544
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
10545
|
+
}
|
|
10546
|
+
const tokenData = await response.json();
|
|
10547
|
+
console.log("[AUTH] Token exchange response received:", {
|
|
10548
|
+
hasIdToken: !!tokenData.id_token,
|
|
10549
|
+
hasAccessToken: !!tokenData.access_token,
|
|
10550
|
+
hasRefreshToken: !!tokenData.refresh_token
|
|
10551
|
+
});
|
|
10552
|
+
if (!tokenData.id_token) {
|
|
10553
|
+
console.error("[AUTH] No ID token in response:", tokenData);
|
|
10554
|
+
throw new Error("No ID token received from Google token exchange");
|
|
10555
|
+
}
|
|
10556
|
+
console.log("[AUTH] Successfully obtained ID token from Google");
|
|
10557
|
+
console.log("[AUTH] ID token length:", tokenData.id_token.length);
|
|
10558
|
+
return await this.signInWithGoogleIdToken(tokenData.id_token, initialRole);
|
|
10559
|
+
} catch (error) {
|
|
10560
|
+
console.error("[AUTH] Error in signInWithGoogleAuthCode:", error);
|
|
10561
|
+
throw handleFirebaseError(error);
|
|
10562
|
+
}
|
|
10563
|
+
}
|
|
10502
10564
|
/**
|
|
10503
10565
|
* Links a Google account to the currently signed-in user using an ID token.
|
|
10504
10566
|
* This is used to upgrade an anonymous user or to allow an existing user
|
|
@@ -10532,6 +10594,66 @@ var AuthService = class extends BaseService {
|
|
|
10532
10594
|
throw handleFirebaseError(error);
|
|
10533
10595
|
}
|
|
10534
10596
|
}
|
|
10597
|
+
/**
|
|
10598
|
+
* Links a Google account to the currently signed-in user using an authorization code.
|
|
10599
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
10600
|
+
* with the platform-specific client ID, then links the Google account to the current user.
|
|
10601
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
10602
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
10603
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
10604
|
+
* @returns The updated user profile.
|
|
10605
|
+
*/
|
|
10606
|
+
async linkGoogleAccountWithAuthCode(authorizationCode, redirectUri, clientId) {
|
|
10607
|
+
try {
|
|
10608
|
+
console.log("[AUTH] Linking Google account with authorization code (native flow)");
|
|
10609
|
+
console.log("[AUTH] Redirect URI:", redirectUri);
|
|
10610
|
+
console.log("[AUTH] Code length:", authorizationCode.length);
|
|
10611
|
+
if (!clientId) {
|
|
10612
|
+
throw new Error("Google client ID is required for authorization code exchange");
|
|
10613
|
+
}
|
|
10614
|
+
console.log("[AUTH] Using client ID:", `${clientId.substring(0, 20)}...`);
|
|
10615
|
+
const tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
10616
|
+
const params = new URLSearchParams({
|
|
10617
|
+
client_id: clientId,
|
|
10618
|
+
code: authorizationCode,
|
|
10619
|
+
grant_type: "authorization_code",
|
|
10620
|
+
redirect_uri: redirectUri
|
|
10621
|
+
});
|
|
10622
|
+
console.log("[AUTH] Making request to Google token endpoint...");
|
|
10623
|
+
const response = await fetch(tokenEndpoint, {
|
|
10624
|
+
method: "POST",
|
|
10625
|
+
headers: {
|
|
10626
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
10627
|
+
},
|
|
10628
|
+
body: params.toString()
|
|
10629
|
+
});
|
|
10630
|
+
if (!response.ok) {
|
|
10631
|
+
const errorText = await response.text();
|
|
10632
|
+
console.error("[AUTH] Google token exchange failed:", {
|
|
10633
|
+
status: response.status,
|
|
10634
|
+
statusText: response.statusText,
|
|
10635
|
+
error: errorText
|
|
10636
|
+
});
|
|
10637
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
10638
|
+
}
|
|
10639
|
+
const tokenData = await response.json();
|
|
10640
|
+
console.log("[AUTH] Token exchange response received:", {
|
|
10641
|
+
hasIdToken: !!tokenData.id_token,
|
|
10642
|
+
hasAccessToken: !!tokenData.access_token,
|
|
10643
|
+
hasRefreshToken: !!tokenData.refresh_token
|
|
10644
|
+
});
|
|
10645
|
+
if (!tokenData.id_token) {
|
|
10646
|
+
console.error("[AUTH] No ID token in response:", tokenData);
|
|
10647
|
+
throw new Error("No ID token received from Google token exchange");
|
|
10648
|
+
}
|
|
10649
|
+
console.log("[AUTH] Successfully obtained ID token from Google");
|
|
10650
|
+
console.log("[AUTH] ID token length:", tokenData.id_token.length);
|
|
10651
|
+
return await this.linkGoogleAccount(tokenData.id_token);
|
|
10652
|
+
} catch (error) {
|
|
10653
|
+
console.error("[AUTH] Error in linkGoogleAccountWithAuthCode:", error);
|
|
10654
|
+
throw handleFirebaseError(error);
|
|
10655
|
+
}
|
|
10656
|
+
}
|
|
10535
10657
|
};
|
|
10536
10658
|
|
|
10537
10659
|
// src/services/calendar/calendar.v2.service.ts
|
package/package.json
CHANGED
|
@@ -903,6 +903,88 @@ export class AuthService extends BaseService {
|
|
|
903
903
|
}
|
|
904
904
|
}
|
|
905
905
|
|
|
906
|
+
/**
|
|
907
|
+
* Signs in a user with a Google authorization code from a mobile client.
|
|
908
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
909
|
+
* with the platform-specific client ID (no client secret needed for native apps).
|
|
910
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
911
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
912
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
913
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
914
|
+
* @returns The signed-in or newly created user.
|
|
915
|
+
*/
|
|
916
|
+
async signInWithGoogleAuthCode(
|
|
917
|
+
authorizationCode: string,
|
|
918
|
+
redirectUri: string,
|
|
919
|
+
clientId: string,
|
|
920
|
+
initialRole: UserRole = UserRole.PATIENT,
|
|
921
|
+
): Promise<User> {
|
|
922
|
+
try {
|
|
923
|
+
console.log('[AUTH] Signing in with Google authorization code (native flow)');
|
|
924
|
+
console.log('[AUTH] Redirect URI:', redirectUri);
|
|
925
|
+
console.log('[AUTH] Code length:', authorizationCode.length);
|
|
926
|
+
|
|
927
|
+
if (!clientId) {
|
|
928
|
+
throw new Error('Google client ID is required for authorization code exchange');
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
console.log('[AUTH] Using client ID:', `${clientId.substring(0, 20)}...`);
|
|
932
|
+
|
|
933
|
+
// Exchange authorization code for tokens using Google's OAuth2 API
|
|
934
|
+
// For native apps, we don't need a client secret
|
|
935
|
+
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
|
936
|
+
|
|
937
|
+
const params = new URLSearchParams({
|
|
938
|
+
client_id: clientId,
|
|
939
|
+
code: authorizationCode,
|
|
940
|
+
grant_type: 'authorization_code',
|
|
941
|
+
redirect_uri: redirectUri,
|
|
942
|
+
// For native apps, we don't include client_secret
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
console.log('[AUTH] Making request to Google token endpoint...');
|
|
946
|
+
|
|
947
|
+
const response = await fetch(tokenEndpoint, {
|
|
948
|
+
method: 'POST',
|
|
949
|
+
headers: {
|
|
950
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
951
|
+
},
|
|
952
|
+
body: params.toString(),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
if (!response.ok) {
|
|
956
|
+
const errorText = await response.text();
|
|
957
|
+
console.error('[AUTH] Google token exchange failed:', {
|
|
958
|
+
status: response.status,
|
|
959
|
+
statusText: response.statusText,
|
|
960
|
+
error: errorText,
|
|
961
|
+
});
|
|
962
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const tokenData = await response.json();
|
|
966
|
+
console.log('[AUTH] Token exchange response received:', {
|
|
967
|
+
hasIdToken: !!tokenData.id_token,
|
|
968
|
+
hasAccessToken: !!tokenData.access_token,
|
|
969
|
+
hasRefreshToken: !!tokenData.refresh_token,
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
if (!tokenData.id_token) {
|
|
973
|
+
console.error('[AUTH] No ID token in response:', tokenData);
|
|
974
|
+
throw new Error('No ID token received from Google token exchange');
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
console.log('[AUTH] Successfully obtained ID token from Google');
|
|
978
|
+
console.log('[AUTH] ID token length:', tokenData.id_token.length);
|
|
979
|
+
|
|
980
|
+
// Now sign in with the ID token
|
|
981
|
+
return await this.signInWithGoogleIdToken(tokenData.id_token, initialRole);
|
|
982
|
+
} catch (error) {
|
|
983
|
+
console.error('[AUTH] Error in signInWithGoogleAuthCode:', error);
|
|
984
|
+
throw handleFirebaseError(error);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
906
988
|
/**
|
|
907
989
|
* Links a Google account to the currently signed-in user using an ID token.
|
|
908
990
|
* This is used to upgrade an anonymous user or to allow an existing user
|
|
@@ -941,4 +1023,82 @@ export class AuthService extends BaseService {
|
|
|
941
1023
|
throw handleFirebaseError(error);
|
|
942
1024
|
}
|
|
943
1025
|
}
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Links a Google account to the currently signed-in user using an authorization code.
|
|
1029
|
+
* This method directly exchanges the authorization code for tokens using Google's OAuth2 API
|
|
1030
|
+
* with the platform-specific client ID, then links the Google account to the current user.
|
|
1031
|
+
* @param authorizationCode - The Google authorization code obtained from the mobile app.
|
|
1032
|
+
* @param redirectUri - The redirect URI used in the OAuth flow.
|
|
1033
|
+
* @param clientId - The platform-specific Google OAuth client ID.
|
|
1034
|
+
* @returns The updated user profile.
|
|
1035
|
+
*/
|
|
1036
|
+
async linkGoogleAccountWithAuthCode(
|
|
1037
|
+
authorizationCode: string,
|
|
1038
|
+
redirectUri: string,
|
|
1039
|
+
clientId: string,
|
|
1040
|
+
): Promise<User> {
|
|
1041
|
+
try {
|
|
1042
|
+
console.log('[AUTH] Linking Google account with authorization code (native flow)');
|
|
1043
|
+
console.log('[AUTH] Redirect URI:', redirectUri);
|
|
1044
|
+
console.log('[AUTH] Code length:', authorizationCode.length);
|
|
1045
|
+
|
|
1046
|
+
if (!clientId) {
|
|
1047
|
+
throw new Error('Google client ID is required for authorization code exchange');
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
console.log('[AUTH] Using client ID:', `${clientId.substring(0, 20)}...`);
|
|
1051
|
+
|
|
1052
|
+
// Exchange authorization code for tokens using Google's OAuth2 API
|
|
1053
|
+
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
|
1054
|
+
|
|
1055
|
+
const params = new URLSearchParams({
|
|
1056
|
+
client_id: clientId,
|
|
1057
|
+
code: authorizationCode,
|
|
1058
|
+
grant_type: 'authorization_code',
|
|
1059
|
+
redirect_uri: redirectUri,
|
|
1060
|
+
});
|
|
1061
|
+
|
|
1062
|
+
console.log('[AUTH] Making request to Google token endpoint...');
|
|
1063
|
+
|
|
1064
|
+
const response = await fetch(tokenEndpoint, {
|
|
1065
|
+
method: 'POST',
|
|
1066
|
+
headers: {
|
|
1067
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
1068
|
+
},
|
|
1069
|
+
body: params.toString(),
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
if (!response.ok) {
|
|
1073
|
+
const errorText = await response.text();
|
|
1074
|
+
console.error('[AUTH] Google token exchange failed:', {
|
|
1075
|
+
status: response.status,
|
|
1076
|
+
statusText: response.statusText,
|
|
1077
|
+
error: errorText,
|
|
1078
|
+
});
|
|
1079
|
+
throw new Error(`Google token exchange failed: ${response.status} - ${errorText}`);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
const tokenData = await response.json();
|
|
1083
|
+
console.log('[AUTH] Token exchange response received:', {
|
|
1084
|
+
hasIdToken: !!tokenData.id_token,
|
|
1085
|
+
hasAccessToken: !!tokenData.access_token,
|
|
1086
|
+
hasRefreshToken: !!tokenData.refresh_token,
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
if (!tokenData.id_token) {
|
|
1090
|
+
console.error('[AUTH] No ID token in response:', tokenData);
|
|
1091
|
+
throw new Error('No ID token received from Google token exchange');
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
console.log('[AUTH] Successfully obtained ID token from Google');
|
|
1095
|
+
console.log('[AUTH] ID token length:', tokenData.id_token.length);
|
|
1096
|
+
|
|
1097
|
+
// Now link the Google account using the ID token
|
|
1098
|
+
return await this.linkGoogleAccount(tokenData.id_token);
|
|
1099
|
+
} catch (error) {
|
|
1100
|
+
console.error('[AUTH] Error in linkGoogleAccountWithAuthCode:', error);
|
|
1101
|
+
throw handleFirebaseError(error);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
944
1104
|
}
|