Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(authentication): support OAuth 2.0 scopes #80

Merged
merged 14 commits into from
May 21, 2022
5 changes: 5 additions & 0 deletions .changeset/four-falcons-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@capacitor-firebase/authentication": minor
---

Added ability to request scopes when authenticating.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Pod::Spec.new do |s|

s.subspec 'Google' do |google|
google.xcconfig = { 'OTHER_SWIFT_FLAGS' => '$(inherited) -DRGCFA_INCLUDE_GOOGLE' }
google.dependency 'GoogleSignIn', '6.0.0'
google.dependency 'GoogleSignIn', '6.2.0'
end

s.subspec 'Facebook' do |facebook|
Expand Down
1 change: 1 addition & 0 deletions packages/authentication/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,7 @@ Remove all listeners for this plugin.
| Prop | Type | Description |
| ---------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------- |
| **`customParameters`** | <code>SignInCustomParameter[]</code> | Configures custom parameters to be passed to the identity provider during the OAuth sign-in flow. |
| **`scopes`** | <code>string[]</code> | Scopes to request from provider. |


#### SignInCustomParameter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,15 @@ private void applySignInConfig(PluginCall call, OAuthProvider.Builder provider)
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}

JSArray scopes = call.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
provider.setScopes(scopeList);
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import com.getcapacitor.JSArray;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FacebookAuthProvider;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthentication;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthenticationPlugin;
import java.util.List;
import org.json.JSONException;

public class FacebookAuthProviderHandler {

Expand All @@ -29,6 +33,7 @@ public FacebookAuthProviderHandler(FirebaseAuthentication pluginImplementation)
try {
mCallbackManager = CallbackManager.Factory.create();
loginButton = new LoginButton(pluginImplementation.getPlugin().getContext());

loginButton.setPermissions("email", "public_profile");
loginButton.registerCallback(
mCallbackManager,
Expand All @@ -54,8 +59,23 @@ public void onError(FacebookException exception) {
}
}

private void applySignInConfig(LoginButton button) {
JSArray scopes = this.savedCall.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
scopeList.add("email");
scopeList.add("public_profile");
button.setPermissions(scopeList);
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}
}

public void signIn(PluginCall call) {
savedCall = call;
this.savedCall = call;
this.applySignInConfig(this.loginButton);
this.loginButton.performClick();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
package dev.robingenz.capacitorjs.plugins.firebase.authentication.handlers;

import android.content.Intent;
import android.util.Log;
import androidx.activity.result.ActivityResult;
import androidx.annotation.Nullable;

import com.getcapacitor.JSArray;
import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.OAuthCredential;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthentication;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthenticationPlugin;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.R;
import java.util.List;
import org.json.JSONException;

public class GoogleAuthProviderHandler {

Expand All @@ -23,14 +31,11 @@ public class GoogleAuthProviderHandler {

public GoogleAuthProviderHandler(FirebaseAuthentication pluginImplementation) {
this.pluginImplementation = pluginImplementation;
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gso);
this.buildGoogleSignInClient(null);
}

public void signIn(PluginCall call) {
this.buildGoogleSignInClient(call);
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
pluginImplementation.startActivityForResult(call, signInIntent, "handleGoogleAuthProviderActivityResult");
}
Expand All @@ -51,4 +56,26 @@ public void handleOnActivityResult(PluginCall call, ActivityResult result) {
pluginImplementation.handleFailedSignIn(call, null, exception);
}
}

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

if (call != null) {
JSArray scopes = call.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
}
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "buildGoogleSignInClient failed.", exception);
}
}
}

mGoogleSignInClient = GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gsob.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,15 @@ private void applySignInConfig(PluginCall call, OAuthProvider.Builder provider)
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}

JSArray scopes = call.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
provider.setScopes(scopeList);
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
package dev.robingenz.capacitorjs.plugins.firebase.authentication.handlers;

import android.content.Intent;
import android.util.Log;
import androidx.activity.result.ActivityResult;
import androidx.annotation.Nullable;

import com.getcapacitor.JSArray;
import com.getcapacitor.PluginCall;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.PlayGamesAuthProvider;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthentication;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.FirebaseAuthenticationPlugin;
import dev.robingenz.capacitorjs.plugins.firebase.authentication.R;
import java.util.List;
import org.json.JSONException;

public class PlayGamesAuthProviderHandler {

Expand All @@ -21,13 +29,33 @@ public class PlayGamesAuthProviderHandler {

public PlayGamesAuthProviderHandler(FirebaseAuthentication pluginImplementation) {
this.pluginImplementation = pluginImplementation;
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestServerAuthCode(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gso);
this.buildGoogleSignInClient(null);
}

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

if (call != null) {
JSArray scopes = call.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
}
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "buildGoogleSignInClient failed.", exception);
}
}
}

mGoogleSignInClient = GoogleSignIn.getClient(pluginImplementation.getPlugin().getActivity(), gsob.build());
}

public void signIn(PluginCall call) {
this.buildGoogleSignInClient(call);
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
pluginImplementation.startActivityForResult(call, signInIntent, "handlePlayGamesAuthProviderActivityResult");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ class FacebookAuthProviderHandler: NSObject {

func signIn(call: CAPPluginCall) {
#if RGCFA_INCLUDE_FACEBOOK
let scopes = call.getArray("scopes", String.self) ?? []
DispatchQueue.main.async {
self.loginManager.logIn(permissions: ["email", "public_profile"], from: self.pluginImplementation.getPlugin().bridge?.viewController) { result, error in
self.loginManager.logIn(permissions: ["email", "public_profile"] + scopes, from: self.pluginImplementation.getPlugin().bridge?.viewController) { result, error in
if let error = error {
self.pluginImplementation.handleFailedSignIn(message: nil, error: error)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ class GoogleAuthProviderHandler: NSObject {
guard let clientId = FirebaseApp.app()?.options.clientID else { return }
let config = GIDConfiguration(clientID: clientId)
guard let controller = self.pluginImplementation.getPlugin().bridge?.viewController else { return }
let scopes = call.getArray("scopes", String.self) ?? []

DispatchQueue.main.async {
GIDSignIn.sharedInstance.signIn(with: config, presenting: controller) { user, error in
GIDSignIn.sharedInstance.signIn(with: config, presenting: controller, hint: nil, additionalScopes: scopes, callback: { user, error in
if let error = error {
self.pluginImplementation.handleFailedSignIn(message: nil, error: error)
return
Expand All @@ -33,7 +34,7 @@ class GoogleAuthProviderHandler: NSObject {

let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
self.pluginImplementation.handleSuccessfulSignIn(credential: credential, idToken: idToken, nonce: nil, accessToken: accessToken)
}
})
}
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class OAuthProviderHandler: NSObject {
}
provider.customParameters?[key] = value
}

let scopes = call.getArray("scopes", String.self) ?? []
provider.scopes = scopes
}

private func startSignInFlow() {
Expand Down
2 changes: 1 addition & 1 deletion packages/authentication/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ end
target 'Plugin' do
capacitor_pods
pod 'Firebase/Auth', '8.13.0'
pod 'GoogleSignIn', '6.0.0'
pod 'GoogleSignIn', '6.2.0'
pod 'FBSDKCoreKit', '11.1.0'
pod 'FBSDKLoginKit', '11.1.0'
end
Expand Down
4 changes: 4 additions & 0 deletions packages/authentication/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ export interface SignInOptions {
* Configures custom parameters to be passed to the identity provider during the OAuth sign-in flow.
*/
customParameters?: SignInCustomParameter[];
/**
* Scopes to request from provider.
*/
scopes?: string[];
}

export interface SignInCustomParameter {
Expand Down
Loading