@capgo/capacitor-social-login 0.0.68-alpha.2 → 0.0.68-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -20
- package/android/src/main/java/ee/forgr/capacitor/social/login/GoogleProvider.java +397 -297
- package/android/src/main/java/ee/forgr/capacitor/social/login/SocialLoginPlugin.java +14 -1
- package/dist/docs.json +38 -14
- package/dist/esm/definitions.d.ts +13 -6
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +1 -0
- package/dist/esm/web.js +137 -90
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +137 -90
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +137 -90
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/SocialLoginPlugin/GoogleProvider.swift +64 -9
- package/ios/Sources/SocialLoginPlugin/SocialLoginPlugin.swift +54 -23
- package/package.json +2 -2
|
@@ -80,10 +80,16 @@ public class GoogleProvider implements SocialProvider {
|
|
|
80
80
|
private String clientId;
|
|
81
81
|
private String[] scopes;
|
|
82
82
|
private List<
|
|
83
|
-
CallbackToFutureAdapter.Completer<
|
|
83
|
+
CallbackToFutureAdapter.Completer<AuthorizationResult>
|
|
84
84
|
> futuresList = new ArrayList<>(FUTURE_LIST_LENGTH);
|
|
85
85
|
|
|
86
86
|
private String savedAccessToken = null;
|
|
87
|
+
private GoogleProviderLoginType mode = GoogleProviderLoginType.ONLINE;
|
|
88
|
+
|
|
89
|
+
public enum GoogleProviderLoginType {
|
|
90
|
+
ONLINE,
|
|
91
|
+
OFFLINE,
|
|
92
|
+
}
|
|
87
93
|
|
|
88
94
|
public GoogleProvider(Activity activity, Context context) {
|
|
89
95
|
this.activity = activity;
|
|
@@ -94,9 +100,10 @@ public class GoogleProvider implements SocialProvider {
|
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
public void initialize(String clientId) {
|
|
103
|
+
public void initialize(String clientId, GoogleProviderLoginType mode) {
|
|
98
104
|
this.credentialManager = CredentialManager.create(activity);
|
|
99
105
|
this.clientId = clientId;
|
|
106
|
+
this.mode = mode;
|
|
100
107
|
|
|
101
108
|
String data = context
|
|
102
109
|
.getSharedPreferences(SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE)
|
|
@@ -126,6 +133,15 @@ public class GoogleProvider implements SocialProvider {
|
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
135
|
|
|
136
|
+
public String arrayFind(String[] array, String search) {
|
|
137
|
+
for (int i = 0; i < array.length; i++) {
|
|
138
|
+
if (array[i].equals(search)) {
|
|
139
|
+
return array[i];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
129
145
|
@Override
|
|
130
146
|
public void login(PluginCall call, JSONObject config) {
|
|
131
147
|
if (this.clientId == null || this.clientId.isEmpty()) {
|
|
@@ -142,9 +158,46 @@ public class GoogleProvider implements SocialProvider {
|
|
|
142
158
|
for (int i = 0; i < scopesArray.length(); i++) {
|
|
143
159
|
this.scopes[i] = scopesArray.optString(i);
|
|
144
160
|
}
|
|
161
|
+
|
|
162
|
+
if (
|
|
163
|
+
arrayFind(
|
|
164
|
+
this.scopes,
|
|
165
|
+
"https://www.googleapis.com/auth/userinfo.email"
|
|
166
|
+
) ==
|
|
167
|
+
null
|
|
168
|
+
) {
|
|
169
|
+
String[] newScopes = new String[this.scopes.length + 1];
|
|
170
|
+
System.arraycopy(this.scopes, 0, newScopes, 0, this.scopes.length);
|
|
171
|
+
newScopes[this.scopes.length] =
|
|
172
|
+
"https://www.googleapis.com/auth/userinfo.email";
|
|
173
|
+
this.scopes = newScopes;
|
|
174
|
+
}
|
|
175
|
+
if (
|
|
176
|
+
arrayFind(
|
|
177
|
+
this.scopes,
|
|
178
|
+
"https://www.googleapis.com/auth/userinfo.profile"
|
|
179
|
+
) ==
|
|
180
|
+
null
|
|
181
|
+
) {
|
|
182
|
+
String[] newScopes = new String[this.scopes.length + 1];
|
|
183
|
+
System.arraycopy(this.scopes, 0, newScopes, 0, this.scopes.length);
|
|
184
|
+
newScopes[this.scopes.length] =
|
|
185
|
+
"https://www.googleapis.com/auth/userinfo.profile";
|
|
186
|
+
this.scopes = newScopes;
|
|
187
|
+
}
|
|
188
|
+
if (arrayFind(this.scopes, "openid") == null) {
|
|
189
|
+
String[] newScopes = new String[this.scopes.length + 1];
|
|
190
|
+
System.arraycopy(this.scopes, 0, newScopes, 0, this.scopes.length);
|
|
191
|
+
newScopes[this.scopes.length] = "openid";
|
|
192
|
+
this.scopes = newScopes;
|
|
193
|
+
}
|
|
145
194
|
} else {
|
|
146
195
|
// Default scopes if not provided
|
|
147
|
-
this.scopes = new String[] {
|
|
196
|
+
this.scopes = new String[] {
|
|
197
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
|
198
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
199
|
+
"openid",
|
|
200
|
+
};
|
|
148
201
|
}
|
|
149
202
|
|
|
150
203
|
GetSignInWithGoogleOption.Builder googleIdOptionBuilder =
|
|
@@ -216,90 +269,240 @@ public class GoogleProvider implements SocialProvider {
|
|
|
216
269
|
) {
|
|
217
270
|
GoogleIdTokenCredential googleIdTokenCredential =
|
|
218
271
|
GoogleIdTokenCredential.createFrom(credential.getData());
|
|
219
|
-
String idToken = googleIdTokenCredential.getIdToken();
|
|
272
|
+
// String idToken = googleIdTokenCredential.getIdToken();
|
|
220
273
|
// resultObj.put("idToken", idToken);
|
|
221
274
|
|
|
222
275
|
// Use ExecutorService to retrieve the access token
|
|
223
276
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
224
|
-
|
|
277
|
+
JSONObject options = call.getObject("options", new JSObject());
|
|
278
|
+
Boolean forceRefreshToken =
|
|
279
|
+
options != null &&
|
|
280
|
+
options.has("forceRefreshToken") &&
|
|
281
|
+
options.getBoolean("forceRefreshToken");
|
|
282
|
+
ListenableFuture<AuthorizationResult> future = getAuthorizationResult(
|
|
283
|
+
forceRefreshToken
|
|
284
|
+
);
|
|
225
285
|
|
|
226
286
|
executor.execute(
|
|
227
287
|
new Runnable() {
|
|
228
288
|
@Override
|
|
229
289
|
public void run() {
|
|
230
290
|
try {
|
|
231
|
-
AccessToken accessToken = future.get();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
291
|
+
// AccessToken accessToken = future.get();
|
|
292
|
+
AuthorizationResult result = future.get();
|
|
293
|
+
if (
|
|
294
|
+
GoogleProvider.this.mode == GoogleProviderLoginType.ONLINE
|
|
295
|
+
) {
|
|
296
|
+
AccessToken accessToken = new AccessToken();
|
|
297
|
+
accessToken.token = result.getAccessToken();
|
|
298
|
+
|
|
299
|
+
OkHttpClient client = new OkHttpClient();
|
|
300
|
+
Request request = new Request.Builder()
|
|
301
|
+
.url(USERINFO_URL)
|
|
302
|
+
.get()
|
|
303
|
+
.addHeader("Authorization", "Bearer " + accessToken.token)
|
|
304
|
+
.build();
|
|
305
|
+
|
|
306
|
+
ListenableFuture<Date> tokenExpiresIn =
|
|
307
|
+
CallbackToFutureAdapter.getFuture(completer -> {
|
|
308
|
+
Request tokenRequest = new Request.Builder()
|
|
309
|
+
.url(
|
|
310
|
+
TOKEN_REQUEST_URL +
|
|
311
|
+
"?" +
|
|
312
|
+
"access_token=" +
|
|
313
|
+
accessToken.token
|
|
314
|
+
)
|
|
315
|
+
.get()
|
|
316
|
+
.build();
|
|
317
|
+
|
|
318
|
+
client
|
|
319
|
+
.newCall(tokenRequest)
|
|
320
|
+
.enqueue(
|
|
321
|
+
new Callback() {
|
|
322
|
+
@Override
|
|
323
|
+
public void onFailure(
|
|
324
|
+
@NonNull Call call,
|
|
325
|
+
@NonNull IOException e
|
|
326
|
+
) {}
|
|
327
|
+
|
|
328
|
+
@Override
|
|
329
|
+
public void onResponse(
|
|
330
|
+
@NonNull Call httpCall,
|
|
331
|
+
@NonNull Response httpResponse
|
|
332
|
+
) throws IOException {
|
|
333
|
+
if (!httpResponse.isSuccessful()) {
|
|
334
|
+
completer.setException(
|
|
335
|
+
new RuntimeException(
|
|
336
|
+
String.format(
|
|
337
|
+
"Invalid response from %s. Response not successful. Status code: %s",
|
|
338
|
+
TOKEN_REQUEST_URL,
|
|
339
|
+
httpResponse.code()
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
);
|
|
343
|
+
Log.e(
|
|
344
|
+
LOG_TAG,
|
|
270
345
|
String.format(
|
|
271
346
|
"Invalid response from %s. Response not successful. Status code: %s",
|
|
272
347
|
TOKEN_REQUEST_URL,
|
|
273
348
|
httpResponse.code()
|
|
274
349
|
)
|
|
350
|
+
);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
ResponseBody responseBody = httpResponse.body();
|
|
355
|
+
if (responseBody == null) {
|
|
356
|
+
completer.setException(
|
|
357
|
+
new RuntimeException(
|
|
358
|
+
String.format(
|
|
359
|
+
"Invalid response from %s. Response body is null",
|
|
360
|
+
TOKEN_REQUEST_URL
|
|
361
|
+
)
|
|
362
|
+
)
|
|
363
|
+
);
|
|
364
|
+
Log.e(
|
|
365
|
+
LOG_TAG,
|
|
366
|
+
String.format(
|
|
367
|
+
"Invalid response from %s. Response body is null",
|
|
368
|
+
TOKEN_REQUEST_URL
|
|
369
|
+
)
|
|
370
|
+
);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
String responseString = responseBody.string();
|
|
375
|
+
JSONObject jsonObject;
|
|
376
|
+
try {
|
|
377
|
+
jsonObject = (JSONObject) new JSONTokener(
|
|
378
|
+
responseString
|
|
379
|
+
).nextValue();
|
|
380
|
+
} catch (JSONException e) {
|
|
381
|
+
completer.setException(
|
|
382
|
+
new RuntimeException(
|
|
383
|
+
String.format(
|
|
384
|
+
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
385
|
+
TOKEN_REQUEST_URL,
|
|
386
|
+
e
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
);
|
|
390
|
+
Log.e(
|
|
391
|
+
LOG_TAG,
|
|
392
|
+
String.format(
|
|
393
|
+
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
394
|
+
TOKEN_REQUEST_URL,
|
|
395
|
+
e
|
|
396
|
+
)
|
|
397
|
+
);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
String expiresIn;
|
|
402
|
+
try {
|
|
403
|
+
expiresIn = jsonObject.getString(
|
|
404
|
+
"expires_in"
|
|
405
|
+
);
|
|
406
|
+
} catch (JSONException e) {
|
|
407
|
+
completer.setException(
|
|
408
|
+
new RuntimeException(
|
|
409
|
+
String.format(
|
|
410
|
+
"Invalid response from %s. Response JSON does not include expires_in. Error: %s",
|
|
411
|
+
TOKEN_REQUEST_URL,
|
|
412
|
+
e
|
|
413
|
+
)
|
|
414
|
+
)
|
|
415
|
+
);
|
|
416
|
+
Log.e(
|
|
417
|
+
LOG_TAG,
|
|
418
|
+
String.format(
|
|
419
|
+
"Invalid response from %s. Response JSON does not include expires_in. Error: %s",
|
|
420
|
+
TOKEN_REQUEST_URL,
|
|
421
|
+
e
|
|
422
|
+
)
|
|
423
|
+
);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
int expressInInt;
|
|
428
|
+
try {
|
|
429
|
+
expressInInt = Integer.parseInt(expiresIn);
|
|
430
|
+
} catch (Exception e) {
|
|
431
|
+
completer.setException(
|
|
432
|
+
new RuntimeException(
|
|
433
|
+
String.format(
|
|
434
|
+
"Invalid response from %s. expires_in: %s is not a valid int. Error: %s",
|
|
435
|
+
TOKEN_REQUEST_URL,
|
|
436
|
+
expiresIn,
|
|
437
|
+
e
|
|
438
|
+
)
|
|
439
|
+
)
|
|
440
|
+
);
|
|
441
|
+
Log.e(
|
|
442
|
+
LOG_TAG,
|
|
443
|
+
String.format(
|
|
444
|
+
"Invalid response from %s. expires_in: %s is not a valid int. Error: %s",
|
|
445
|
+
TOKEN_REQUEST_URL,
|
|
446
|
+
expiresIn,
|
|
447
|
+
e
|
|
448
|
+
)
|
|
449
|
+
);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
Date instant = new Date();
|
|
454
|
+
Calendar calendar = Calendar.getInstance();
|
|
455
|
+
calendar.setTime(instant);
|
|
456
|
+
calendar.add(Calendar.SECOND, expressInInt);
|
|
457
|
+
completer.set(calendar.getTime());
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
return "TokenExpiresInOperationTag";
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
client
|
|
466
|
+
.newCall(request)
|
|
467
|
+
.enqueue(
|
|
468
|
+
new Callback() {
|
|
469
|
+
@Override
|
|
470
|
+
public void onResponse(
|
|
471
|
+
@NonNull Call httpCall,
|
|
472
|
+
@NonNull Response httpResponse
|
|
473
|
+
) throws IOException {
|
|
474
|
+
try {
|
|
475
|
+
if (!httpResponse.isSuccessful()) {
|
|
476
|
+
call.reject(
|
|
477
|
+
String.format(
|
|
478
|
+
"Invalid response from %s. Response not successful. Status code: %s",
|
|
479
|
+
USERINFO_URL,
|
|
480
|
+
httpResponse.code()
|
|
275
481
|
)
|
|
276
482
|
);
|
|
277
483
|
Log.e(
|
|
278
484
|
LOG_TAG,
|
|
279
485
|
String.format(
|
|
280
486
|
"Invalid response from %s. Response not successful. Status code: %s",
|
|
281
|
-
|
|
487
|
+
USERINFO_URL,
|
|
282
488
|
httpResponse.code()
|
|
283
489
|
)
|
|
284
490
|
);
|
|
285
491
|
return;
|
|
286
492
|
}
|
|
287
|
-
|
|
288
493
|
ResponseBody responseBody = httpResponse.body();
|
|
289
494
|
if (responseBody == null) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
TOKEN_REQUEST_URL
|
|
295
|
-
)
|
|
495
|
+
call.reject(
|
|
496
|
+
String.format(
|
|
497
|
+
"Invalid response from %s. Response body is null",
|
|
498
|
+
USERINFO_URL
|
|
296
499
|
)
|
|
297
500
|
);
|
|
298
501
|
Log.e(
|
|
299
502
|
LOG_TAG,
|
|
300
503
|
String.format(
|
|
301
504
|
"Invalid response from %s. Response body is null",
|
|
302
|
-
|
|
505
|
+
USERINFO_URL
|
|
303
506
|
)
|
|
304
507
|
);
|
|
305
508
|
return;
|
|
@@ -312,258 +515,133 @@ public class GoogleProvider implements SocialProvider {
|
|
|
312
515
|
responseString
|
|
313
516
|
).nextValue();
|
|
314
517
|
} catch (JSONException e) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
e
|
|
321
|
-
)
|
|
518
|
+
call.reject(
|
|
519
|
+
String.format(
|
|
520
|
+
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
521
|
+
USERINFO_URL,
|
|
522
|
+
e
|
|
322
523
|
)
|
|
323
524
|
);
|
|
324
525
|
Log.e(
|
|
325
526
|
LOG_TAG,
|
|
326
527
|
String.format(
|
|
327
528
|
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
328
|
-
|
|
529
|
+
USERINFO_URL,
|
|
329
530
|
e
|
|
330
531
|
)
|
|
331
532
|
);
|
|
332
533
|
return;
|
|
333
534
|
}
|
|
334
535
|
|
|
335
|
-
String expiresIn;
|
|
336
536
|
try {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
new RuntimeException(
|
|
341
|
-
String.format(
|
|
342
|
-
"Invalid response from %s. Response JSON does not include expires_in. Error: %s",
|
|
343
|
-
TOKEN_REQUEST_URL,
|
|
344
|
-
e
|
|
345
|
-
)
|
|
346
|
-
)
|
|
537
|
+
String name = jsonObject.getString("name");
|
|
538
|
+
String givenName = jsonObject.getString(
|
|
539
|
+
"given_name"
|
|
347
540
|
);
|
|
348
|
-
|
|
349
|
-
|
|
541
|
+
String familyName = jsonObject.getString(
|
|
542
|
+
"family_name"
|
|
543
|
+
);
|
|
544
|
+
String picture = jsonObject.getString(
|
|
545
|
+
"picture"
|
|
546
|
+
);
|
|
547
|
+
String email = jsonObject.getString("email");
|
|
548
|
+
String sub = jsonObject.getString("sub");
|
|
549
|
+
|
|
550
|
+
// now, let's try to get the expiry
|
|
551
|
+
try {
|
|
552
|
+
Date expiryDate = tokenExpiresIn.get(
|
|
553
|
+
5,
|
|
554
|
+
TimeUnit.SECONDS
|
|
555
|
+
);
|
|
556
|
+
long seconds =
|
|
557
|
+
(expiryDate.getTime() -
|
|
558
|
+
(new Date()).getTime()) /
|
|
559
|
+
1000;
|
|
560
|
+
accessToken.expires = String.valueOf(seconds);
|
|
561
|
+
} catch (
|
|
562
|
+
ExecutionException
|
|
563
|
+
| InterruptedException
|
|
564
|
+
| TimeoutException e
|
|
565
|
+
) {
|
|
566
|
+
Log.e(LOG_TAG, "Cannot get expiry date", e);
|
|
567
|
+
// it's a non-fatal error
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
profile.put("email", email);
|
|
571
|
+
profile.put("familyName", familyName);
|
|
572
|
+
profile.put("givenName", givenName);
|
|
573
|
+
profile.put("id", sub);
|
|
574
|
+
profile.put("name", name);
|
|
575
|
+
profile.put("imageUrl", picture);
|
|
576
|
+
|
|
577
|
+
JSObject accessTokenObj = new JSObject();
|
|
578
|
+
accessTokenObj.put("token", accessToken.token);
|
|
579
|
+
if (accessToken.expires != null) {
|
|
580
|
+
accessTokenObj.put(
|
|
581
|
+
"expires",
|
|
582
|
+
accessToken.expires
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
resultObj.put("accessToken", accessTokenObj);
|
|
587
|
+
resultObj.put("profile", profile);
|
|
588
|
+
response.put("result", resultObj);
|
|
589
|
+
resultObj.put("responseType", "online");
|
|
590
|
+
persistState(accessToken.token);
|
|
591
|
+
call.resolve(response);
|
|
592
|
+
} catch (JSONException e) {
|
|
593
|
+
call.reject(
|
|
350
594
|
String.format(
|
|
351
|
-
"Invalid response from %s.
|
|
352
|
-
|
|
595
|
+
"Invalid response from %s. Could not get some value from JSON. Error: %s",
|
|
596
|
+
USERINFO_URL,
|
|
353
597
|
e
|
|
354
598
|
)
|
|
355
599
|
);
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
int expressInInt;
|
|
360
|
-
try {
|
|
361
|
-
expressInInt = Integer.parseInt(expiresIn);
|
|
362
|
-
} catch (Exception e) {
|
|
363
|
-
completer.setException(
|
|
364
|
-
new RuntimeException(
|
|
365
|
-
String.format(
|
|
366
|
-
"Invalid response from %s. expires_in: %s is not a valid int. Error: %s",
|
|
367
|
-
TOKEN_REQUEST_URL,
|
|
368
|
-
expiresIn,
|
|
369
|
-
e
|
|
370
|
-
)
|
|
371
|
-
)
|
|
372
|
-
);
|
|
373
600
|
Log.e(
|
|
374
601
|
LOG_TAG,
|
|
375
602
|
String.format(
|
|
376
|
-
"Invalid response from %s.
|
|
377
|
-
|
|
378
|
-
expiresIn,
|
|
603
|
+
"Invalid response from %s. Could not get some value from JSON. Error: %s",
|
|
604
|
+
USERINFO_URL,
|
|
379
605
|
e
|
|
380
606
|
)
|
|
381
607
|
);
|
|
382
608
|
return;
|
|
383
609
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
Calendar calendar = Calendar.getInstance();
|
|
387
|
-
calendar.setTime(instant);
|
|
388
|
-
calendar.add(Calendar.SECOND, expressInInt);
|
|
389
|
-
completer.set(calendar.getTime());
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
);
|
|
393
|
-
|
|
394
|
-
return "TokenExpiresInOperationTag";
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
client
|
|
398
|
-
.newCall(request)
|
|
399
|
-
.enqueue(
|
|
400
|
-
new Callback() {
|
|
401
|
-
@Override
|
|
402
|
-
public void onResponse(
|
|
403
|
-
@NonNull Call httpCall,
|
|
404
|
-
@NonNull Response httpResponse
|
|
405
|
-
) throws IOException {
|
|
406
|
-
try {
|
|
407
|
-
if (!httpResponse.isSuccessful()) {
|
|
408
|
-
call.reject(
|
|
409
|
-
String.format(
|
|
410
|
-
"Invalid response from %s. Response not successful. Status code: %s",
|
|
411
|
-
USERINFO_URL,
|
|
412
|
-
httpResponse.code()
|
|
413
|
-
)
|
|
414
|
-
);
|
|
415
|
-
Log.e(
|
|
416
|
-
LOG_TAG,
|
|
417
|
-
String.format(
|
|
418
|
-
"Invalid response from %s. Response not successful. Status code: %s",
|
|
419
|
-
USERINFO_URL,
|
|
420
|
-
httpResponse.code()
|
|
421
|
-
)
|
|
422
|
-
);
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
ResponseBody responseBody = httpResponse.body();
|
|
426
|
-
if (responseBody == null) {
|
|
427
|
-
call.reject(
|
|
428
|
-
String.format(
|
|
429
|
-
"Invalid response from %s. Response body is null",
|
|
430
|
-
USERINFO_URL
|
|
431
|
-
)
|
|
432
|
-
);
|
|
433
|
-
Log.e(
|
|
434
|
-
LOG_TAG,
|
|
435
|
-
String.format(
|
|
436
|
-
"Invalid response from %s. Response body is null",
|
|
437
|
-
USERINFO_URL
|
|
438
|
-
)
|
|
439
|
-
);
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
String responseString = responseBody.string();
|
|
444
|
-
JSONObject jsonObject;
|
|
445
|
-
try {
|
|
446
|
-
jsonObject = (JSONObject) new JSONTokener(
|
|
447
|
-
responseString
|
|
448
|
-
).nextValue();
|
|
449
|
-
} catch (JSONException e) {
|
|
450
|
-
call.reject(
|
|
451
|
-
String.format(
|
|
452
|
-
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
453
|
-
USERINFO_URL,
|
|
454
|
-
e
|
|
455
|
-
)
|
|
456
|
-
);
|
|
457
|
-
Log.e(
|
|
458
|
-
LOG_TAG,
|
|
459
|
-
String.format(
|
|
460
|
-
"Invalid response from %s. Response body is not a valid JSON. Error: %s",
|
|
461
|
-
USERINFO_URL,
|
|
462
|
-
e
|
|
463
|
-
)
|
|
464
|
-
);
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
try {
|
|
469
|
-
String name = jsonObject.getString("name");
|
|
470
|
-
String givenName = jsonObject.getString(
|
|
471
|
-
"given_name"
|
|
472
|
-
);
|
|
473
|
-
String familyName = jsonObject.getString(
|
|
474
|
-
"family_name"
|
|
475
|
-
);
|
|
476
|
-
String picture = jsonObject.getString("picture");
|
|
477
|
-
String email = jsonObject.getString("email");
|
|
478
|
-
String sub = jsonObject.getString("sub");
|
|
479
|
-
|
|
480
|
-
// now, let's try to get the expiry
|
|
481
|
-
try {
|
|
482
|
-
Date expiryDate = tokenExpiresIn.get(
|
|
483
|
-
5,
|
|
484
|
-
TimeUnit.SECONDS
|
|
485
|
-
);
|
|
486
|
-
long seconds =
|
|
487
|
-
(expiryDate.getTime() -
|
|
488
|
-
(new Date()).getTime()) /
|
|
489
|
-
1000;
|
|
490
|
-
accessToken.expires = String.valueOf(seconds);
|
|
491
|
-
} catch (
|
|
492
|
-
ExecutionException
|
|
493
|
-
| InterruptedException
|
|
494
|
-
| TimeoutException e
|
|
495
|
-
) {
|
|
496
|
-
Log.e(LOG_TAG, "Cannot get expiry date", e);
|
|
497
|
-
// it's a non-fatal error
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
profile.put("email", email);
|
|
501
|
-
profile.put("familyName", familyName);
|
|
502
|
-
profile.put("givenName", givenName);
|
|
503
|
-
profile.put("id", sub);
|
|
504
|
-
profile.put("name", name);
|
|
505
|
-
profile.put("imageUrl", picture);
|
|
506
|
-
|
|
507
|
-
JSObject accessTokenObj = new JSObject();
|
|
508
|
-
accessTokenObj.put("token", accessToken.token);
|
|
509
|
-
if (accessToken.expires != null) {
|
|
510
|
-
accessTokenObj.put(
|
|
511
|
-
"expires",
|
|
512
|
-
accessToken.expires
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
resultObj.put("accessToken", accessTokenObj);
|
|
517
|
-
resultObj.put("profile", profile);
|
|
518
|
-
response.put("result", resultObj);
|
|
519
|
-
persistState(accessToken.token);
|
|
520
|
-
call.resolve(response);
|
|
521
|
-
} catch (JSONException e) {
|
|
522
|
-
call.reject(
|
|
523
|
-
String.format(
|
|
524
|
-
"Invalid response from %s. Could not get some value from JSON. Error: %s",
|
|
525
|
-
USERINFO_URL,
|
|
526
|
-
e
|
|
527
|
-
)
|
|
528
|
-
);
|
|
529
|
-
Log.e(
|
|
530
|
-
LOG_TAG,
|
|
531
|
-
String.format(
|
|
532
|
-
"Invalid response from %s. Could not get some value from JSON. Error: %s",
|
|
533
|
-
USERINFO_URL,
|
|
534
|
-
e
|
|
535
|
-
)
|
|
536
|
-
);
|
|
537
|
-
return;
|
|
610
|
+
} finally {
|
|
611
|
+
httpResponse.close();
|
|
538
612
|
}
|
|
539
|
-
} finally {
|
|
540
|
-
httpResponse.close();
|
|
541
613
|
}
|
|
542
|
-
}
|
|
543
614
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
615
|
+
@Override
|
|
616
|
+
public void onFailure(
|
|
617
|
+
@NonNull Call httpCall,
|
|
618
|
+
@NonNull IOException e
|
|
619
|
+
) {
|
|
620
|
+
call.reject(
|
|
621
|
+
String.format(
|
|
622
|
+
"Invalid response from %s. Error: %s",
|
|
623
|
+
USERINFO_URL,
|
|
624
|
+
e
|
|
625
|
+
)
|
|
626
|
+
);
|
|
627
|
+
Log.e(
|
|
628
|
+
LOG_TAG,
|
|
629
|
+
String.format(
|
|
630
|
+
"Invalid response from %s",
|
|
631
|
+
USERINFO_URL
|
|
632
|
+
),
|
|
553
633
|
e
|
|
554
|
-
)
|
|
555
|
-
|
|
556
|
-
Log.e(
|
|
557
|
-
LOG_TAG,
|
|
558
|
-
String.format(
|
|
559
|
-
"Invalid response from %s",
|
|
560
|
-
USERINFO_URL
|
|
561
|
-
),
|
|
562
|
-
e
|
|
563
|
-
);
|
|
634
|
+
);
|
|
635
|
+
}
|
|
564
636
|
}
|
|
565
|
-
|
|
566
|
-
|
|
637
|
+
);
|
|
638
|
+
} else {
|
|
639
|
+
String serverAuthCode = result.getServerAuthCode();
|
|
640
|
+
resultObj.put("serverAuthCode", serverAuthCode);
|
|
641
|
+
resultObj.put("responseType", "offline");
|
|
642
|
+
response.put("result", resultObj);
|
|
643
|
+
call.resolve(response);
|
|
644
|
+
}
|
|
567
645
|
} catch (Exception e) {
|
|
568
646
|
call.reject(
|
|
569
647
|
"Error retrieving access token: " + e.getMessage()
|
|
@@ -586,7 +664,9 @@ public class GoogleProvider implements SocialProvider {
|
|
|
586
664
|
}
|
|
587
665
|
}
|
|
588
666
|
|
|
589
|
-
private ListenableFuture<
|
|
667
|
+
private ListenableFuture<AuthorizationResult> getAuthorizationResult(
|
|
668
|
+
Boolean forceRefreshToken
|
|
669
|
+
) {
|
|
590
670
|
// Account account = new Account(credential.getId(), "com.google");
|
|
591
671
|
// String scopesString = "oauth2:" + TextUtils.join(" ", this.scopes);
|
|
592
672
|
// String token = GoogleAuthUtil.getToken(
|
|
@@ -602,18 +682,26 @@ public class GoogleProvider implements SocialProvider {
|
|
|
602
682
|
//
|
|
603
683
|
// return accessToken;
|
|
604
684
|
|
|
605
|
-
ListenableFuture<
|
|
606
|
-
completer -> {
|
|
607
|
-
List<Scope> scopes =
|
|
608
|
-
|
|
609
|
-
new Scope(
|
|
610
|
-
|
|
611
|
-
|
|
685
|
+
ListenableFuture<AuthorizationResult> future =
|
|
686
|
+
CallbackToFutureAdapter.getFuture(completer -> {
|
|
687
|
+
List<Scope> scopes = new ArrayList<>(this.scopes.length);
|
|
688
|
+
for (int i = 0; i < this.scopes.length; i++) {
|
|
689
|
+
scopes.add(new Scope(this.scopes[i]));
|
|
690
|
+
}
|
|
691
|
+
AuthorizationRequest.Builder authorizationRequestBuilder =
|
|
692
|
+
AuthorizationRequest.builder().setRequestedScopes(scopes);
|
|
693
|
+
// .requestOfflineAccess(this.clientId)
|
|
694
|
+
|
|
695
|
+
if (GoogleProvider.this.mode == GoogleProviderLoginType.OFFLINE) {
|
|
696
|
+
authorizationRequestBuilder =
|
|
697
|
+
authorizationRequestBuilder.requestOfflineAccess(
|
|
698
|
+
this.clientId,
|
|
699
|
+
forceRefreshToken
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
|
|
612
703
|
AuthorizationRequest authorizationRequest =
|
|
613
|
-
|
|
614
|
-
.setRequestedScopes(scopes)
|
|
615
|
-
// .requestOfflineAccess(this.clientId)
|
|
616
|
-
.build();
|
|
704
|
+
authorizationRequestBuilder.build();
|
|
617
705
|
|
|
618
706
|
Identity.getAuthorizationClient(context)
|
|
619
707
|
.authorize(authorizationRequest)
|
|
@@ -677,9 +765,9 @@ public class GoogleProvider implements SocialProvider {
|
|
|
677
765
|
// if (authorizationResult.getServerAuthCode() != null)
|
|
678
766
|
// Log.i("TAG", authorizationResult.getServerAuthCode());
|
|
679
767
|
|
|
680
|
-
AccessToken accessToken = new AccessToken();
|
|
681
|
-
accessToken.token = authorizationResult.getAccessToken();
|
|
682
|
-
completer.set(
|
|
768
|
+
// AccessToken accessToken = new AccessToken();
|
|
769
|
+
// accessToken.token = authorizationResult.getAccessToken();
|
|
770
|
+
completer.set(authorizationResult);
|
|
683
771
|
}
|
|
684
772
|
})
|
|
685
773
|
.addOnFailureListener(e -> {
|
|
@@ -688,8 +776,7 @@ public class GoogleProvider implements SocialProvider {
|
|
|
688
776
|
});
|
|
689
777
|
|
|
690
778
|
return "GetAccessTokenOperationTag";
|
|
691
|
-
}
|
|
692
|
-
);
|
|
779
|
+
});
|
|
693
780
|
|
|
694
781
|
return future;
|
|
695
782
|
}
|
|
@@ -710,17 +797,16 @@ public class GoogleProvider implements SocialProvider {
|
|
|
710
797
|
return;
|
|
711
798
|
}
|
|
712
799
|
|
|
713
|
-
CallbackToFutureAdapter.Completer<
|
|
714
|
-
futureIndex
|
|
715
|
-
);
|
|
800
|
+
CallbackToFutureAdapter.Completer<AuthorizationResult> future =
|
|
801
|
+
futuresList.get(futureIndex);
|
|
716
802
|
|
|
717
803
|
try {
|
|
718
804
|
AuthorizationResult authorizationResult = Identity.getAuthorizationClient(
|
|
719
805
|
this.activity
|
|
720
806
|
).getAuthorizationResultFromIntent(data);
|
|
721
|
-
AccessToken accessToken = new AccessToken();
|
|
722
|
-
accessToken.token = authorizationResult.getAccessToken();
|
|
723
|
-
future.set(
|
|
807
|
+
// AccessToken accessToken = new AccessToken();
|
|
808
|
+
// accessToken.token = authorizationResult.getAccessToken();
|
|
809
|
+
future.set(authorizationResult);
|
|
724
810
|
} catch (ApiException e) {
|
|
725
811
|
Log.e(LOG_TAG, "Cannot get getAuthorizationResultFromIntent", e);
|
|
726
812
|
future.setException(
|
|
@@ -772,6 +858,10 @@ public class GoogleProvider implements SocialProvider {
|
|
|
772
858
|
|
|
773
859
|
@Override
|
|
774
860
|
public void logout(PluginCall call) {
|
|
861
|
+
if (this.mode == GoogleProviderLoginType.OFFLINE) {
|
|
862
|
+
call.reject("logout is not implemented when using offline mode");
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
775
865
|
rawLogout(
|
|
776
866
|
new CredentialManagerCallback<Void, Exception>() {
|
|
777
867
|
@Override
|
|
@@ -926,6 +1016,12 @@ public class GoogleProvider implements SocialProvider {
|
|
|
926
1016
|
|
|
927
1017
|
@Override
|
|
928
1018
|
public void getAuthorizationCode(PluginCall call) {
|
|
1019
|
+
if (this.mode == GoogleProviderLoginType.OFFLINE) {
|
|
1020
|
+
call.reject(
|
|
1021
|
+
"getAuthorizationCode is not implemented when using offline mode"
|
|
1022
|
+
);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
929
1025
|
if (GoogleProvider.this.savedAccessToken == null) {
|
|
930
1026
|
call.reject("User is not logged in");
|
|
931
1027
|
return;
|
|
@@ -969,6 +1065,10 @@ public class GoogleProvider implements SocialProvider {
|
|
|
969
1065
|
|
|
970
1066
|
@Override
|
|
971
1067
|
public void isLoggedIn(PluginCall call) {
|
|
1068
|
+
if (this.mode == GoogleProviderLoginType.OFFLINE) {
|
|
1069
|
+
call.reject("isLoggedIn is not implemented when using offline mode");
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
972
1072
|
if (GoogleProvider.this.savedAccessToken == null) {
|
|
973
1073
|
call.resolve(new JSObject().put("isLoggedIn", false));
|
|
974
1074
|
return;
|