Skip to content

Commit

Permalink
feat(authentication): support serverAuthCode for Google Sign-in (#442)
Browse files Browse the repository at this point in the history
  • Loading branch information
robingenz authored Sep 27, 2023
1 parent 2ea241b commit 12e0052
Show file tree
Hide file tree
Showing 14 changed files with 108 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/new-lemons-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@capacitor-firebase/authentication': minor
---

feat: support `forceCodeForRefreshToken` for Google Sign-in
3 changes: 2 additions & 1 deletion packages/authentication/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,7 @@ Remove all listeners for this plugin.
| **`nonce`** | <code>string</code> | The random string used to make sure that the ID token you get was granted specifically in response to your app's authentication request. | 0.1.0 |
| **`providerId`** | <code>string</code> | The authentication provider ID for the credential. | 0.1.0 |
| **`secret`** | <code>string</code> | The OAuth access token secret associated with the credential if it belongs to an OAuth 1.0 provider. | 0.1.0 |
| **`serverAuthCode`** | <code>string</code> | The server auth code. Only available for Google Sign-in and Play Games Sign-In on Android and iOS. | 5.2.0 |


#### AdditionalUserInfo
Expand Down Expand Up @@ -1633,7 +1634,7 @@ Remove all listeners for this plugin.
| Prop | Type | Description | Default | Since |
| ---------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ----- |
| **`customParameters`** | <code>SignInCustomParameter[]</code> | Configures custom parameters to be passed to the identity provider during the OAuth sign-in flow. Supports Apple, Facebook, GitHub, Google, Microsoft, Twitter and Yahoo on Web. Supports Apple, GitHub, Microsoft, Twitter and Yahoo on Android. Supports Facebook, GitHub, Microsoft, Twitter and Yahoo on iOS. | | 1.1.0 |
| **`mode`** | <code>'popup' \| 'redirect'</code> | Whether to use the popup-based OAuth authentication flow or the full-page redirect flow. If you choose `redirect`, you will get the result of the call via the `authStateChange` listener after the redirect. | <code>'popup'</code> | 1.3.0 |
| **`mode`** | <code>'popup' \| 'redirect'</code> | Whether to use the popup-based OAuth authentication flow or the full-page redirect flow. If you choose `redirect`, you will get the result of the call via the `authStateChange` listener after the redirect. Only available for Web. | <code>'popup'</code> | 1.3.0 |
| **`scopes`** | <code>string[]</code> | Scopes to request from provider. Supports Apple, Facebook, GitHub, Google, Microsoft, Twitter and Yahoo on Web. Supports Apple, GitHub, Google, Microsoft, Twitter, Yahoo and Play Games on Android. Supports Facebook, GitHub, Google, Microsoft, Twitter and Yahoo on iOS. | | 1.1.0 |


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ public void handleSuccessfulSignIn(
@Nullable String idToken,
@Nullable String nonce,
@Nullable String accessToken,
@Nullable String serverAuthCode,
@Nullable AdditionalUserInfo additionalUserInfo
) {
boolean skipNativeAuth = call.getBoolean("skipNativeAuth", this.config.getSkipNativeAuth());
Expand All @@ -677,6 +678,7 @@ public void handleSuccessfulSignIn(
idToken,
nonce,
accessToken,
serverAuthCode,
additionalUserInfo
);
call.resolve(signInResult);
Expand Down Expand Up @@ -732,7 +734,8 @@ public void handleSuccessfulLink(
@Nullable AuthCredential credential,
@Nullable String idToken,
@Nullable String nonce,
@Nullable String accessToken
@Nullable String accessToken,
@Nullable String serverAuthCode
) {
FirebaseUser user = firebaseAuthInstance.getCurrentUser();
if (user == null) {
Expand All @@ -746,7 +749,7 @@ public void handleSuccessfulLink(
task -> {
if (task.isSuccessful()) {
final AuthResult authResult = task.getResult();
handleSuccessfulLink(call, authResult, idToken, nonce, accessToken);
handleSuccessfulLink(call, authResult, idToken, nonce, accessToken, serverAuthCode);
} else {
Exception exception = task.getException();
Logger.error(TAG, exception.getMessage(), exception);
Expand All @@ -762,14 +765,16 @@ public void handleSuccessfulLink(
final AuthResult authResult,
@Nullable String idToken,
@Nullable String nonce,
@Nullable String accessToken
@Nullable String accessToken,
@Nullable String serverAuthCode
) {
JSObject linkResult = FirebaseAuthenticationHelper.createSignInResult(
authResult.getUser(),
authResult.getCredential(),
idToken,
nonce,
accessToken,
serverAuthCode,
authResult.getAdditionalUserInfo()
);
call.resolve(linkResult);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,27 @@ public static JSObject createSignInResult(
@Nullable String nonce,
@Nullable String accessToken,
@Nullable AdditionalUserInfo additionalUserInfo
) {
return FirebaseAuthenticationHelper.createSignInResult(user, credential, idToken, nonce, accessToken, null, additionalUserInfo);
}

public static JSObject createSignInResult(
@Nullable FirebaseUser user,
@Nullable AuthCredential credential,
@Nullable String idToken,
@Nullable String nonce,
@Nullable String accessToken,
@Nullable String serverAuthCode,
@Nullable AdditionalUserInfo additionalUserInfo
) {
JSObject userResult = FirebaseAuthenticationHelper.createUserResult(user);
JSObject credentialResult = FirebaseAuthenticationHelper.createCredentialResult(credential, idToken, nonce, accessToken);
JSObject credentialResult = FirebaseAuthenticationHelper.createCredentialResult(
credential,
idToken,
nonce,
accessToken,
serverAuthCode
);
JSObject additionalUserInfoResult = FirebaseAuthenticationHelper.createAdditionalUserInfoResult(additionalUserInfo);
JSObject result = new JSObject();
result.put("user", userResult);
Expand Down Expand Up @@ -85,7 +103,8 @@ public static JSObject createCredentialResult(
@Nullable AuthCredential credential,
@Nullable String idToken,
@Nullable String nonce,
@Nullable String accessToken
@Nullable String accessToken,
@Nullable String serverAuthCode
) {
if (credential == null && idToken == null && nonce == null && accessToken == null) {
return null;
Expand Down Expand Up @@ -117,6 +136,9 @@ public static JSObject createCredentialResult(
if (accessToken != null) {
result.put("accessToken", accessToken);
}
if (serverAuthCode != null) {
result.put("serverAuthCode", serverAuthCode);
}
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ private void startActivityForLink(final PluginCall call, OAuthProvider.Builder p
pluginImplementation
.getCurrentUser()
.startActivityForLinkWithProvider(pluginImplementation.getPlugin().getActivity(), provider.build())
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, currentNonce, null))
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, currentNonce, null, null))
.addOnFailureListener(exception -> pluginImplementation.handleFailedLink(call, null, exception));
}

private void finishActivityForLink(final PluginCall call, Task<AuthResult> pendingResultTask) {
pendingResultTask
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, currentNonce, null))
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, currentNonce, null, null))
.addOnFailureListener(exception -> pluginImplementation.handleFailedLink(call, null, exception));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ private void handleSuccessCallback(LoginResult loginResult) {
return;
}
if (isLink) {
pluginImplementation.handleSuccessfulLink(savedCall, credential, null, null, accessTokenString);
pluginImplementation.handleSuccessfulLink(savedCall, credential, null, null, accessTokenString, null);
} else {
pluginImplementation.handleSuccessfulSignIn(savedCall, credential, null, null, accessTokenString, null);
pluginImplementation.handleSuccessfulSignIn(savedCall, credential, null, null, accessTokenString, null, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void handleOnActivityResult(@NonNull final PluginCall call, @NonNull Acti
try {
GoogleSignInAccount account = task.getResult(ApiException.class);
String idToken = account.getIdToken();
String serverAuthCode = account.getServerAuthCode();
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
// Get Access Token and resolve
new Thread(
Expand All @@ -77,9 +78,9 @@ public void handleOnActivityResult(@NonNull final PluginCall call, @NonNull Acti
return;
}
if (isLink) {
pluginImplementation.handleSuccessfulLink(call, credential, idToken, null, accessToken);
pluginImplementation.handleSuccessfulLink(call, credential, idToken, null, accessToken, serverAuthCode);
} else {
pluginImplementation.handleSuccessfulSignIn(call, credential, idToken, null, accessToken, null);
pluginImplementation.handleSuccessfulSignIn(call, credential, idToken, null, accessToken, serverAuthCode, null);
}
}
)
Expand All @@ -98,8 +99,9 @@ private GoogleSignInClient buildGoogleSignInClient() {
}

private GoogleSignInClient buildGoogleSignInClient(@Nullable PluginCall call) {
GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
GoogleSignInOptions.Builder googleSignInOptionsBuilder = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestServerAuthCode(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail();

if (call != null) {
Expand All @@ -108,14 +110,14 @@ private GoogleSignInClient buildGoogleSignInClient(@Nullable PluginCall call) {
try {
List<String> scopeList = scopes.toList();
for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
googleSignInOptionsBuilder = googleSignInOptionsBuilder.requestScopes(new Scope(scope));
}
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "buildGoogleSignInClient failed.", exception);
}
}
}

return GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gsob.build());
return GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), googleSignInOptionsBuilder.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ private void startActivityForLink(final PluginCall call, OAuthProvider.Builder p
pluginImplementation
.getCurrentUser()
.startActivityForLinkWithProvider(pluginImplementation.getPlugin().getActivity(), provider.build())
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, null, null))
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, null, null, null))
.addOnFailureListener(exception -> pluginImplementation.handleFailedLink(call, null, exception));
}

private void finishActivityForLink(final PluginCall call, Task<AuthResult> pendingResultTask) {
pendingResultTask
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, null, null))
.addOnSuccessListener(authResult -> pluginImplementation.handleSuccessfulLink(call, authResult, null, null, null, null))
.addOnFailureListener(exception -> pluginImplementation.handleFailedLink(call, null, exception));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public void handleOnActivityResult(@NonNull final PluginCall call, @NonNull Acti
AuthCredential credential = PlayGamesAuthProvider.getCredential(serverAuthCode);
String idToken = account.getIdToken();
if (isLink) {
pluginImplementation.handleSuccessfulLink(call, credential, idToken, null, null);
pluginImplementation.handleSuccessfulLink(call, credential, idToken, null, null, serverAuthCode);
} else {
pluginImplementation.handleSuccessfulSignIn(call, credential, idToken, null, null, null);
pluginImplementation.handleSuccessfulSignIn(call, credential, idToken, null, null, serverAuthCode, null);
}
} catch (ApiException exception) {
if (isLink) {
Expand All @@ -75,7 +75,7 @@ private GoogleSignInClient buildGoogleSignInClient() {
}

private GoogleSignInClient buildGoogleSignInClient(@Nullable final PluginCall call) {
GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
GoogleSignInOptions.Builder googleSignInOptionsBuilder = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestServerAuthCode(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail();
Expand All @@ -86,14 +86,14 @@ private GoogleSignInClient buildGoogleSignInClient(@Nullable final PluginCall ca
try {
List<String> scopeList = scopes.toList();
for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
googleSignInOptionsBuilder = googleSignInOptionsBuilder.requestScopes(new Scope(scope));
}
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "buildGoogleSignInClient failed.", exception);
}
}
}

return GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gsob.build());
return GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), googleSignInOptionsBuilder.build());
}
}
2 changes: 2 additions & 0 deletions packages/authentication/ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(FRAMEWORK_SEARCH_PATHS)\n$(FRAMEWORK_SEARCH_PATHS)\n$(FRAMEWORK_SEARCH_PATHS)";
ONLY_ACTIVE_ARCH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D RGCFA_INCLUDE_GOOGLE -D RGCFA_INCLUDE_FACEBOOK";
PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.Plugin;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
Expand All @@ -618,6 +619,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(FRAMEWORK_SEARCH_PATHS)";
ONLY_ACTIVE_ARCH = NO;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -D RGCFA_INCLUDE_GOOGLE -D RGCFA_INCLUDE_FACEBOOK";
PRODUCT_BUNDLE_IDENTIFIER = com.getcapacitor.Plugin;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
Expand Down
Loading

0 comments on commit 12e0052

Please sign in to comment.