21
21
import com .getcapacitor .JSArray ;
22
22
import com .getcapacitor .Logger ;
23
23
import com .getcapacitor .PluginCall ;
24
+ import com .google .android .gms .auth .GoogleAuthException ;
25
+ import com .google .android .gms .auth .GoogleAuthUtil ;
24
26
import com .google .android .gms .auth .api .identity .AuthorizationRequest ;
25
27
import com .google .android .gms .auth .api .identity .AuthorizationResult ;
26
28
import com .google .android .gms .auth .api .identity .Identity ;
29
+ import com .google .android .gms .auth .api .signin .GoogleSignIn ;
30
+ import com .google .android .gms .auth .api .signin .GoogleSignInAccount ;
31
+ import com .google .android .gms .auth .api .signin .GoogleSignInClient ;
32
+ import com .google .android .gms .auth .api .signin .GoogleSignInOptions ;
27
33
import com .google .android .gms .common .api .ApiException ;
28
34
import com .google .android .gms .common .api .Scope ;
35
+ import com .google .android .gms .tasks .Task ;
29
36
import com .google .android .libraries .identity .googleid .GetGoogleIdOption ;
30
37
import com .google .android .libraries .identity .googleid .GoogleIdTokenCredential ;
31
38
import com .google .firebase .auth .AuthCredential ;
34
41
import io .capawesome .capacitorjs .plugins .firebase .authentication .FirebaseAuthenticationPlugin ;
35
42
import io .capawesome .capacitorjs .plugins .firebase .authentication .R ;
36
43
import io .capawesome .capacitorjs .plugins .firebase .authentication .interfaces .NonEmptyCallback ;
44
+ import java .io .IOException ;
37
45
import java .util .ArrayList ;
38
46
import java .util .List ;
39
47
import java .util .concurrent .Executor ;
43
51
public class GoogleAuthProviderHandler {
44
52
45
53
private FirebaseAuthentication pluginImplementation ;
54
+ private GoogleSignInClient mGoogleSignInClient ;
46
55
47
56
@ Nullable
48
57
private AuthCredential lastAuthCredential ;
@@ -57,6 +66,7 @@ public class GoogleAuthProviderHandler {
57
66
58
67
public GoogleAuthProviderHandler (FirebaseAuthentication pluginImplementation ) {
59
68
this .pluginImplementation = pluginImplementation ;
69
+ this .mGoogleSignInClient = buildGoogleSignInClient ();
60
70
}
61
71
62
72
public void handleActivityResult (@ NonNull ActivityResult result ) {
@@ -75,6 +85,53 @@ public void handleActivityResult(@NonNull ActivityResult result) {
75
85
}
76
86
}
77
87
88
+ public void handleOnActivityResult (@ NonNull final PluginCall call , @ NonNull ActivityResult result , boolean isLink ) {
89
+ Intent data = result .getData ();
90
+ Task <GoogleSignInAccount > task = GoogleSignIn .getSignedInAccountFromIntent (data );
91
+ try {
92
+ GoogleSignInAccount account = task .getResult (ApiException .class );
93
+ String idToken = account .getIdToken ();
94
+ String serverAuthCode = account .getServerAuthCode ();
95
+ AuthCredential credential = GoogleAuthProvider .getCredential (idToken , null );
96
+
97
+ new Thread (() -> {
98
+ String accessToken = null ;
99
+ List <String > scopes = new ArrayList <>();
100
+ scopes .add ("oauth2:email" );
101
+ scopes .addAll (getScopesAsList (call ));
102
+
103
+ try {
104
+ accessToken = GoogleAuthUtil .getToken (
105
+ mGoogleSignInClient .getApplicationContext (),
106
+ account .getAccount (),
107
+ String .join (" " , scopes )
108
+ );
109
+ // Clears local cache after every login attempt
110
+ // to ensure permissions changes elsewhere are reflected in future tokens
111
+ GoogleAuthUtil .clearToken (mGoogleSignInClient .getApplicationContext (), accessToken );
112
+ } catch (IOException | GoogleAuthException exception ) {
113
+ if (isLink ) {
114
+ pluginImplementation .handleFailedLink (call , null , exception );
115
+ } else {
116
+ pluginImplementation .handleFailedSignIn (call , null , exception );
117
+ }
118
+ return ;
119
+ }
120
+ if (isLink ) {
121
+ pluginImplementation .handleSuccessfulLink (call , credential , idToken , null , accessToken , serverAuthCode );
122
+ } else {
123
+ pluginImplementation .handleSuccessfulSignIn (call , credential , idToken , null , accessToken , serverAuthCode , null );
124
+ }
125
+ }).start ();
126
+ } catch (ApiException exception ) {
127
+ if (isLink ) {
128
+ pluginImplementation .handleFailedLink (call , null , exception );
129
+ } else {
130
+ pluginImplementation .handleFailedSignIn (call , null , exception );
131
+ }
132
+ }
133
+ }
134
+
78
135
public void handleAuthorizationResult (@ NonNull AuthorizationResult authorizationResult ) {
79
136
if (lastCall == null ) {
80
137
return ;
@@ -105,12 +162,32 @@ public void handleAuthorizationResultError(@NonNull Exception exception) {
105
162
lastIdToken = null ;
106
163
}
107
164
165
+ public void signIn (final PluginCall call ) {
166
+ signInOrLink (call , false );
167
+ }
168
+
108
169
public void link (final PluginCall call ) {
109
170
signInOrLink (call , true );
110
171
}
111
172
112
- public void signIn (final PluginCall call ) {
113
- signInOrLink (call , false );
173
+ private GoogleSignInClient buildGoogleSignInClient () {
174
+ return buildGoogleSignInClient (null );
175
+ }
176
+
177
+ private GoogleSignInClient buildGoogleSignInClient (@ Nullable PluginCall call ) {
178
+ GoogleSignInOptions .Builder googleSignInOptionsBuilder = new GoogleSignInOptions .Builder (GoogleSignInOptions .DEFAULT_SIGN_IN )
179
+ .requestIdToken (pluginImplementation .getPlugin ().getContext ().getString (R .string .default_web_client_id ))
180
+ .requestServerAuthCode (pluginImplementation .getPlugin ().getContext ().getString (R .string .default_web_client_id ))
181
+ .requestEmail ();
182
+
183
+ if (call != null ) {
184
+ List <String > scopeList = getScopesAsList (call );
185
+ for (String scope : scopeList ) {
186
+ googleSignInOptionsBuilder = googleSignInOptionsBuilder .requestScopes (new Scope (scope ));
187
+ }
188
+ }
189
+
190
+ return GoogleSignIn .getClient (pluginImplementation .getPlugin ().getActivity (), googleSignInOptionsBuilder .build ());
114
191
}
115
192
116
193
public void signOut () {
@@ -151,6 +228,19 @@ private List<Scope> buildScopeList(@NonNull PluginCall call) {
151
228
return scopeList ;
152
229
}
153
230
231
+ private List <String > getScopesAsList (@ NonNull PluginCall call ) {
232
+ List <String > scopeList = new ArrayList <>();
233
+ JSArray scopes = call .getArray ("scopes" );
234
+ if (scopes != null ) {
235
+ try {
236
+ scopeList = scopes .toList ();
237
+ } catch (JSONException exception ) {
238
+ Log .e (FirebaseAuthenticationPlugin .TAG , "getScopesAsList failed." , exception );
239
+ }
240
+ }
241
+ return scopeList ;
242
+ }
243
+
154
244
private void handleGetCredentialError (final PluginCall call , final boolean isLink , final GetCredentialException exception ) {
155
245
if (isLink ) {
156
246
pluginImplementation .handleFailedLink (call , null , exception );
@@ -205,32 +295,46 @@ public void error(Exception exception) {
205
295
}
206
296
207
297
private void signInOrLink (final PluginCall call , final boolean isLink ) {
208
- Executor executor = Executors .newSingleThreadExecutor ();
209
- GetGoogleIdOption googleIdOption = new GetGoogleIdOption .Builder ()
210
- // Your server's client ID, not your Android client ID
211
- .setServerClientId (pluginImplementation .getPlugin ().getContext ().getString (R .string .default_web_client_id ))
212
- // Show all accounts on the device (not just the accounts that have been used previously)
213
- .setFilterByAuthorizedAccounts (false )
214
- .build ();
215
- GetCredentialRequest request = new GetCredentialRequest .Builder ().addCredentialOption (googleIdOption ).build ();
216
- CredentialManager credentialManager = CredentialManager .create (pluginImplementation .getPlugin ().getActivity ());
217
- credentialManager .getCredentialAsync (
218
- pluginImplementation .getPlugin ().getContext (),
219
- request ,
220
- null ,
221
- executor ,
222
- new CredentialManagerCallback <GetCredentialResponse , GetCredentialException >() {
223
- @ Override
224
- public void onResult (GetCredentialResponse response ) {
225
- handleGetCredentialResult (call , isLink , response );
226
- }
298
+ Boolean useCredentialManagerRaw = call .getBoolean ("useCredentialManager" );
299
+ boolean useCredentialManager = (useCredentialManagerRaw != null ) ? useCredentialManagerRaw : true ;
227
300
228
- @ Override
229
- public void onError (@ NonNull GetCredentialException exception ) {
230
- handleGetCredentialError (call , isLink , exception );
301
+ if (useCredentialManager ) {
302
+ Executor executor = Executors .newSingleThreadExecutor ();
303
+ GetGoogleIdOption googleIdOption = new GetGoogleIdOption .Builder ()
304
+ // Your server's client ID, not your Android client ID
305
+ .setServerClientId (pluginImplementation .getPlugin ().getContext ().getString (R .string .default_web_client_id ))
306
+ // Show all accounts on the device (not just the accounts that have been used previously)
307
+ .setFilterByAuthorizedAccounts (false )
308
+ .build ();
309
+ GetCredentialRequest request = new GetCredentialRequest .Builder ().addCredentialOption (googleIdOption ).build ();
310
+ CredentialManager credentialManager = CredentialManager .create (pluginImplementation .getPlugin ().getActivity ());
311
+ credentialManager .getCredentialAsync (
312
+ pluginImplementation .getPlugin ().getContext (),
313
+ request ,
314
+ null ,
315
+ executor ,
316
+ new CredentialManagerCallback <GetCredentialResponse , GetCredentialException >() {
317
+ @ Override
318
+ public void onResult (GetCredentialResponse response ) {
319
+ handleGetCredentialResult (call , isLink , response );
320
+ }
321
+
322
+ @ Override
323
+ public void onError (@ NonNull GetCredentialException exception ) {
324
+ handleGetCredentialError (call , isLink , exception );
325
+ }
231
326
}
327
+ );
328
+ } else {
329
+ mGoogleSignInClient = buildGoogleSignInClient (call );
330
+ Intent signInIntent = mGoogleSignInClient .getSignInIntent ();
331
+
332
+ if (isLink ) {
333
+ pluginImplementation .startActivityForResult (call , signInIntent , "handleGoogleAuthProviderLinkActivityResult" );
334
+ } else {
335
+ pluginImplementation .startActivityForResult (call , signInIntent , "handleGoogleAuthProviderSignInActivityResult" );
232
336
}
233
- );
337
+ }
234
338
}
235
339
236
340
/**
0 commit comments