react-native-nitro-auth 0.5.5 → 0.5.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 +22 -17
- package/android/proguard-rules.pro +7 -1
- package/android/src/main/AndroidManifest.xml +12 -0
- package/android/src/main/cpp/PlatformAuth+Android.cpp +260 -67
- package/android/src/main/java/com/auth/AuthAdapter.kt +217 -146
- package/android/src/main/java/com/auth/GoogleSignInActivity.kt +9 -5
- package/cpp/HybridAuth.cpp +79 -64
- package/cpp/HybridAuth.hpp +9 -7
- package/cpp/JSONSerializer.hpp +3 -0
- package/ios/AuthAdapter.swift +173 -60
- package/ios/PlatformAuth+iOS.mm +10 -3
- package/lib/commonjs/Auth.web.js +50 -10
- package/lib/commonjs/Auth.web.js.map +1 -1
- package/lib/commonjs/index.web.js +30 -12
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/service.js +9 -7
- package/lib/commonjs/service.js.map +1 -1
- package/lib/commonjs/service.web.js +65 -13
- package/lib/commonjs/service.web.js.map +1 -1
- package/lib/commonjs/ui/social-button.js +19 -14
- package/lib/commonjs/ui/social-button.js.map +1 -1
- package/lib/commonjs/ui/social-button.web.js +16 -10
- package/lib/commonjs/ui/social-button.web.js.map +1 -1
- package/lib/commonjs/use-auth.js +13 -5
- package/lib/commonjs/use-auth.js.map +1 -1
- package/lib/commonjs/utils/logger.js +1 -0
- package/lib/commonjs/utils/logger.js.map +1 -1
- package/lib/module/Auth.web.js +50 -10
- package/lib/module/Auth.web.js.map +1 -1
- package/lib/module/global.d.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +2 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/service.js +9 -7
- package/lib/module/service.js.map +1 -1
- package/lib/module/service.web.js +65 -13
- package/lib/module/service.web.js.map +1 -1
- package/lib/module/ui/social-button.js +19 -14
- package/lib/module/ui/social-button.js.map +1 -1
- package/lib/module/ui/social-button.web.js +16 -10
- package/lib/module/ui/social-button.web.js.map +1 -1
- package/lib/module/use-auth.js +13 -5
- package/lib/module/use-auth.js.map +1 -1
- package/lib/module/utils/logger.js +1 -0
- package/lib/module/utils/logger.js.map +1 -1
- package/lib/typescript/commonjs/Auth.web.d.ts +5 -1
- package/lib/typescript/commonjs/Auth.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +1 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +2 -1
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/service.d.ts.map +1 -1
- package/lib/typescript/commonjs/service.web.d.ts +2 -18
- package/lib/typescript/commonjs/service.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/use-auth.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/logger.d.ts.map +1 -1
- package/lib/typescript/module/Auth.web.d.ts +5 -1
- package/lib/typescript/module/Auth.web.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +2 -1
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/service.d.ts.map +1 -1
- package/lib/typescript/module/service.web.d.ts +2 -18
- package/lib/typescript/module/service.web.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/module/use-auth.d.ts.map +1 -1
- package/lib/typescript/module/utils/logger.d.ts.map +1 -1
- package/package.json +2 -4
- package/src/Auth.web.ts +77 -11
- package/src/global.d.ts +0 -11
- package/src/index.ts +5 -1
- package/src/index.web.ts +6 -1
- package/src/service.ts +9 -7
- package/src/service.web.ts +84 -15
- package/src/ui/social-button.tsx +21 -9
- package/src/ui/social-button.web.tsx +17 -4
- package/src/use-auth.ts +35 -8
- package/src/utils/logger.ts +1 -0
package/README.md
CHANGED
|
@@ -308,12 +308,13 @@ To enable Microsoft Sign-In, you need to register an application in the Azure Po
|
|
|
308
308
|
- `nitro_auth_microsoft_client_id`
|
|
309
309
|
- `nitro_auth_microsoft_tenant` (optional)
|
|
310
310
|
- `nitro_auth_microsoft_b2c_domain` (optional)
|
|
311
|
-
-
|
|
311
|
+
- `MicrosoftAuthActivity` is **automatically declared** by the library manifest — no manual `AndroidManifest.xml` entry is required for basic Microsoft OAuth redirect handling. If you need to customize the intent-filter (e.g., restrict the host/path to your specific package and client ID), you can override it in your app manifest:
|
|
312
312
|
|
|
313
313
|
```xml
|
|
314
314
|
<activity
|
|
315
315
|
android:name="com.auth.MicrosoftAuthActivity"
|
|
316
|
-
android:exported="true"
|
|
316
|
+
android:exported="true"
|
|
317
|
+
android:launchMode="singleTask">
|
|
317
318
|
<intent-filter>
|
|
318
319
|
<action android:name="android.intent.action.VIEW" />
|
|
319
320
|
<category android:name="android.intent.category.DEFAULT" />
|
|
@@ -693,19 +694,21 @@ try {
|
|
|
693
694
|
}
|
|
694
695
|
```
|
|
695
696
|
|
|
696
|
-
| Error Code | Description
|
|
697
|
-
| ---------------------- |
|
|
698
|
-
| `cancelled` | The user cancelled the sign-in flow
|
|
699
|
-
| `
|
|
700
|
-
| `
|
|
701
|
-
| `
|
|
702
|
-
| `
|
|
703
|
-
| `
|
|
704
|
-
| `
|
|
705
|
-
| `
|
|
706
|
-
| `
|
|
707
|
-
| `
|
|
708
|
-
| `
|
|
697
|
+
| Error Code | Description |
|
|
698
|
+
| ---------------------- | --------------------------------------------------------------- |
|
|
699
|
+
| `cancelled` | The user cancelled the sign-in flow or dismissed the popup |
|
|
700
|
+
| `timeout` | The login popup/flow timed out |
|
|
701
|
+
| `popup_blocked` | The browser blocked the popup window |
|
|
702
|
+
| `network_error` | A network or connectivity error occurred |
|
|
703
|
+
| `configuration_error` | Missing client IDs, invalid tenant, or misconfigured setup |
|
|
704
|
+
| `unsupported_provider` | The provider is not supported on this platform |
|
|
705
|
+
| `invalid_state` | PKCE state mismatch — possible CSRF attack |
|
|
706
|
+
| `invalid_nonce` | Nonce mismatch in token response — possible replay attack |
|
|
707
|
+
| `token_error` | Token exchange or storage failed |
|
|
708
|
+
| `no_id_token` | No `id_token` in token response |
|
|
709
|
+
| `parse_error` | Failed to parse token response |
|
|
710
|
+
| `refresh_failed` | Refresh token flow failed (token may be expired or revoked) |
|
|
711
|
+
| `unknown` | An unknown or unmapped error occurred |
|
|
709
712
|
|
|
710
713
|
### Native Error Metadata
|
|
711
714
|
|
|
@@ -729,10 +732,12 @@ The `AuthUser.underlyingError` field carries a raw warning string when the provi
|
|
|
729
732
|
|
|
730
733
|
### Troubleshooting
|
|
731
734
|
|
|
732
|
-
- `configuration_error`: verify client IDs, URL schemes, and redirect URIs are set for the current platform.
|
|
733
|
-
- `invalid_state` or `invalid_nonce`: ensure the redirect URI in your provider console matches your app config exactly.
|
|
735
|
+
- `configuration_error`: verify client IDs, URL schemes, and redirect URIs are set for the current platform. On Android, check that the `microsoftTenant` is a non-empty valid value.
|
|
736
|
+
- `invalid_state` or `invalid_nonce`: ensure the redirect URI in your provider console matches your app config exactly. These indicate a potential CSRF or replay attack — do not retry silently.
|
|
737
|
+
- `refresh_failed`: the refresh token is likely expired or revoked. Clear the session and prompt the user to sign in again. On Android and web, structured error details from the provider (e.g. `invalid_grant`) are surfaced via `error.underlyingMessage`.
|
|
734
738
|
- `hasPlayServices` is false: prompt the user to install/update Google Play Services or disable One-Tap.
|
|
735
739
|
- Apple web login fails: confirm `appleWebClientId` is set and your domain is registered with Apple.
|
|
740
|
+
- Microsoft Android redirect hangs: confirm the `msauth://` redirect URI in your Azure app matches your package name and client ID.
|
|
736
741
|
|
|
737
742
|
### Automatic Token Refresh
|
|
738
743
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
# Nitro Auth Proguard Rules
|
|
2
|
-
-keep class com.auth
|
|
2
|
+
-keep class com.auth.AuthAdapter {
|
|
3
|
+
public static <methods>;
|
|
4
|
+
}
|
|
5
|
+
-keep class com.auth.MicrosoftAuthActivity { *; }
|
|
6
|
+
-keep class com.auth.GoogleSignInActivity { *; }
|
|
7
|
+
-keep class com.auth.NitroAuthModule { *; }
|
|
8
|
+
-keep class com.auth.NitroAuthPackage { *; }
|
|
3
9
|
-keep class com.margelo.nitro.com.auth.** { *; }
|
|
4
10
|
-keep class com.google.android.gms.auth.api.signin.** { *; }
|
|
@@ -8,5 +8,17 @@
|
|
|
8
8
|
android:name="com.auth.GoogleSignInActivity"
|
|
9
9
|
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
|
10
10
|
android:exported="false" />
|
|
11
|
+
<activity
|
|
12
|
+
android:name="com.auth.MicrosoftAuthActivity"
|
|
13
|
+
android:exported="true"
|
|
14
|
+
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
|
15
|
+
android:launchMode="singleTask">
|
|
16
|
+
<intent-filter>
|
|
17
|
+
<action android:name="android.intent.action.VIEW" />
|
|
18
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
19
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
20
|
+
<data android:scheme="msauth" />
|
|
21
|
+
</intent-filter>
|
|
22
|
+
</activity>
|
|
11
23
|
</application>
|
|
12
24
|
</manifest>
|
|
@@ -13,14 +13,6 @@ namespace margelo::nitro::NitroAuth {
|
|
|
13
13
|
|
|
14
14
|
using namespace facebook::jni;
|
|
15
15
|
|
|
16
|
-
struct JContext : JavaClass<JContext> {
|
|
17
|
-
static constexpr auto kJavaDescriptor = "Landroid/content/Context;";
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
struct JAuthAdapter : JavaClass<JAuthAdapter> {
|
|
21
|
-
static constexpr auto kJavaDescriptor = "Lcom/auth/AuthAdapter;";
|
|
22
|
-
};
|
|
23
|
-
|
|
24
16
|
static std::shared_ptr<Promise<AuthUser>> gLoginPromise;
|
|
25
17
|
static std::shared_ptr<Promise<AuthUser>> gScopesPromise;
|
|
26
18
|
static std::shared_ptr<Promise<AuthTokens>> gRefreshPromise;
|
|
@@ -29,29 +21,84 @@ static std::mutex gMutex;
|
|
|
29
21
|
static jclass gAuthAdapterClass = nullptr;
|
|
30
22
|
static jmethodID gLoginMethod = nullptr;
|
|
31
23
|
static jmethodID gRequestScopesMethod = nullptr;
|
|
24
|
+
static jmethodID gRefreshMethod = nullptr;
|
|
25
|
+
static jmethodID gRestoreMethod = nullptr;
|
|
26
|
+
static jmethodID gHasPlayMethod = nullptr;
|
|
27
|
+
static jmethodID gLogoutMethod = nullptr;
|
|
28
|
+
|
|
29
|
+
// Call from JNI_OnUnload or dispose to prevent stale refs after a module reload.
|
|
30
|
+
static void clearCachedJniRefs(JNIEnv* env) {
|
|
31
|
+
if (gAuthAdapterClass != nullptr) {
|
|
32
|
+
env->DeleteGlobalRef(gAuthAdapterClass);
|
|
33
|
+
gAuthAdapterClass = nullptr;
|
|
34
|
+
}
|
|
35
|
+
gLoginMethod = nullptr;
|
|
36
|
+
gRequestScopesMethod = nullptr;
|
|
37
|
+
gRefreshMethod = nullptr;
|
|
38
|
+
gRestoreMethod = nullptr;
|
|
39
|
+
gHasPlayMethod = nullptr;
|
|
40
|
+
gLogoutMethod = nullptr;
|
|
41
|
+
}
|
|
32
42
|
|
|
33
43
|
static void ensureAuthAdapterMethods(JNIEnv* env) {
|
|
34
|
-
if (gAuthAdapterClass != nullptr && gLoginMethod != nullptr
|
|
44
|
+
if (gAuthAdapterClass != nullptr && gLoginMethod != nullptr
|
|
45
|
+
&& gRequestScopesMethod != nullptr && gRefreshMethod != nullptr
|
|
46
|
+
&& gRestoreMethod != nullptr && gHasPlayMethod != nullptr
|
|
47
|
+
&& gLogoutMethod != nullptr) {
|
|
35
48
|
return;
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
if (gAuthAdapterClass == nullptr) {
|
|
52
|
+
jclass localAdapterClass = env->FindClass("com/auth/AuthAdapter");
|
|
53
|
+
if (localAdapterClass == nullptr) {
|
|
54
|
+
throw std::runtime_error("Unable to resolve com/auth/AuthAdapter");
|
|
55
|
+
}
|
|
56
|
+
gAuthAdapterClass = static_cast<jclass>(env->NewGlobalRef(localAdapterClass));
|
|
57
|
+
env->DeleteLocalRef(localAdapterClass);
|
|
41
58
|
}
|
|
42
|
-
gAuthAdapterClass = static_cast<jclass>(env->NewGlobalRef(localAdapterClass));
|
|
43
|
-
env->DeleteLocalRef(localAdapterClass);
|
|
44
59
|
|
|
45
|
-
gLoginMethod
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
if (gLoginMethod == nullptr) {
|
|
61
|
+
gLoginMethod = env->GetStaticMethodID(
|
|
62
|
+
gAuthAdapterClass,
|
|
63
|
+
"loginSync",
|
|
64
|
+
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;ZZZLjava/lang/String;Ljava/lang/String;)V"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (gRequestScopesMethod == nullptr) {
|
|
68
|
+
gRequestScopesMethod = env->GetStaticMethodID(
|
|
69
|
+
gAuthAdapterClass,
|
|
70
|
+
"requestScopesSync",
|
|
71
|
+
"(Landroid/content/Context;[Ljava/lang/String;)V"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (gRefreshMethod == nullptr) {
|
|
75
|
+
gRefreshMethod = env->GetStaticMethodID(
|
|
76
|
+
gAuthAdapterClass,
|
|
77
|
+
"refreshTokenSync",
|
|
78
|
+
"(Landroid/content/Context;)V"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (gRestoreMethod == nullptr) {
|
|
82
|
+
gRestoreMethod = env->GetStaticMethodID(
|
|
83
|
+
gAuthAdapterClass,
|
|
84
|
+
"restoreSession",
|
|
85
|
+
"(Landroid/content/Context;)V"
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (gHasPlayMethod == nullptr) {
|
|
89
|
+
gHasPlayMethod = env->GetStaticMethodID(
|
|
90
|
+
gAuthAdapterClass,
|
|
91
|
+
"hasPlayServices",
|
|
92
|
+
"(Landroid/content/Context;)Z"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (gLogoutMethod == nullptr) {
|
|
96
|
+
gLogoutMethod = env->GetStaticMethodID(
|
|
97
|
+
gAuthAdapterClass,
|
|
98
|
+
"logoutSync",
|
|
99
|
+
"(Landroid/content/Context;)V"
|
|
100
|
+
);
|
|
101
|
+
}
|
|
55
102
|
}
|
|
56
103
|
|
|
57
104
|
std::shared_ptr<Promise<AuthUser>> PlatformAuth::login(AuthProvider provider, const std::optional<LoginOptions>& options) {
|
|
@@ -61,11 +108,12 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::login(AuthProvider provider, co
|
|
|
61
108
|
promise->reject(std::make_exception_ptr(std::runtime_error("Android Context not initialized")));
|
|
62
109
|
return promise;
|
|
63
110
|
}
|
|
64
|
-
|
|
111
|
+
|
|
65
112
|
{
|
|
66
113
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
67
114
|
if (gLoginPromise) {
|
|
68
|
-
|
|
115
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("operation_in_progress")));
|
|
116
|
+
return promise;
|
|
69
117
|
}
|
|
70
118
|
gLoginPromise = promise;
|
|
71
119
|
}
|
|
@@ -106,15 +154,20 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::login(AuthProvider provider, co
|
|
|
106
154
|
try {
|
|
107
155
|
ensureAuthAdapterMethods(env);
|
|
108
156
|
} catch (...) {
|
|
157
|
+
{
|
|
158
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
159
|
+
gLoginPromise = nullptr;
|
|
160
|
+
}
|
|
109
161
|
promise->reject(std::current_exception());
|
|
110
162
|
return promise;
|
|
111
163
|
}
|
|
112
164
|
jclass stringClass = env->FindClass("java/lang/String");
|
|
113
165
|
jobjectArray jScopes = env->NewObjectArray(scopes.size(), stringClass, nullptr);
|
|
114
166
|
for (size_t i = 0; i < scopes.size(); i++) {
|
|
115
|
-
|
|
167
|
+
auto jstr = make_jstring(scopes[i]);
|
|
168
|
+
env->SetObjectArrayElement(jScopes, i, jstr.get());
|
|
116
169
|
}
|
|
117
|
-
|
|
170
|
+
|
|
118
171
|
local_ref<JString> providerRef = make_jstring(providerStr);
|
|
119
172
|
local_ref<JString> loginHintRef;
|
|
120
173
|
local_ref<JString> tenantRef;
|
|
@@ -130,8 +183,8 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::login(AuthProvider provider, co
|
|
|
130
183
|
promptRef = make_jstring(prompt.value());
|
|
131
184
|
}
|
|
132
185
|
|
|
133
|
-
env->CallStaticVoidMethod(gAuthAdapterClass, gLoginMethod,
|
|
134
|
-
contextPtr,
|
|
186
|
+
env->CallStaticVoidMethod(gAuthAdapterClass, gLoginMethod,
|
|
187
|
+
contextPtr,
|
|
135
188
|
providerRef.get(),
|
|
136
189
|
nullptr,
|
|
137
190
|
jScopes,
|
|
@@ -144,7 +197,18 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::login(AuthProvider provider, co
|
|
|
144
197
|
|
|
145
198
|
env->DeleteLocalRef(jScopes);
|
|
146
199
|
env->DeleteLocalRef(stringClass);
|
|
147
|
-
|
|
200
|
+
|
|
201
|
+
if (env->ExceptionCheck()) {
|
|
202
|
+
env->ExceptionDescribe();
|
|
203
|
+
env->ExceptionClear();
|
|
204
|
+
{
|
|
205
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
206
|
+
gLoginPromise = nullptr;
|
|
207
|
+
}
|
|
208
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("JNI call failed")));
|
|
209
|
+
return promise;
|
|
210
|
+
}
|
|
211
|
+
|
|
148
212
|
return promise;
|
|
149
213
|
}
|
|
150
214
|
|
|
@@ -159,7 +223,8 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::requestScopes(const std::vector
|
|
|
159
223
|
{
|
|
160
224
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
161
225
|
if (gScopesPromise) {
|
|
162
|
-
|
|
226
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("operation_in_progress")));
|
|
227
|
+
return promise;
|
|
163
228
|
}
|
|
164
229
|
gScopesPromise = promise;
|
|
165
230
|
}
|
|
@@ -168,18 +233,35 @@ std::shared_ptr<Promise<AuthUser>> PlatformAuth::requestScopes(const std::vector
|
|
|
168
233
|
try {
|
|
169
234
|
ensureAuthAdapterMethods(env);
|
|
170
235
|
} catch (...) {
|
|
236
|
+
{
|
|
237
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
238
|
+
gScopesPromise = nullptr;
|
|
239
|
+
}
|
|
171
240
|
promise->reject(std::current_exception());
|
|
172
241
|
return promise;
|
|
173
242
|
}
|
|
174
243
|
jclass stringClass = env->FindClass("java/lang/String");
|
|
175
244
|
jobjectArray jScopes = env->NewObjectArray(scopes.size(), stringClass, nullptr);
|
|
176
245
|
for (size_t i = 0; i < scopes.size(); i++) {
|
|
177
|
-
|
|
246
|
+
auto jstr = make_jstring(scopes[i]);
|
|
247
|
+
env->SetObjectArrayElement(jScopes, i, jstr.get());
|
|
178
248
|
}
|
|
179
|
-
|
|
249
|
+
|
|
180
250
|
env->CallStaticVoidMethod(gAuthAdapterClass, gRequestScopesMethod, contextPtr, jScopes);
|
|
181
251
|
env->DeleteLocalRef(jScopes);
|
|
182
252
|
env->DeleteLocalRef(stringClass);
|
|
253
|
+
|
|
254
|
+
if (env->ExceptionCheck()) {
|
|
255
|
+
env->ExceptionDescribe();
|
|
256
|
+
env->ExceptionClear();
|
|
257
|
+
{
|
|
258
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
259
|
+
gScopesPromise = nullptr;
|
|
260
|
+
}
|
|
261
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("JNI call failed")));
|
|
262
|
+
return promise;
|
|
263
|
+
}
|
|
264
|
+
|
|
183
265
|
return promise;
|
|
184
266
|
}
|
|
185
267
|
|
|
@@ -194,14 +276,37 @@ std::shared_ptr<Promise<AuthTokens>> PlatformAuth::refreshToken() {
|
|
|
194
276
|
{
|
|
195
277
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
196
278
|
if (gRefreshPromise) {
|
|
197
|
-
|
|
279
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("operation_in_progress")));
|
|
280
|
+
return promise;
|
|
198
281
|
}
|
|
199
282
|
gRefreshPromise = promise;
|
|
200
283
|
}
|
|
201
284
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
285
|
+
JNIEnv* env = Environment::current();
|
|
286
|
+
try {
|
|
287
|
+
ensureAuthAdapterMethods(env);
|
|
288
|
+
} catch (...) {
|
|
289
|
+
{
|
|
290
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
291
|
+
gRefreshPromise = nullptr;
|
|
292
|
+
}
|
|
293
|
+
promise->reject(std::current_exception());
|
|
294
|
+
return promise;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
env->CallStaticVoidMethod(gAuthAdapterClass, gRefreshMethod, contextPtr);
|
|
298
|
+
|
|
299
|
+
if (env->ExceptionCheck()) {
|
|
300
|
+
env->ExceptionDescribe();
|
|
301
|
+
env->ExceptionClear();
|
|
302
|
+
{
|
|
303
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
304
|
+
gRefreshPromise = nullptr;
|
|
305
|
+
}
|
|
306
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("JNI call failed")));
|
|
307
|
+
return promise;
|
|
308
|
+
}
|
|
309
|
+
|
|
205
310
|
return promise;
|
|
206
311
|
}
|
|
207
312
|
|
|
@@ -216,33 +321,79 @@ std::shared_ptr<Promise<std::optional<AuthUser>>> PlatformAuth::silentRestore()
|
|
|
216
321
|
{
|
|
217
322
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
218
323
|
if (gSilentPromise) {
|
|
219
|
-
|
|
324
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("operation_in_progress")));
|
|
325
|
+
return promise;
|
|
220
326
|
}
|
|
221
327
|
gSilentPromise = promise;
|
|
222
328
|
}
|
|
223
329
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
330
|
+
JNIEnv* env = Environment::current();
|
|
331
|
+
try {
|
|
332
|
+
ensureAuthAdapterMethods(env);
|
|
333
|
+
} catch (...) {
|
|
334
|
+
{
|
|
335
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
336
|
+
gSilentPromise = nullptr;
|
|
337
|
+
}
|
|
338
|
+
promise->reject(std::current_exception());
|
|
339
|
+
return promise;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
env->CallStaticVoidMethod(gAuthAdapterClass, gRestoreMethod, contextPtr);
|
|
343
|
+
|
|
344
|
+
if (env->ExceptionCheck()) {
|
|
345
|
+
env->ExceptionDescribe();
|
|
346
|
+
env->ExceptionClear();
|
|
347
|
+
{
|
|
348
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
349
|
+
gSilentPromise = nullptr;
|
|
350
|
+
}
|
|
351
|
+
promise->reject(std::make_exception_ptr(std::runtime_error("JNI call failed")));
|
|
352
|
+
return promise;
|
|
353
|
+
}
|
|
354
|
+
|
|
227
355
|
return promise;
|
|
228
356
|
}
|
|
229
357
|
|
|
230
358
|
bool PlatformAuth::hasPlayServices() {
|
|
231
359
|
auto contextPtr = static_cast<jobject>(AuthCache::getAndroidContext());
|
|
232
360
|
if (!contextPtr) return false;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
361
|
+
|
|
362
|
+
JNIEnv* env = Environment::current();
|
|
363
|
+
try {
|
|
364
|
+
ensureAuthAdapterMethods(env);
|
|
365
|
+
} catch (...) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
jboolean result = env->CallStaticBooleanMethod(gAuthAdapterClass, gHasPlayMethod, contextPtr);
|
|
370
|
+
|
|
371
|
+
if (env->ExceptionCheck()) {
|
|
372
|
+
env->ExceptionDescribe();
|
|
373
|
+
env->ExceptionClear();
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return result;
|
|
237
378
|
}
|
|
238
379
|
|
|
239
380
|
void PlatformAuth::logout() {
|
|
240
381
|
auto contextPtr = static_cast<jobject>(AuthCache::getAndroidContext());
|
|
241
382
|
if (!contextPtr) return;
|
|
242
383
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
384
|
+
JNIEnv* env = Environment::current();
|
|
385
|
+
try {
|
|
386
|
+
ensureAuthAdapterMethods(env);
|
|
387
|
+
} catch (...) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
env->CallStaticVoidMethod(gAuthAdapterClass, gLogoutMethod, contextPtr);
|
|
392
|
+
|
|
393
|
+
if (env->ExceptionCheck()) {
|
|
394
|
+
env->ExceptionDescribe();
|
|
395
|
+
env->ExceptionClear();
|
|
396
|
+
}
|
|
246
397
|
}
|
|
247
398
|
|
|
248
399
|
extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeInitialize(JNIEnv*, jclass, jobject context) {
|
|
@@ -250,22 +401,30 @@ extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeInitialize(JNI
|
|
|
250
401
|
}
|
|
251
402
|
|
|
252
403
|
extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeOnLoginSuccess(
|
|
253
|
-
JNIEnv* env, jclass,
|
|
254
|
-
jstring provider, jstring email, jstring name, jstring photo, jstring idToken, jstring accessToken, jstring serverAuthCode, jobjectArray scopes, jobject expirationTime) {
|
|
255
|
-
|
|
404
|
+
JNIEnv* env, jclass,
|
|
405
|
+
jstring origin, jstring provider, jstring email, jstring name, jstring photo, jstring idToken, jstring accessToken, jstring serverAuthCode, jobjectArray scopes, jobject expirationTime) {
|
|
406
|
+
|
|
407
|
+
const char* originCStr = env->GetStringUTFChars(origin, nullptr);
|
|
408
|
+
std::string originStr(originCStr);
|
|
409
|
+
env->ReleaseStringUTFChars(origin, originCStr);
|
|
410
|
+
|
|
256
411
|
std::shared_ptr<Promise<AuthUser>> loginPromise;
|
|
257
412
|
std::shared_ptr<Promise<AuthUser>> scopesPromise;
|
|
258
413
|
std::shared_ptr<Promise<std::optional<AuthUser>>> silentPromise;
|
|
259
414
|
{
|
|
260
415
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
416
|
+
if (originStr == "login") {
|
|
417
|
+
loginPromise = gLoginPromise;
|
|
418
|
+
gLoginPromise = nullptr;
|
|
419
|
+
} else if (originStr == "scopes") {
|
|
420
|
+
scopesPromise = gScopesPromise;
|
|
421
|
+
gScopesPromise = nullptr;
|
|
422
|
+
} else if (originStr == "silent") {
|
|
423
|
+
silentPromise = gSilentPromise;
|
|
424
|
+
gSilentPromise = nullptr;
|
|
425
|
+
}
|
|
267
426
|
}
|
|
268
|
-
|
|
427
|
+
|
|
269
428
|
AuthUser user;
|
|
270
429
|
const char* providerCStr = env->GetStringUTFChars(provider, nullptr);
|
|
271
430
|
std::string providerStr(providerCStr);
|
|
@@ -333,19 +492,27 @@ extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeOnLoginSuccess
|
|
|
333
492
|
}
|
|
334
493
|
|
|
335
494
|
extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeOnLoginError(
|
|
336
|
-
JNIEnv* env, jclass, jstring error, jstring underlyingError) {
|
|
337
|
-
|
|
495
|
+
JNIEnv* env, jclass, jstring origin, jstring error, jstring underlyingError) {
|
|
496
|
+
|
|
497
|
+
const char* originCStr = env->GetStringUTFChars(origin, nullptr);
|
|
498
|
+
std::string originStr(originCStr);
|
|
499
|
+
env->ReleaseStringUTFChars(origin, originCStr);
|
|
500
|
+
|
|
338
501
|
std::shared_ptr<Promise<AuthUser>> loginPromise;
|
|
339
502
|
std::shared_ptr<Promise<AuthUser>> scopesPromise;
|
|
340
503
|
std::shared_ptr<Promise<std::optional<AuthUser>>> silentPromise;
|
|
341
504
|
{
|
|
342
505
|
std::lock_guard<std::mutex> lock(gMutex);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
506
|
+
if (originStr == "login") {
|
|
507
|
+
loginPromise = gLoginPromise;
|
|
508
|
+
gLoginPromise = nullptr;
|
|
509
|
+
} else if (originStr == "scopes") {
|
|
510
|
+
scopesPromise = gScopesPromise;
|
|
511
|
+
gScopesPromise = nullptr;
|
|
512
|
+
} else if (originStr == "silent") {
|
|
513
|
+
silentPromise = gSilentPromise;
|
|
514
|
+
gSilentPromise = nullptr;
|
|
515
|
+
}
|
|
349
516
|
}
|
|
350
517
|
|
|
351
518
|
const char* errorCStr = env->GetStringUTFChars(error, nullptr);
|
|
@@ -423,4 +590,30 @@ extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeOnRefreshError
|
|
|
423
590
|
}
|
|
424
591
|
}
|
|
425
592
|
|
|
593
|
+
extern "C" JNIEXPORT void JNICALL Java_com_auth_AuthAdapter_nativeDispose(JNIEnv* env, jclass) {
|
|
594
|
+
std::shared_ptr<Promise<AuthUser>> loginPromise;
|
|
595
|
+
std::shared_ptr<Promise<AuthUser>> scopesPromise;
|
|
596
|
+
std::shared_ptr<Promise<AuthTokens>> refreshPromise;
|
|
597
|
+
std::shared_ptr<Promise<std::optional<AuthUser>>> silentPromise;
|
|
598
|
+
{
|
|
599
|
+
std::lock_guard<std::mutex> lock(gMutex);
|
|
600
|
+
loginPromise = std::move(gLoginPromise);
|
|
601
|
+
scopesPromise = std::move(gScopesPromise);
|
|
602
|
+
refreshPromise = std::move(gRefreshPromise);
|
|
603
|
+
silentPromise = std::move(gSilentPromise);
|
|
604
|
+
gLoginPromise = nullptr;
|
|
605
|
+
gScopesPromise = nullptr;
|
|
606
|
+
gRefreshPromise = nullptr;
|
|
607
|
+
gSilentPromise = nullptr;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
auto disposed = std::make_exception_ptr(std::runtime_error("disposed"));
|
|
611
|
+
if (loginPromise) loginPromise->reject(disposed);
|
|
612
|
+
if (scopesPromise) scopesPromise->reject(disposed);
|
|
613
|
+
if (refreshPromise) refreshPromise->reject(disposed);
|
|
614
|
+
if (silentPromise) silentPromise->reject(disposed);
|
|
615
|
+
|
|
616
|
+
clearCachedJniRefs(env);
|
|
617
|
+
}
|
|
618
|
+
|
|
426
619
|
} // namespace margelo::nitro::NitroAuth
|