react-native-nitro-auth 0.5.5 → 0.5.7
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 +30 -19
- package/android/proguard-rules.pro +7 -1
- package/android/src/main/AndroidManifest.xml +12 -0
- package/android/src/main/cpp/PlatformAuth+Android.cpp +261 -68
- package/android/src/main/java/com/auth/AuthAdapter.kt +250 -157
- 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 +208 -66
- package/ios/PlatformAuth+iOS.mm +30 -4
- 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 +25 -19
- 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 +34 -10
- package/lib/commonjs/use-auth.js.map +1 -1
- package/lib/commonjs/utils/auth-error.js +1 -1
- package/lib/commonjs/utils/auth-error.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 +25 -19
- 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 +34 -10
- package/lib/module/use-auth.js.map +1 -1
- package/lib/module/utils/auth-error.js +1 -1
- package/lib/module/utils/auth-error.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.nitro.d.ts +2 -2
- package/lib/typescript/commonjs/Auth.nitro.d.ts.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/auth-error.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/logger.d.ts.map +1 -1
- package/lib/typescript/module/Auth.nitro.d.ts +2 -2
- package/lib/typescript/module/Auth.nitro.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/auth-error.d.ts.map +1 -1
- package/lib/typescript/module/utils/logger.d.ts.map +1 -1
- package/nitro.json +4 -1
- package/nitrogen/generated/ios/NitroAuth+autolinking.rb +2 -0
- package/package.json +3 -4
- package/src/Auth.nitro.ts +3 -1
- 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 +26 -19
- 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 +65 -9
- package/src/utils/auth-error.ts +2 -0
- package/src/utils/logger.ts +1 -0
package/src/Auth.web.ts
CHANGED
|
@@ -24,6 +24,7 @@ const WEB_STORAGE_MODES = new Set([
|
|
|
24
24
|
STORAGE_MODE_MEMORY,
|
|
25
25
|
] as const);
|
|
26
26
|
const inMemoryWebStorage = new Map<string, string>();
|
|
27
|
+
let _appleSdkLoadPromise: Promise<void> | undefined;
|
|
27
28
|
|
|
28
29
|
type WebStorageDriver = {
|
|
29
30
|
save(key: string, value: string): void;
|
|
@@ -152,6 +153,7 @@ const parseAuthWebExtraConfig = (value: unknown): AuthWebExtraConfig => {
|
|
|
152
153
|
|
|
153
154
|
const getConfig = (): AuthWebExtraConfig => {
|
|
154
155
|
try {
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
155
157
|
const Constants = require("expo-constants").default;
|
|
156
158
|
return parseAuthWebExtraConfig(Constants.expoConfig?.extra);
|
|
157
159
|
} catch (error) {
|
|
@@ -175,7 +177,8 @@ class AuthWeb implements Auth {
|
|
|
175
177
|
private _browserStorageResolved = false;
|
|
176
178
|
private _browserStorageCache: Storage | undefined;
|
|
177
179
|
private _refreshPromise: Promise<AuthTokens> | undefined;
|
|
178
|
-
private
|
|
180
|
+
private _pendingGoogleNonce: string | undefined;
|
|
181
|
+
private _loginInFlight: boolean = false;
|
|
179
182
|
|
|
180
183
|
constructor() {
|
|
181
184
|
this._config = getConfig();
|
|
@@ -303,6 +306,7 @@ class AuthWeb implements Auth {
|
|
|
303
306
|
const storage = this.getBrowserStorage();
|
|
304
307
|
if (storage) {
|
|
305
308
|
storage.removeItem(key);
|
|
309
|
+
return;
|
|
306
310
|
}
|
|
307
311
|
inMemoryWebStorage.delete(key);
|
|
308
312
|
}
|
|
@@ -539,7 +543,7 @@ class AuthWeb implements Auth {
|
|
|
539
543
|
const refreshToken = this.loadRefreshToken();
|
|
540
544
|
|
|
541
545
|
if (!refreshToken) {
|
|
542
|
-
throw new
|
|
546
|
+
throw new AuthWebError("refresh_failed", "No refresh token available");
|
|
543
547
|
}
|
|
544
548
|
|
|
545
549
|
const clientId = this._config.microsoftClientId;
|
|
@@ -645,13 +649,27 @@ class AuthWeb implements Auth {
|
|
|
645
649
|
|
|
646
650
|
if (msg.includes("cancel") || msg.includes("popup_closed")) {
|
|
647
651
|
mappedMsg = "cancelled";
|
|
652
|
+
} else if (msg.includes("access_denied")) {
|
|
653
|
+
mappedMsg = "cancelled";
|
|
648
654
|
} else if (msg.includes("timeout")) {
|
|
649
655
|
mappedMsg = "timeout";
|
|
650
656
|
} else if (msg.includes("popup blocked")) {
|
|
651
657
|
mappedMsg = "popup_blocked";
|
|
652
|
-
} else if (
|
|
658
|
+
} else if (
|
|
659
|
+
msg.includes("network") ||
|
|
660
|
+
msg.includes("server_error") ||
|
|
661
|
+
msg.includes("temporarily_unavailable")
|
|
662
|
+
) {
|
|
653
663
|
mappedMsg = "network_error";
|
|
654
|
-
} else if (msg.includes("
|
|
664
|
+
} else if (msg.includes("invalid_grant") || msg.includes("invalid_token")) {
|
|
665
|
+
mappedMsg = "refresh_failed";
|
|
666
|
+
} else if (
|
|
667
|
+
msg.includes("invalid_scope") ||
|
|
668
|
+
msg.includes("unauthorized_client") ||
|
|
669
|
+
msg.includes("invalid_client") ||
|
|
670
|
+
msg.includes("client id") ||
|
|
671
|
+
msg.includes("config")
|
|
672
|
+
) {
|
|
655
673
|
mappedMsg = "configuration_error";
|
|
656
674
|
}
|
|
657
675
|
|
|
@@ -746,6 +764,24 @@ class AuthWeb implements Auth {
|
|
|
746
764
|
private async loginGoogle(
|
|
747
765
|
scopes: string[],
|
|
748
766
|
loginHint?: string,
|
|
767
|
+
): Promise<void> {
|
|
768
|
+
if (this._loginInFlight) {
|
|
769
|
+
throw new AuthWebError(
|
|
770
|
+
"cancelled",
|
|
771
|
+
"Another login is already in progress",
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
this._loginInFlight = true;
|
|
775
|
+
try {
|
|
776
|
+
await this._loginGoogleInner(scopes, loginHint);
|
|
777
|
+
} finally {
|
|
778
|
+
this._loginInFlight = false;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
private async _loginGoogleInner(
|
|
783
|
+
scopes: string[],
|
|
784
|
+
loginHint?: string,
|
|
749
785
|
): Promise<void> {
|
|
750
786
|
const clientId = this._config.googleWebClientId;
|
|
751
787
|
|
|
@@ -755,6 +791,8 @@ class AuthWeb implements Auth {
|
|
|
755
791
|
);
|
|
756
792
|
}
|
|
757
793
|
|
|
794
|
+
const nonce = crypto.randomUUID();
|
|
795
|
+
this._pendingGoogleNonce = nonce;
|
|
758
796
|
return new Promise((resolve, reject) => {
|
|
759
797
|
const redirectUri = window.location.origin;
|
|
760
798
|
const authUrl = new URL("https://accounts.google.com/o/oauth2/v2/auth");
|
|
@@ -762,7 +800,7 @@ class AuthWeb implements Auth {
|
|
|
762
800
|
authUrl.searchParams.set("redirect_uri", redirectUri);
|
|
763
801
|
authUrl.searchParams.set("response_type", "id_token token code");
|
|
764
802
|
authUrl.searchParams.set("scope", scopes.join(" "));
|
|
765
|
-
authUrl.searchParams.set("nonce",
|
|
803
|
+
authUrl.searchParams.set("nonce", nonce);
|
|
766
804
|
authUrl.searchParams.set("access_type", "offline");
|
|
767
805
|
authUrl.searchParams.set("prompt", "consent");
|
|
768
806
|
|
|
@@ -798,6 +836,13 @@ class AuthWeb implements Auth {
|
|
|
798
836
|
throw new Error("No id_token in response");
|
|
799
837
|
}
|
|
800
838
|
|
|
839
|
+
const decoded = this.parseJwtPayload(idToken);
|
|
840
|
+
if (decoded["nonce"] !== this._pendingGoogleNonce) {
|
|
841
|
+
this._pendingGoogleNonce = undefined;
|
|
842
|
+
throw new Error("Nonce mismatch - possible replay attack");
|
|
843
|
+
}
|
|
844
|
+
this._pendingGoogleNonce = undefined;
|
|
845
|
+
|
|
801
846
|
this._grantedScopes = scopes;
|
|
802
847
|
this.saveValue(SCOPES_KEY, JSON.stringify(scopes));
|
|
803
848
|
|
|
@@ -842,6 +887,26 @@ class AuthWeb implements Auth {
|
|
|
842
887
|
loginHint?: string,
|
|
843
888
|
tenant?: string,
|
|
844
889
|
prompt?: string,
|
|
890
|
+
): Promise<void> {
|
|
891
|
+
if (this._loginInFlight) {
|
|
892
|
+
throw new AuthWebError(
|
|
893
|
+
"cancelled",
|
|
894
|
+
"Another login is already in progress",
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
this._loginInFlight = true;
|
|
898
|
+
try {
|
|
899
|
+
await this._loginMicrosoftInner(scopes, loginHint, tenant, prompt);
|
|
900
|
+
} finally {
|
|
901
|
+
this._loginInFlight = false;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
private async _loginMicrosoftInner(
|
|
906
|
+
scopes: string[],
|
|
907
|
+
loginHint?: string,
|
|
908
|
+
tenant?: string,
|
|
909
|
+
prompt?: string,
|
|
845
910
|
): Promise<void> {
|
|
846
911
|
const clientId = this._config.microsoftClientId;
|
|
847
912
|
|
|
@@ -1074,11 +1139,11 @@ class AuthWeb implements Auth {
|
|
|
1074
1139
|
return;
|
|
1075
1140
|
}
|
|
1076
1141
|
|
|
1077
|
-
if (
|
|
1078
|
-
return
|
|
1142
|
+
if (_appleSdkLoadPromise) {
|
|
1143
|
+
return _appleSdkLoadPromise;
|
|
1079
1144
|
}
|
|
1080
1145
|
|
|
1081
|
-
|
|
1146
|
+
_appleSdkLoadPromise = new Promise<void>((resolve, reject) => {
|
|
1082
1147
|
const scriptId = "nitro-auth-apple-sdk";
|
|
1083
1148
|
const existingScript = document.getElementById(
|
|
1084
1149
|
scriptId,
|
|
@@ -1102,7 +1167,7 @@ class AuthWeb implements Auth {
|
|
|
1102
1167
|
existingScript.addEventListener(
|
|
1103
1168
|
"error",
|
|
1104
1169
|
() => {
|
|
1105
|
-
|
|
1170
|
+
_appleSdkLoadPromise = undefined;
|
|
1106
1171
|
reject(new Error("Failed to load Apple SDK"));
|
|
1107
1172
|
},
|
|
1108
1173
|
{ once: true },
|
|
@@ -1119,13 +1184,13 @@ class AuthWeb implements Auth {
|
|
|
1119
1184
|
resolve();
|
|
1120
1185
|
};
|
|
1121
1186
|
script.onerror = () => {
|
|
1122
|
-
|
|
1187
|
+
_appleSdkLoadPromise = undefined;
|
|
1123
1188
|
reject(new Error("Failed to load Apple SDK"));
|
|
1124
1189
|
};
|
|
1125
1190
|
document.head.appendChild(script);
|
|
1126
1191
|
});
|
|
1127
1192
|
|
|
1128
|
-
return
|
|
1193
|
+
return _appleSdkLoadPromise;
|
|
1129
1194
|
}
|
|
1130
1195
|
|
|
1131
1196
|
private async loginApple(): Promise<void> {
|
|
@@ -1199,6 +1264,7 @@ class AuthWeb implements Auth {
|
|
|
1199
1264
|
logger.setEnabled(enabled);
|
|
1200
1265
|
}
|
|
1201
1266
|
|
|
1267
|
+
/** @internal Reserved for future use — not part of the public API */
|
|
1202
1268
|
setWebStorageAdapter(adapter: JSStorageAdapter | undefined): void {
|
|
1203
1269
|
this._storageAdapter = adapter
|
|
1204
1270
|
? this.createWebStorageDriver(adapter)
|
package/src/global.d.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
declare global {
|
|
2
2
|
interface Window {
|
|
3
|
-
google?: {
|
|
4
|
-
accounts: {
|
|
5
|
-
id: {
|
|
6
|
-
initialize: (config: {
|
|
7
|
-
client_id: string;
|
|
8
|
-
callback: (response: { credential: string }) => void;
|
|
9
|
-
}) => void;
|
|
10
|
-
prompt: () => void;
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
3
|
AppleID?: {
|
|
15
4
|
auth: {
|
|
16
5
|
init: (config: {
|
package/src/index.ts
CHANGED
|
@@ -2,4 +2,8 @@ export * from "./Auth.nitro";
|
|
|
2
2
|
export * from "./ui/social-button";
|
|
3
3
|
export { useAuth, type UseAuthReturn } from "./use-auth";
|
|
4
4
|
export { AuthService } from "./service";
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
AuthError,
|
|
7
|
+
isAuthErrorCode,
|
|
8
|
+
toAuthErrorCode,
|
|
9
|
+
} from "./utils/auth-error";
|
package/src/index.web.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export * from "./Auth.nitro";
|
|
2
2
|
export * from "./ui/social-button.web";
|
|
3
|
-
export
|
|
3
|
+
export { useAuth, type UseAuthReturn } from "./use-auth";
|
|
4
4
|
export { AuthService } from "./service.web";
|
|
5
|
+
export {
|
|
6
|
+
AuthError,
|
|
7
|
+
isAuthErrorCode,
|
|
8
|
+
toAuthErrorCode,
|
|
9
|
+
} from "./utils/auth-error";
|
package/src/service.ts
CHANGED
|
@@ -8,28 +8,34 @@ import type {
|
|
|
8
8
|
} from "./Auth.nitro";
|
|
9
9
|
import { AuthError } from "./utils/auth-error";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
let nitroAuth: Auth | undefined;
|
|
12
|
+
|
|
13
|
+
function getNitroAuth(): Auth {
|
|
14
|
+
nitroAuth ??= NitroModules.createHybridObject<Auth>("Auth");
|
|
15
|
+
return nitroAuth;
|
|
16
|
+
}
|
|
12
17
|
|
|
13
18
|
export const AuthService: Auth = {
|
|
14
19
|
get name() {
|
|
15
|
-
return
|
|
20
|
+
return getNitroAuth().name;
|
|
16
21
|
},
|
|
17
22
|
|
|
18
23
|
get currentUser() {
|
|
19
|
-
return
|
|
24
|
+
return getNitroAuth().currentUser;
|
|
20
25
|
},
|
|
21
26
|
|
|
22
27
|
get grantedScopes() {
|
|
23
|
-
return
|
|
28
|
+
return getNitroAuth().grantedScopes;
|
|
24
29
|
},
|
|
25
30
|
|
|
26
31
|
get hasPlayServices() {
|
|
27
|
-
return
|
|
32
|
+
return getNitroAuth().hasPlayServices;
|
|
28
33
|
},
|
|
29
34
|
|
|
30
35
|
async login(provider: AuthProvider, options?: LoginOptions) {
|
|
31
36
|
try {
|
|
32
|
-
|
|
37
|
+
await getNitroAuth().login(provider, options);
|
|
38
|
+
return;
|
|
33
39
|
} catch (e) {
|
|
34
40
|
throw AuthError.from(e);
|
|
35
41
|
}
|
|
@@ -37,7 +43,8 @@ export const AuthService: Auth = {
|
|
|
37
43
|
|
|
38
44
|
async requestScopes(scopes: string[]) {
|
|
39
45
|
try {
|
|
40
|
-
|
|
46
|
+
await getNitroAuth().requestScopes(scopes);
|
|
47
|
+
return;
|
|
41
48
|
} catch (e) {
|
|
42
49
|
throw AuthError.from(e);
|
|
43
50
|
}
|
|
@@ -45,7 +52,8 @@ export const AuthService: Auth = {
|
|
|
45
52
|
|
|
46
53
|
async revokeScopes(scopes: string[]) {
|
|
47
54
|
try {
|
|
48
|
-
|
|
55
|
+
await getNitroAuth().revokeScopes(scopes);
|
|
56
|
+
return;
|
|
49
57
|
} catch (e) {
|
|
50
58
|
throw AuthError.from(e);
|
|
51
59
|
}
|
|
@@ -53,7 +61,7 @@ export const AuthService: Auth = {
|
|
|
53
61
|
|
|
54
62
|
async getAccessToken() {
|
|
55
63
|
try {
|
|
56
|
-
return await
|
|
64
|
+
return await getNitroAuth().getAccessToken();
|
|
57
65
|
} catch (e) {
|
|
58
66
|
throw AuthError.from(e);
|
|
59
67
|
}
|
|
@@ -61,43 +69,42 @@ export const AuthService: Auth = {
|
|
|
61
69
|
|
|
62
70
|
async refreshToken() {
|
|
63
71
|
try {
|
|
64
|
-
return await
|
|
72
|
+
return await getNitroAuth().refreshToken();
|
|
65
73
|
} catch (e) {
|
|
66
74
|
throw AuthError.from(e);
|
|
67
75
|
}
|
|
68
76
|
},
|
|
69
77
|
|
|
70
78
|
logout() {
|
|
71
|
-
|
|
79
|
+
getNitroAuth().logout();
|
|
72
80
|
},
|
|
73
81
|
|
|
74
82
|
async silentRestore() {
|
|
75
83
|
try {
|
|
76
|
-
|
|
84
|
+
await getNitroAuth().silentRestore();
|
|
85
|
+
return;
|
|
77
86
|
} catch (e) {
|
|
78
87
|
throw AuthError.from(e);
|
|
79
88
|
}
|
|
80
89
|
},
|
|
81
90
|
|
|
82
91
|
onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
|
|
83
|
-
return
|
|
84
|
-
callback(user);
|
|
85
|
-
});
|
|
92
|
+
return getNitroAuth().onAuthStateChanged(callback);
|
|
86
93
|
},
|
|
87
94
|
|
|
88
95
|
onTokensRefreshed(callback: (tokens: AuthTokens) => void) {
|
|
89
|
-
return
|
|
96
|
+
return getNitroAuth().onTokensRefreshed(callback);
|
|
90
97
|
},
|
|
91
98
|
|
|
92
99
|
setLoggingEnabled(enabled: boolean) {
|
|
93
|
-
|
|
100
|
+
getNitroAuth().setLoggingEnabled(enabled);
|
|
94
101
|
},
|
|
95
102
|
|
|
96
103
|
dispose() {
|
|
97
|
-
|
|
104
|
+
getNitroAuth().dispose();
|
|
98
105
|
},
|
|
99
106
|
|
|
100
107
|
equals(other: Parameters<Auth["equals"]>[0]): boolean {
|
|
101
|
-
return
|
|
108
|
+
return getNitroAuth().equals(other);
|
|
102
109
|
},
|
|
103
110
|
};
|
package/src/service.web.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Auth,
|
|
3
|
+
AuthProvider,
|
|
4
|
+
AuthTokens,
|
|
5
|
+
LoginOptions,
|
|
6
|
+
AuthUser,
|
|
7
|
+
} from "./Auth.nitro";
|
|
1
8
|
import { AuthModule } from "./Auth.web";
|
|
9
|
+
import { AuthError } from "./utils/auth-error";
|
|
2
10
|
|
|
3
|
-
export const AuthService = {
|
|
4
|
-
...AuthModule,
|
|
5
|
-
|
|
11
|
+
export const AuthService: Auth = {
|
|
6
12
|
get name() {
|
|
7
13
|
return AuthModule.name;
|
|
8
14
|
},
|
|
@@ -19,16 +25,79 @@ export const AuthService = {
|
|
|
19
25
|
return AuthModule.hasPlayServices;
|
|
20
26
|
},
|
|
21
27
|
|
|
22
|
-
login:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
async login(provider: AuthProvider, options?: LoginOptions) {
|
|
29
|
+
try {
|
|
30
|
+
await AuthModule.login(provider, options);
|
|
31
|
+
return;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
throw AuthError.from(e);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async requestScopes(scopes: string[]) {
|
|
38
|
+
try {
|
|
39
|
+
await AuthModule.requestScopes(scopes);
|
|
40
|
+
return;
|
|
41
|
+
} catch (e) {
|
|
42
|
+
throw AuthError.from(e);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
async revokeScopes(scopes: string[]) {
|
|
47
|
+
try {
|
|
48
|
+
await AuthModule.revokeScopes(scopes);
|
|
49
|
+
return;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
throw AuthError.from(e);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
async getAccessToken() {
|
|
56
|
+
try {
|
|
57
|
+
return await AuthModule.getAccessToken();
|
|
58
|
+
} catch (e) {
|
|
59
|
+
throw AuthError.from(e);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
async refreshToken() {
|
|
64
|
+
try {
|
|
65
|
+
return await AuthModule.refreshToken();
|
|
66
|
+
} catch (e) {
|
|
67
|
+
throw AuthError.from(e);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
logout() {
|
|
72
|
+
AuthModule.logout();
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
async silentRestore() {
|
|
76
|
+
try {
|
|
77
|
+
await AuthModule.silentRestore();
|
|
78
|
+
return;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
throw AuthError.from(e);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
|
|
85
|
+
return AuthModule.onAuthStateChanged(callback);
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
onTokensRefreshed(callback: (tokens: AuthTokens) => void) {
|
|
89
|
+
return AuthModule.onTokensRefreshed(callback);
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
setLoggingEnabled(enabled: boolean) {
|
|
93
|
+
AuthModule.setLoggingEnabled(enabled);
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
dispose() {
|
|
97
|
+
AuthModule.dispose();
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
equals(other: Parameters<Auth["equals"]>[0]): boolean {
|
|
101
|
+
return AuthModule.equals(other);
|
|
102
|
+
},
|
|
34
103
|
};
|
package/src/ui/social-button.tsx
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
View,
|
|
8
8
|
ActivityIndicator,
|
|
9
9
|
} from "react-native";
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
10
|
+
import { AuthService } from "../service";
|
|
11
|
+
import { logger } from "../utils/logger";
|
|
12
|
+
import type { AuthProvider, AuthUser } from "../Auth.nitro";
|
|
12
13
|
|
|
13
14
|
export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
|
|
14
15
|
|
|
@@ -56,8 +57,7 @@ const getTextColor = (variant: SocialButtonVariant): string =>
|
|
|
56
57
|
variant === "white" || variant === "outline" ? "#000000" : "#FFFFFF";
|
|
57
58
|
|
|
58
59
|
async function performLogin(provider: AuthProvider): Promise<void> {
|
|
59
|
-
|
|
60
|
-
await auth.login(provider);
|
|
60
|
+
await AuthService.login(provider);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export const SocialButton = ({
|
|
@@ -83,12 +83,16 @@ export const SocialButton = ({
|
|
|
83
83
|
setLoading(true);
|
|
84
84
|
try {
|
|
85
85
|
await performLogin(provider);
|
|
86
|
-
const user =
|
|
86
|
+
const user = AuthService.currentUser;
|
|
87
87
|
if (user) {
|
|
88
88
|
onSuccess?.(user);
|
|
89
89
|
}
|
|
90
90
|
} catch (error) {
|
|
91
|
-
onError
|
|
91
|
+
if (onError) {
|
|
92
|
+
onError(error);
|
|
93
|
+
} else if (__DEV__) {
|
|
94
|
+
logger.error("SocialButton unhandled error:", error);
|
|
95
|
+
}
|
|
92
96
|
} finally {
|
|
93
97
|
setLoading(false);
|
|
94
98
|
}
|
|
@@ -126,19 +130,21 @@ export const SocialButton = ({
|
|
|
126
130
|
<>
|
|
127
131
|
{provider === "google" && variant !== "primary" && (
|
|
128
132
|
<View style={styles.iconPlaceholder}>
|
|
129
|
-
<Text style={
|
|
133
|
+
<Text style={styles.iconText}>G</Text>
|
|
130
134
|
</View>
|
|
131
135
|
)}
|
|
132
136
|
{provider === "apple" && variant !== "primary" && (
|
|
133
137
|
<View style={styles.iconPlaceholder}>
|
|
134
|
-
<Text
|
|
138
|
+
<Text
|
|
139
|
+
style={[styles.iconText, { color: getTextColor(variant) }]}
|
|
140
|
+
>
|
|
135
141
|
|
|
136
142
|
</Text>
|
|
137
143
|
</View>
|
|
138
144
|
)}
|
|
139
145
|
{provider === "microsoft" && variant !== "primary" && (
|
|
140
146
|
<View style={styles.iconPlaceholder}>
|
|
141
|
-
<Text style={
|
|
147
|
+
<Text style={styles.microsoftIconText}>⊞</Text>
|
|
142
148
|
</View>
|
|
143
149
|
)}
|
|
144
150
|
<Text
|
|
@@ -179,4 +185,10 @@ const styles = StyleSheet.create({
|
|
|
179
185
|
fontSize: 16,
|
|
180
186
|
fontWeight: "600",
|
|
181
187
|
},
|
|
188
|
+
iconText: {
|
|
189
|
+
fontSize: 18,
|
|
190
|
+
},
|
|
191
|
+
microsoftIconText: {
|
|
192
|
+
fontSize: 16,
|
|
193
|
+
},
|
|
182
194
|
});
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ActivityIndicator,
|
|
9
9
|
} from "react-native";
|
|
10
10
|
import { AuthModule } from "../Auth.web";
|
|
11
|
+
import { logger } from "../utils/logger";
|
|
11
12
|
import type { AuthProvider, AuthUser } from "../Auth.nitro";
|
|
12
13
|
|
|
13
14
|
export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
|
|
@@ -87,7 +88,11 @@ export const SocialButton = ({
|
|
|
87
88
|
onSuccess?.(user);
|
|
88
89
|
}
|
|
89
90
|
} catch (error) {
|
|
90
|
-
onError
|
|
91
|
+
if (onError) {
|
|
92
|
+
onError(error);
|
|
93
|
+
} else if (process.env.NODE_ENV !== "production") {
|
|
94
|
+
logger.error("SocialButton unhandled error:", error);
|
|
95
|
+
}
|
|
91
96
|
} finally {
|
|
92
97
|
setLoading(false);
|
|
93
98
|
}
|
|
@@ -125,19 +130,21 @@ export const SocialButton = ({
|
|
|
125
130
|
<>
|
|
126
131
|
{provider === "google" && variant !== "primary" && (
|
|
127
132
|
<View style={styles.iconPlaceholder}>
|
|
128
|
-
<Text style={
|
|
133
|
+
<Text style={styles.iconText}>G</Text>
|
|
129
134
|
</View>
|
|
130
135
|
)}
|
|
131
136
|
{provider === "apple" && variant !== "primary" && (
|
|
132
137
|
<View style={styles.iconPlaceholder}>
|
|
133
|
-
<Text
|
|
138
|
+
<Text
|
|
139
|
+
style={[styles.iconText, { color: getTextColor(variant) }]}
|
|
140
|
+
>
|
|
134
141
|
|
|
135
142
|
</Text>
|
|
136
143
|
</View>
|
|
137
144
|
)}
|
|
138
145
|
{provider === "microsoft" && variant !== "primary" && (
|
|
139
146
|
<View style={styles.iconPlaceholder}>
|
|
140
|
-
<Text style={
|
|
147
|
+
<Text style={styles.microsoftIconText}>⊞</Text>
|
|
141
148
|
</View>
|
|
142
149
|
)}
|
|
143
150
|
<Text
|
|
@@ -178,4 +185,10 @@ const styles = StyleSheet.create({
|
|
|
178
185
|
fontSize: 16,
|
|
179
186
|
fontWeight: "600",
|
|
180
187
|
},
|
|
188
|
+
iconText: {
|
|
189
|
+
fontSize: 18,
|
|
190
|
+
},
|
|
191
|
+
microsoftIconText: {
|
|
192
|
+
fontSize: 16,
|
|
193
|
+
},
|
|
181
194
|
});
|