@capawesome/capacitor-google-sign-in 0.0.1
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/CapawesomeCapacitorGoogleSignIn.podspec +19 -0
- package/Package.swift +30 -0
- package/README.md +276 -0
- package/android/build.gradle +65 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/GoogleSignIn.java +300 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/GoogleSignInPlugin.java +159 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/classes/CustomException.java +20 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/classes/CustomExceptions.java +11 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/classes/options/InitializeOptions.java +56 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/classes/options/SignInOptions.java +25 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/classes/results/SignInResult.java +75 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/interfaces/Callback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/interfaces/EmptyCallback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/interfaces/NonEmptyResultCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/interfaces/Result.java +7 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +310 -0
- package/dist/esm/definitions.d.ts +173 -0
- package/dist/esm/definitions.js +13 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +13 -0
- package/dist/esm/web.js +106 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +133 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +136 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Classes/Options/InitializeOptions.swift +19 -0
- package/ios/Plugin/Classes/Results/SignInResult.swift +50 -0
- package/ios/Plugin/Enums/CustomError.swift +38 -0
- package/ios/Plugin/GoogleSignIn.swift +90 -0
- package/ios/Plugin/GoogleSignInPlugin.swift +81 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/Protocols/Result.swift +5 -0
- package/package.json +93 -0
package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/GoogleSignIn.java
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin;
|
|
2
|
+
|
|
3
|
+
import android.app.PendingIntent;
|
|
4
|
+
import android.util.Base64;
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
import androidx.credentials.ClearCredentialStateRequest;
|
|
8
|
+
import androidx.credentials.Credential;
|
|
9
|
+
import androidx.credentials.CredentialManager;
|
|
10
|
+
import androidx.credentials.CustomCredential;
|
|
11
|
+
import androidx.credentials.GetCredentialRequest;
|
|
12
|
+
import androidx.credentials.GetCredentialResponse;
|
|
13
|
+
import com.google.android.gms.auth.api.identity.AuthorizationRequest;
|
|
14
|
+
import com.google.android.gms.auth.api.identity.AuthorizationResult;
|
|
15
|
+
import com.google.android.gms.auth.api.identity.Identity;
|
|
16
|
+
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption;
|
|
17
|
+
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential;
|
|
18
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.CustomExceptions;
|
|
19
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.options.InitializeOptions;
|
|
20
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.options.SignInOptions;
|
|
21
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.results.SignInResult;
|
|
22
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.EmptyCallback;
|
|
23
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.NonEmptyResultCallback;
|
|
24
|
+
import java.util.Arrays;
|
|
25
|
+
import java.util.List;
|
|
26
|
+
import org.json.JSONObject;
|
|
27
|
+
|
|
28
|
+
public class GoogleSignIn {
|
|
29
|
+
|
|
30
|
+
private final GoogleSignInPlugin plugin;
|
|
31
|
+
|
|
32
|
+
@Nullable
|
|
33
|
+
private String clientId;
|
|
34
|
+
|
|
35
|
+
@Nullable
|
|
36
|
+
private String[] scopes;
|
|
37
|
+
|
|
38
|
+
@Nullable
|
|
39
|
+
private NonEmptyResultCallback<SignInResult> pendingSignInCallback;
|
|
40
|
+
|
|
41
|
+
@Nullable
|
|
42
|
+
private String pendingIdToken;
|
|
43
|
+
|
|
44
|
+
@Nullable
|
|
45
|
+
private String pendingUserId;
|
|
46
|
+
|
|
47
|
+
@Nullable
|
|
48
|
+
private String pendingEmail;
|
|
49
|
+
|
|
50
|
+
@Nullable
|
|
51
|
+
private String pendingDisplayName;
|
|
52
|
+
|
|
53
|
+
@Nullable
|
|
54
|
+
private String pendingGivenName;
|
|
55
|
+
|
|
56
|
+
@Nullable
|
|
57
|
+
private String pendingFamilyName;
|
|
58
|
+
|
|
59
|
+
@Nullable
|
|
60
|
+
private String pendingImageUrl;
|
|
61
|
+
|
|
62
|
+
public GoogleSignIn(@NonNull GoogleSignInPlugin plugin) {
|
|
63
|
+
this.plugin = plugin;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public void initialize(@NonNull InitializeOptions options, @NonNull EmptyCallback callback) {
|
|
67
|
+
this.clientId = options.getClientId();
|
|
68
|
+
this.scopes = options.getScopes();
|
|
69
|
+
callback.success();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public void signIn(@NonNull SignInOptions options, @NonNull NonEmptyResultCallback<SignInResult> callback) {
|
|
73
|
+
if (clientId == null) {
|
|
74
|
+
callback.error(CustomExceptions.NOT_INITIALIZED);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
GetSignInWithGoogleOption.Builder optionBuilder = new GetSignInWithGoogleOption.Builder(clientId);
|
|
79
|
+
String nonce = options.getNonce();
|
|
80
|
+
if (nonce != null) {
|
|
81
|
+
optionBuilder.setNonce(nonce);
|
|
82
|
+
}
|
|
83
|
+
GetSignInWithGoogleOption signInOption = optionBuilder.build();
|
|
84
|
+
|
|
85
|
+
GetCredentialRequest request = new GetCredentialRequest.Builder().addCredentialOption(signInOption).build();
|
|
86
|
+
|
|
87
|
+
CredentialManager credentialManager = CredentialManager.create(plugin.getContext());
|
|
88
|
+
credentialManager.getCredentialAsync(
|
|
89
|
+
plugin.getActivity(),
|
|
90
|
+
request,
|
|
91
|
+
null,
|
|
92
|
+
Runnable::run,
|
|
93
|
+
new androidx.credentials.CredentialManagerCallback<
|
|
94
|
+
GetCredentialResponse,
|
|
95
|
+
androidx.credentials.exceptions.GetCredentialException
|
|
96
|
+
>() {
|
|
97
|
+
@Override
|
|
98
|
+
public void onResult(@NonNull GetCredentialResponse response) {
|
|
99
|
+
handleCredentialResponse(response, callback);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Override
|
|
103
|
+
public void onError(@NonNull androidx.credentials.exceptions.GetCredentialException e) {
|
|
104
|
+
if (e instanceof androidx.credentials.exceptions.GetCredentialCancellationException) {
|
|
105
|
+
callback.error(CustomExceptions.SIGN_IN_CANCELED);
|
|
106
|
+
} else {
|
|
107
|
+
callback.error(new Exception(e.getMessage()));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public void signOut(@NonNull EmptyCallback callback) {
|
|
115
|
+
CredentialManager credentialManager = CredentialManager.create(plugin.getContext());
|
|
116
|
+
ClearCredentialStateRequest request = new ClearCredentialStateRequest();
|
|
117
|
+
credentialManager.clearCredentialStateAsync(
|
|
118
|
+
request,
|
|
119
|
+
null,
|
|
120
|
+
Runnable::run,
|
|
121
|
+
new androidx.credentials.CredentialManagerCallback<Void, androidx.credentials.exceptions.ClearCredentialException>() {
|
|
122
|
+
@Override
|
|
123
|
+
public void onResult(@NonNull Void result) {
|
|
124
|
+
callback.success();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Override
|
|
128
|
+
public void onError(@NonNull androidx.credentials.exceptions.ClearCredentialException e) {
|
|
129
|
+
callback.error(new Exception(e.getMessage()));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public void handleAuthorizationResult(@NonNull AuthorizationResult authResult) {
|
|
136
|
+
if (pendingSignInCallback == null) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
NonEmptyResultCallback<SignInResult> callback = pendingSignInCallback;
|
|
140
|
+
String accessToken = authResult.getAccessToken();
|
|
141
|
+
String serverAuthCode = authResult.getServerAuthCode();
|
|
142
|
+
SignInResult result = new SignInResult(
|
|
143
|
+
pendingIdToken,
|
|
144
|
+
pendingUserId,
|
|
145
|
+
pendingEmail,
|
|
146
|
+
pendingDisplayName,
|
|
147
|
+
pendingGivenName,
|
|
148
|
+
pendingFamilyName,
|
|
149
|
+
pendingImageUrl,
|
|
150
|
+
accessToken,
|
|
151
|
+
serverAuthCode
|
|
152
|
+
);
|
|
153
|
+
clearPendingState();
|
|
154
|
+
callback.success(result);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public void handleAuthorizationCanceled() {
|
|
158
|
+
if (pendingSignInCallback == null) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
NonEmptyResultCallback<SignInResult> callback = pendingSignInCallback;
|
|
162
|
+
clearPendingState();
|
|
163
|
+
callback.error(CustomExceptions.SIGN_IN_CANCELED);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private void handleCredentialResponse(@NonNull GetCredentialResponse response, @NonNull NonEmptyResultCallback<SignInResult> callback) {
|
|
167
|
+
Credential credential = response.getCredential();
|
|
168
|
+
if (!(credential instanceof CustomCredential)) {
|
|
169
|
+
callback.error(new Exception("Unexpected credential type."));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
CustomCredential customCredential = (CustomCredential) credential;
|
|
173
|
+
if (!GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(customCredential.getType())) {
|
|
174
|
+
callback.error(new Exception("Unexpected credential type."));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
GoogleIdTokenCredential googleCredential = GoogleIdTokenCredential.createFrom(customCredential.getData());
|
|
179
|
+
String idToken = googleCredential.getIdToken();
|
|
180
|
+
String userId = parseUserIdFromIdToken(idToken);
|
|
181
|
+
if (userId == null) {
|
|
182
|
+
callback.error(new Exception("Failed to parse user ID from ID token."));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
String email = googleCredential.getId();
|
|
187
|
+
String displayName = googleCredential.getDisplayName();
|
|
188
|
+
String givenName = googleCredential.getGivenName();
|
|
189
|
+
String familyName = googleCredential.getFamilyName();
|
|
190
|
+
android.net.Uri profilePictureUri = googleCredential.getProfilePictureUri();
|
|
191
|
+
String imageUrl = profilePictureUri != null ? profilePictureUri.toString() : null;
|
|
192
|
+
|
|
193
|
+
if (scopes != null && scopes.length > 0) {
|
|
194
|
+
authorize(idToken, userId, email, displayName, givenName, familyName, imageUrl, callback);
|
|
195
|
+
} else {
|
|
196
|
+
SignInResult result = new SignInResult(idToken, userId, email, displayName, givenName, familyName, imageUrl, null, null);
|
|
197
|
+
callback.success(result);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private void authorize(
|
|
202
|
+
@NonNull String idToken,
|
|
203
|
+
@NonNull String userId,
|
|
204
|
+
@Nullable String email,
|
|
205
|
+
@Nullable String displayName,
|
|
206
|
+
@Nullable String givenName,
|
|
207
|
+
@Nullable String familyName,
|
|
208
|
+
@Nullable String imageUrl,
|
|
209
|
+
@NonNull NonEmptyResultCallback<SignInResult> callback
|
|
210
|
+
) {
|
|
211
|
+
List<com.google.android.gms.common.api.Scope> scopeList = new java.util.ArrayList<>();
|
|
212
|
+
for (String scope : scopes) {
|
|
213
|
+
scopeList.add(new com.google.android.gms.common.api.Scope(scope));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
AuthorizationRequest authRequest = AuthorizationRequest.builder()
|
|
217
|
+
.setRequestedScopes(scopeList)
|
|
218
|
+
.requestOfflineAccess(clientId)
|
|
219
|
+
.build();
|
|
220
|
+
|
|
221
|
+
Identity.getAuthorizationClient(plugin.getActivity())
|
|
222
|
+
.authorize(authRequest)
|
|
223
|
+
.addOnSuccessListener(authResult -> {
|
|
224
|
+
if (authResult.hasResolution()) {
|
|
225
|
+
PendingIntent pendingIntent = authResult.getPendingIntent();
|
|
226
|
+
if (pendingIntent != null) {
|
|
227
|
+
savePendingState(idToken, userId, email, displayName, givenName, familyName, imageUrl, callback);
|
|
228
|
+
plugin.launchAuthorizationIntent(pendingIntent);
|
|
229
|
+
} else {
|
|
230
|
+
callback.error(new Exception("Authorization resolution has no pending intent."));
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
String accessToken = authResult.getAccessToken();
|
|
234
|
+
String serverAuthCode = authResult.getServerAuthCode();
|
|
235
|
+
SignInResult result = new SignInResult(
|
|
236
|
+
idToken,
|
|
237
|
+
userId,
|
|
238
|
+
email,
|
|
239
|
+
displayName,
|
|
240
|
+
givenName,
|
|
241
|
+
familyName,
|
|
242
|
+
imageUrl,
|
|
243
|
+
accessToken,
|
|
244
|
+
serverAuthCode
|
|
245
|
+
);
|
|
246
|
+
callback.success(result);
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
.addOnFailureListener(e -> {
|
|
250
|
+
callback.error(new Exception(e.getMessage()));
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@Nullable
|
|
255
|
+
private String parseUserIdFromIdToken(@NonNull String idToken) {
|
|
256
|
+
try {
|
|
257
|
+
String[] parts = idToken.split("\\.");
|
|
258
|
+
if (parts.length != 3) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
byte[] decodedBytes = Base64.decode(parts[1], Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
|
|
262
|
+
String payload = new String(decodedBytes, "UTF-8");
|
|
263
|
+
JSONObject json = new JSONObject(payload);
|
|
264
|
+
return json.optString("sub", null);
|
|
265
|
+
} catch (Exception e) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private void savePendingState(
|
|
271
|
+
@NonNull String idToken,
|
|
272
|
+
@NonNull String userId,
|
|
273
|
+
@Nullable String email,
|
|
274
|
+
@Nullable String displayName,
|
|
275
|
+
@Nullable String givenName,
|
|
276
|
+
@Nullable String familyName,
|
|
277
|
+
@Nullable String imageUrl,
|
|
278
|
+
@NonNull NonEmptyResultCallback<SignInResult> callback
|
|
279
|
+
) {
|
|
280
|
+
this.pendingSignInCallback = callback;
|
|
281
|
+
this.pendingIdToken = idToken;
|
|
282
|
+
this.pendingUserId = userId;
|
|
283
|
+
this.pendingEmail = email;
|
|
284
|
+
this.pendingDisplayName = displayName;
|
|
285
|
+
this.pendingGivenName = givenName;
|
|
286
|
+
this.pendingFamilyName = familyName;
|
|
287
|
+
this.pendingImageUrl = imageUrl;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private void clearPendingState() {
|
|
291
|
+
this.pendingSignInCallback = null;
|
|
292
|
+
this.pendingIdToken = null;
|
|
293
|
+
this.pendingUserId = null;
|
|
294
|
+
this.pendingEmail = null;
|
|
295
|
+
this.pendingDisplayName = null;
|
|
296
|
+
this.pendingGivenName = null;
|
|
297
|
+
this.pendingFamilyName = null;
|
|
298
|
+
this.pendingImageUrl = null;
|
|
299
|
+
}
|
|
300
|
+
}
|
package/android/src/main/java/io/capawesome/capacitorjs/plugins/googlesignin/GoogleSignInPlugin.java
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.app.PendingIntent;
|
|
5
|
+
import android.content.IntentSender;
|
|
6
|
+
import androidx.activity.result.ActivityResult;
|
|
7
|
+
import androidx.activity.result.ActivityResultLauncher;
|
|
8
|
+
import androidx.activity.result.IntentSenderRequest;
|
|
9
|
+
import androidx.activity.result.contract.ActivityResultContracts;
|
|
10
|
+
import androidx.annotation.NonNull;
|
|
11
|
+
import androidx.annotation.Nullable;
|
|
12
|
+
import com.getcapacitor.Logger;
|
|
13
|
+
import com.getcapacitor.Plugin;
|
|
14
|
+
import com.getcapacitor.PluginCall;
|
|
15
|
+
import com.getcapacitor.PluginMethod;
|
|
16
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
17
|
+
import com.google.android.gms.auth.api.identity.AuthorizationResult;
|
|
18
|
+
import com.google.android.gms.auth.api.identity.Identity;
|
|
19
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.CustomException;
|
|
20
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.options.InitializeOptions;
|
|
21
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.options.SignInOptions;
|
|
22
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.results.SignInResult;
|
|
23
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.EmptyCallback;
|
|
24
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.NonEmptyResultCallback;
|
|
25
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.Result;
|
|
26
|
+
|
|
27
|
+
@CapacitorPlugin(name = "GoogleSignIn")
|
|
28
|
+
public class GoogleSignInPlugin extends Plugin {
|
|
29
|
+
|
|
30
|
+
public static final String ERROR_UNKNOWN_ERROR = "An unknown error has occurred.";
|
|
31
|
+
public static final String TAG = "GoogleSignInPlugin";
|
|
32
|
+
|
|
33
|
+
private GoogleSignIn implementation;
|
|
34
|
+
private ActivityResultLauncher<IntentSenderRequest> authorizationLauncher;
|
|
35
|
+
|
|
36
|
+
@Override
|
|
37
|
+
public void load() {
|
|
38
|
+
super.load();
|
|
39
|
+
this.implementation = new GoogleSignIn(this);
|
|
40
|
+
this.authorizationLauncher = getActivity()
|
|
41
|
+
.registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), this::handleAuthorizationActivityResult);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@PluginMethod
|
|
45
|
+
public void initialize(PluginCall call) {
|
|
46
|
+
try {
|
|
47
|
+
InitializeOptions options = new InitializeOptions(call);
|
|
48
|
+
EmptyCallback callback = new EmptyCallback() {
|
|
49
|
+
@Override
|
|
50
|
+
public void success() {
|
|
51
|
+
resolveCall(call);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Override
|
|
55
|
+
public void error(Exception exception) {
|
|
56
|
+
rejectCall(call, exception);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
implementation.initialize(options, callback);
|
|
60
|
+
} catch (Exception exception) {
|
|
61
|
+
rejectCall(call, exception);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@PluginMethod
|
|
66
|
+
public void signIn(PluginCall call) {
|
|
67
|
+
try {
|
|
68
|
+
SignInOptions options = new SignInOptions(call);
|
|
69
|
+
NonEmptyResultCallback<SignInResult> callback = new NonEmptyResultCallback<>() {
|
|
70
|
+
@Override
|
|
71
|
+
public void success(@NonNull SignInResult result) {
|
|
72
|
+
resolveCall(call, result);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Override
|
|
76
|
+
public void error(Exception exception) {
|
|
77
|
+
rejectCall(call, exception);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
implementation.signIn(options, callback);
|
|
81
|
+
} catch (Exception exception) {
|
|
82
|
+
rejectCall(call, exception);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@PluginMethod
|
|
87
|
+
public void handleRedirectCallback(PluginCall call) {
|
|
88
|
+
rejectCallAsUnimplemented(call);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@PluginMethod
|
|
92
|
+
public void signOut(PluginCall call) {
|
|
93
|
+
try {
|
|
94
|
+
EmptyCallback callback = new EmptyCallback() {
|
|
95
|
+
@Override
|
|
96
|
+
public void success() {
|
|
97
|
+
resolveCall(call);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Override
|
|
101
|
+
public void error(Exception exception) {
|
|
102
|
+
rejectCall(call, exception);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
implementation.signOut(callback);
|
|
106
|
+
} catch (Exception exception) {
|
|
107
|
+
rejectCall(call, exception);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public void launchAuthorizationIntent(@NonNull PendingIntent pendingIntent) {
|
|
112
|
+
IntentSenderRequest request = new IntentSenderRequest.Builder(pendingIntent).build();
|
|
113
|
+
authorizationLauncher.launch(request);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void handleAuthorizationActivityResult(@NonNull ActivityResult result) {
|
|
117
|
+
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
|
|
118
|
+
try {
|
|
119
|
+
AuthorizationResult authResult = Identity.getAuthorizationClient(getActivity()).getAuthorizationResultFromIntent(
|
|
120
|
+
result.getData()
|
|
121
|
+
);
|
|
122
|
+
implementation.handleAuthorizationResult(authResult);
|
|
123
|
+
} catch (Exception e) {
|
|
124
|
+
implementation.handleAuthorizationCanceled();
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
implementation.handleAuthorizationCanceled();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private void rejectCallAsUnimplemented(@NonNull PluginCall call) {
|
|
132
|
+
call.unimplemented("This method is not available on this platform.");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private void rejectCall(@NonNull PluginCall call, @NonNull Exception exception) {
|
|
136
|
+
String message = exception.getMessage();
|
|
137
|
+
if (message == null) {
|
|
138
|
+
message = ERROR_UNKNOWN_ERROR;
|
|
139
|
+
}
|
|
140
|
+
String code = null;
|
|
141
|
+
if (exception instanceof CustomException) {
|
|
142
|
+
code = ((CustomException) exception).getCode();
|
|
143
|
+
}
|
|
144
|
+
Logger.error(TAG, message, exception);
|
|
145
|
+
call.reject(message, code);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private void resolveCall(@NonNull PluginCall call) {
|
|
149
|
+
call.resolve();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private void resolveCall(@NonNull PluginCall call, @Nullable Result result) {
|
|
153
|
+
if (result == null) {
|
|
154
|
+
call.resolve();
|
|
155
|
+
} else {
|
|
156
|
+
call.resolve(result.toJSObject());
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin.classes;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
|
|
6
|
+
public class CustomException extends Exception {
|
|
7
|
+
|
|
8
|
+
@Nullable
|
|
9
|
+
private final String code;
|
|
10
|
+
|
|
11
|
+
public CustomException(@Nullable String code, @NonNull String message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
public String getCode() {
|
|
18
|
+
return code;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin.classes;
|
|
2
|
+
|
|
3
|
+
public class CustomExceptions {
|
|
4
|
+
|
|
5
|
+
public static final CustomException CLIENT_ID_MISSING = new CustomException(null, "clientId must be provided.");
|
|
6
|
+
public static final CustomException NOT_INITIALIZED = new CustomException(
|
|
7
|
+
null,
|
|
8
|
+
"Google Sign-In is not initialized. Call initialize() first."
|
|
9
|
+
);
|
|
10
|
+
public static final CustomException SIGN_IN_CANCELED = new CustomException("SIGN_IN_CANCELED", "The user canceled the sign-in flow.");
|
|
11
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin.classes.options;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.JSArray;
|
|
6
|
+
import com.getcapacitor.PluginCall;
|
|
7
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.classes.CustomExceptions;
|
|
8
|
+
import java.util.ArrayList;
|
|
9
|
+
import java.util.List;
|
|
10
|
+
|
|
11
|
+
public class InitializeOptions {
|
|
12
|
+
|
|
13
|
+
@NonNull
|
|
14
|
+
private final String clientId;
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
private final String[] scopes;
|
|
18
|
+
|
|
19
|
+
public InitializeOptions(@NonNull PluginCall call) throws Exception {
|
|
20
|
+
this.clientId = getClientIdFromCall(call);
|
|
21
|
+
this.scopes = getScopesFromCall(call);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@NonNull
|
|
25
|
+
public String getClientId() {
|
|
26
|
+
return clientId;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Nullable
|
|
30
|
+
public String[] getScopes() {
|
|
31
|
+
return scopes;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@NonNull
|
|
35
|
+
private static String getClientIdFromCall(@NonNull PluginCall call) throws Exception {
|
|
36
|
+
String clientId = call.getString("clientId");
|
|
37
|
+
if (clientId == null) {
|
|
38
|
+
throw CustomExceptions.CLIENT_ID_MISSING;
|
|
39
|
+
}
|
|
40
|
+
return clientId;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Nullable
|
|
44
|
+
private static String[] getScopesFromCall(@NonNull PluginCall call) {
|
|
45
|
+
JSArray scopesArray = call.getArray("scopes");
|
|
46
|
+
if (scopesArray == null) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
List<String> scopesList = scopesArray.toList();
|
|
51
|
+
return scopesList.toArray(new String[0]);
|
|
52
|
+
} catch (Exception e) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin.classes.options;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.PluginCall;
|
|
6
|
+
|
|
7
|
+
public class SignInOptions {
|
|
8
|
+
|
|
9
|
+
@Nullable
|
|
10
|
+
private final String nonce;
|
|
11
|
+
|
|
12
|
+
public SignInOptions(@NonNull PluginCall call) {
|
|
13
|
+
this.nonce = getNonceFromCall(call);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Nullable
|
|
17
|
+
public String getNonce() {
|
|
18
|
+
return nonce;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Nullable
|
|
22
|
+
private static String getNonceFromCall(@NonNull PluginCall call) {
|
|
23
|
+
return call.getString("nonce");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package io.capawesome.capacitorjs.plugins.googlesignin.classes.results;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import com.getcapacitor.JSObject;
|
|
6
|
+
import io.capawesome.capacitorjs.plugins.googlesignin.interfaces.Result;
|
|
7
|
+
import org.json.JSONObject;
|
|
8
|
+
|
|
9
|
+
public class SignInResult implements Result {
|
|
10
|
+
|
|
11
|
+
@NonNull
|
|
12
|
+
private final String idToken;
|
|
13
|
+
|
|
14
|
+
@NonNull
|
|
15
|
+
private final String userId;
|
|
16
|
+
|
|
17
|
+
@Nullable
|
|
18
|
+
private final String email;
|
|
19
|
+
|
|
20
|
+
@Nullable
|
|
21
|
+
private final String displayName;
|
|
22
|
+
|
|
23
|
+
@Nullable
|
|
24
|
+
private final String givenName;
|
|
25
|
+
|
|
26
|
+
@Nullable
|
|
27
|
+
private final String familyName;
|
|
28
|
+
|
|
29
|
+
@Nullable
|
|
30
|
+
private final String imageUrl;
|
|
31
|
+
|
|
32
|
+
@Nullable
|
|
33
|
+
private final String accessToken;
|
|
34
|
+
|
|
35
|
+
@Nullable
|
|
36
|
+
private final String serverAuthCode;
|
|
37
|
+
|
|
38
|
+
public SignInResult(
|
|
39
|
+
@NonNull String idToken,
|
|
40
|
+
@NonNull String userId,
|
|
41
|
+
@Nullable String email,
|
|
42
|
+
@Nullable String displayName,
|
|
43
|
+
@Nullable String givenName,
|
|
44
|
+
@Nullable String familyName,
|
|
45
|
+
@Nullable String imageUrl,
|
|
46
|
+
@Nullable String accessToken,
|
|
47
|
+
@Nullable String serverAuthCode
|
|
48
|
+
) {
|
|
49
|
+
this.idToken = idToken;
|
|
50
|
+
this.userId = userId;
|
|
51
|
+
this.email = email;
|
|
52
|
+
this.displayName = displayName;
|
|
53
|
+
this.givenName = givenName;
|
|
54
|
+
this.familyName = familyName;
|
|
55
|
+
this.imageUrl = imageUrl;
|
|
56
|
+
this.accessToken = accessToken;
|
|
57
|
+
this.serverAuthCode = serverAuthCode;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Override
|
|
61
|
+
@NonNull
|
|
62
|
+
public JSObject toJSObject() {
|
|
63
|
+
JSObject result = new JSObject();
|
|
64
|
+
result.put("idToken", idToken);
|
|
65
|
+
result.put("userId", userId);
|
|
66
|
+
result.put("email", email == null ? JSONObject.NULL : email);
|
|
67
|
+
result.put("displayName", displayName == null ? JSONObject.NULL : displayName);
|
|
68
|
+
result.put("givenName", givenName == null ? JSONObject.NULL : givenName);
|
|
69
|
+
result.put("familyName", familyName == null ? JSONObject.NULL : familyName);
|
|
70
|
+
result.put("imageUrl", imageUrl == null ? JSONObject.NULL : imageUrl);
|
|
71
|
+
result.put("accessToken", accessToken == null ? JSONObject.NULL : accessToken);
|
|
72
|
+
result.put("serverAuthCode", serverAuthCode == null ? JSONObject.NULL : serverAuthCode);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
File without changes
|