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
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 @@ -10,6 +10,7 @@
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;
Expand Down Expand Up @@ -58,20 +59,23 @@ public void onError(FacebookException exception) {
}
}

public void signIn(PluginCall call) {
savedCall = call;
JSArray scopes = call.getArray("scopes");
private void applySignInConfig() {
nkalupahana marked this conversation as resolved.
Show resolved Hide resolved
JSArray scopes = this.savedCall.getArray("scopes");
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
scopeList.add("email");
scopeList.add("public_profile");
this.loginButton.setPermissions(scopeList);
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "signIn (applying scopes) failed.", exception);
Log.e(FirebaseAuthenticationPlugin.TAG, "applySignInConfig failed.", exception);
}
}
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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;
Expand All @@ -29,33 +31,33 @@ 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) {
JSArray scopes = call.getArray("scopes");
// Got scopes? Need to get the client again with these new options.
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail();
private void buildGoogleSignInClient(@Nullable PluginCall call) {
nkalupahana marked this conversation as resolved.
Show resolved Hide resolved
GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail();

for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
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());
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "signIn (applying scopes) 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, "handleGoogleAuthProviderActivityResult");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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;
Expand All @@ -27,32 +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);
}

public void signIn(PluginCall call) {
JSArray scopes = call.getArray("scopes");
// Got scopes? Need to get the client again with these new options.
if (scopes != null) {
try {
List<String> scopeList = scopes.toList();
GoogleSignInOptions.Builder gsob = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(pluginImplementation.getPlugin().getContext().getString(R.string.default_web_client_id))
.requestEmail();
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();

for (String scope : scopeList) {
gsob = gsob.requestScopes(new Scope(scope));
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());
} catch (JSONException exception) {
Log.e(FirebaseAuthenticationPlugin.TAG, "signIn (applying scopes) 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,7 +22,7 @@ class GoogleAuthProviderHandler: NSObject {
let scopes = call.getArray("scopes", String.self) ?? []

DispatchQueue.main.async {
GIDSignIn.sharedInstance.signIn(with: config, presenting: controller, hint: "gmail.com", additionalScopes: scopes, callback: { 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 Down
1 change: 0 additions & 1 deletion packages/authentication/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ 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.
*/
Expand Down
36 changes: 15 additions & 21 deletions packages/authentication/src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,23 +122,17 @@ export class FirebaseAuthenticationWeb
auth.languageCode = options.languageCode;
}

// Attach scopes to provider if they're there.
// Takes in either a string describing an OAuthProvider, or specific other providers.
private createProviderWithScopes(
provider: string | GoogleAuthProvider | FacebookAuthProvider,
options?: SignInOptions,
) {
if (typeof provider === 'string') provider = new OAuthProvider(provider);
private applySignInConfig(provider: OAuthProvider | GoogleAuthProvider | FacebookAuthProvider, options?: SignInOptions) {
if (options?.scopes) {
for (const scope of options.scopes) {
provider.addScope(scope);
}
}
return provider;
}

public async signInWithApple(options?: SignInOptions): Promise<SignInResult> {
const provider = this.createProviderWithScopes('apple.com', options);
const provider = new OAuthProvider('apple.com');
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = OAuthProvider.credentialFromResult(result);
Expand Down Expand Up @@ -168,10 +162,8 @@ export class FirebaseAuthenticationWeb
public async signInWithFacebook(
options?: SignInOptions,
): Promise<SignInResult> {
const provider = this.createProviderWithScopes(
new FacebookAuthProvider(),
options,
);
const provider = new FacebookAuthProvider();
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = FacebookAuthProvider.credentialFromResult(result);
Expand All @@ -181,7 +173,8 @@ export class FirebaseAuthenticationWeb
public async signInWithGithub(
options?: SignInOptions,
): Promise<SignInResult> {
const provider = this.createProviderWithScopes('github.com', options);
const provider = new OAuthProvider('github.com');
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = OAuthProvider.credentialFromResult(result);
Expand All @@ -191,10 +184,8 @@ export class FirebaseAuthenticationWeb
public async signInWithGoogle(
options?: SignInOptions,
): Promise<SignInResult> {
const provider = this.createProviderWithScopes(
new GoogleAuthProvider(),
options,
);
const provider = new GoogleAuthProvider();
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = GoogleAuthProvider.credentialFromResult(result);
Expand All @@ -204,7 +195,8 @@ export class FirebaseAuthenticationWeb
public async signInWithMicrosoft(
options?: SignInOptions,
): Promise<SignInResult> {
const provider = this.createProviderWithScopes('microsoft.com', options);
const provider = new OAuthProvider('microsoft.com');
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = OAuthProvider.credentialFromResult(result);
Expand All @@ -224,15 +216,17 @@ export class FirebaseAuthenticationWeb
public async signInWithTwitter(
options?: SignInOptions,
): Promise<SignInResult> {
const provider = this.createProviderWithScopes('twitter.com', options);
const provider = new OAuthProvider('twitter.com');
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = OAuthProvider.credentialFromResult(result);
return this.createSignInResultFromAuthCredential(result.user, credential);
}

public async signInWithYahoo(options?: SignInOptions): Promise<SignInResult> {
const provider = this.createProviderWithScopes('yahoo.com', options);
const provider = new OAuthProvider('yahoo.com');
this.applySignInConfig(provider, options);
const auth = getAuth();
const result = await signInWithPopup(auth, provider);
const credential = OAuthProvider.credentialFromResult(result);
Expand Down