Skip to content

Commit 2c0819c

Browse files
committed
feat(gotrue): implement linkIdentityWithIdToken for OIDC support
- Add linkIdentityWithIdToken method to link identities using ID tokens - Support OAuth providers with ID token verification - Include nonce and access token validation for enhanced security - Emit userUpdated event when identity is successfully linked Closes CLIBS-282
1 parent 9b42fab commit 2c0819c

File tree

1 file changed

+62
-7
lines changed

1 file changed

+62
-7
lines changed

packages/gotrue/lib/src/gotrue_client.dart

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -390,18 +390,20 @@ class GoTrueClient {
390390
String? nonce,
391391
String? captchaToken,
392392
}) async {
393+
final body = {
394+
'provider': provider.snakeCase,
395+
'id_token': idToken,
396+
'nonce': nonce,
397+
'gotrue_meta_security': {'captcha_token': captchaToken},
398+
'access_token': accessToken,
399+
};
400+
393401
final response = await _fetch.request(
394402
'$_url/token',
395403
RequestMethodType.post,
396404
options: GotrueRequestOptions(
397405
headers: _headers,
398-
body: {
399-
'provider': provider.snakeCase,
400-
'id_token': idToken,
401-
'nonce': nonce,
402-
'gotrue_meta_security': {'captcha_token': captchaToken},
403-
'access_token': accessToken,
404-
},
406+
body: body,
405407
query: {'grant_type': 'id_token'},
406408
),
407409
);
@@ -902,6 +904,59 @@ class GoTrueClient {
902904
return res.user?.identities ?? [];
903905
}
904906

907+
/// Link an identity to the current user using an ID token.
908+
///
909+
/// [provider] is the OAuth provider
910+
///
911+
/// [idToken] is the ID token from the OAuth provider
912+
///
913+
/// [accessToken] is the access token from the OAuth provider
914+
///
915+
/// [nonce] is the nonce used for the OAuth flow
916+
///
917+
/// [captchaToken] is the verification token received when the user
918+
/// completes the captcha on the app.
919+
Future<AuthResponse> linkIdentityWithIdToken({
920+
required OAuthProvider provider,
921+
required String idToken,
922+
String? accessToken,
923+
String? nonce,
924+
String? captchaToken,
925+
}) async {
926+
final body = {
927+
'provider': provider.snakeCase,
928+
'id_token': idToken,
929+
'nonce': nonce,
930+
'gotrue_meta_security': {'captcha_token': captchaToken},
931+
'access_token': accessToken,
932+
'link_identity': true,
933+
};
934+
935+
final response = await _fetch.request(
936+
'$_url/token',
937+
RequestMethodType.post,
938+
options: GotrueRequestOptions(
939+
headers: _headers,
940+
jwt: _currentSession?.accessToken,
941+
body: body,
942+
query: {'grant_type': 'id_token'},
943+
),
944+
);
945+
946+
final authResponse = AuthResponse.fromJson(response);
947+
948+
if (authResponse.session == null) {
949+
throw AuthException(
950+
'An error occurred on token verification.',
951+
);
952+
}
953+
954+
_saveSession(authResponse.session!);
955+
notifyAllSubscribers(AuthChangeEvent.userUpdated);
956+
957+
return authResponse;
958+
}
959+
905960
/// Returns the URL to link the user's identity with an OAuth provider.
906961
Future<OAuthResponse> getLinkIdentityUrl(
907962
OAuthProvider provider, {

0 commit comments

Comments
 (0)