@pelican-identity/react-native 1.2.9 → 1.2.11
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/dist/components/PelicanAuth.d.ts +5 -0
- package/dist/hooks/usePelicanAuth.d.ts +6 -0
- package/dist/hooks/usePelicanAuth.js +116 -0
- package/dist/hooks/usePelicanAuth.js.map +1 -0
- package/dist/index.d.ts +5 -24
- package/dist/index.js +2 -257
- package/dist/index.js.map +1 -1
- package/dist/utilities.d.ts +26 -0
- package/dist/utilities.d.ts.map +1 -0
- package/dist/utilities.js +62 -0
- package/dist/utilities.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useState, useRef, useEffect, useCallback } from "react";
|
|
2
|
+
import { AppState, Linking } from "react-native";
|
|
3
|
+
import { CryptoService } from "@pelican-identity/auth-core";
|
|
4
|
+
import { getRelayUrl, getEncryptedData, validateCallbackUrl, } from "../utilities";
|
|
5
|
+
const cryptoService = new CryptoService();
|
|
6
|
+
export const usePelicanAuth = (props) => {
|
|
7
|
+
const { authType, projectId, publicKey, appId, callBackUrl, onSuccess, onError, onLoading, } = props;
|
|
8
|
+
const [loading, setLoading] = useState(false);
|
|
9
|
+
const sessionKey = useRef(null);
|
|
10
|
+
const sessionID = useRef(null);
|
|
11
|
+
const timeoutRef = useRef(null);
|
|
12
|
+
const isProcessing = useRef(false);
|
|
13
|
+
const clearAuthTimeout = useCallback(() => {
|
|
14
|
+
if (timeoutRef.current) {
|
|
15
|
+
clearTimeout(timeoutRef.current);
|
|
16
|
+
timeoutRef.current = null;
|
|
17
|
+
}
|
|
18
|
+
}, []);
|
|
19
|
+
const handleCallback = useCallback(async () => {
|
|
20
|
+
if (!sessionID.current || !sessionKey.current || isProcessing.current)
|
|
21
|
+
return;
|
|
22
|
+
try {
|
|
23
|
+
isProcessing.current = true;
|
|
24
|
+
const { cipher, nonce } = await getEncryptedData({
|
|
25
|
+
businessKey: publicKey,
|
|
26
|
+
authType,
|
|
27
|
+
projectID: projectId,
|
|
28
|
+
sessionID: sessionID.current,
|
|
29
|
+
appId,
|
|
30
|
+
});
|
|
31
|
+
const decryptedData = cryptoService.decryptSymmetric({
|
|
32
|
+
encrypted: { cipher, nonce },
|
|
33
|
+
keyString: sessionKey.current,
|
|
34
|
+
});
|
|
35
|
+
if (decryptedData) {
|
|
36
|
+
clearAuthTimeout();
|
|
37
|
+
const result = JSON.parse(decryptedData);
|
|
38
|
+
onSuccess(result);
|
|
39
|
+
sessionKey.current = null;
|
|
40
|
+
sessionID.current = null;
|
|
41
|
+
setLoading(false);
|
|
42
|
+
onLoading?.(false);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error("Pelican Callback Error:", error);
|
|
47
|
+
onError?.(error);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
isProcessing.current = false;
|
|
51
|
+
}
|
|
52
|
+
}, [
|
|
53
|
+
authType,
|
|
54
|
+
projectId,
|
|
55
|
+
publicKey,
|
|
56
|
+
appId,
|
|
57
|
+
onSuccess,
|
|
58
|
+
onError,
|
|
59
|
+
onLoading,
|
|
60
|
+
clearAuthTimeout,
|
|
61
|
+
]);
|
|
62
|
+
const initialize = async () => {
|
|
63
|
+
const validation = validateCallbackUrl(callBackUrl || "");
|
|
64
|
+
if (!validation.isValid)
|
|
65
|
+
console.warn(`[Pelican] ${validation.reason}`);
|
|
66
|
+
try {
|
|
67
|
+
clearAuthTimeout();
|
|
68
|
+
setLoading(true);
|
|
69
|
+
onLoading?.(true);
|
|
70
|
+
const { relay_url, session_id } = await getRelayUrl({
|
|
71
|
+
businessKey: publicKey,
|
|
72
|
+
authType,
|
|
73
|
+
projectID: projectId,
|
|
74
|
+
appId,
|
|
75
|
+
});
|
|
76
|
+
sessionKey.current = cryptoService.generateSymmetricKey();
|
|
77
|
+
sessionID.current = session_id;
|
|
78
|
+
timeoutRef.current = setTimeout(() => {
|
|
79
|
+
if (sessionID.current) {
|
|
80
|
+
setLoading(false);
|
|
81
|
+
onLoading?.(false);
|
|
82
|
+
sessionID.current = null;
|
|
83
|
+
onError?.(new Error("Authentication timed out"));
|
|
84
|
+
}
|
|
85
|
+
}, 5 * 60 * 1000);
|
|
86
|
+
const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(sessionKey.current)}&sessionID=${encodeURIComponent(sessionID.current)}&authType=${encodeURIComponent(authType)}&projectId=${encodeURIComponent(projectId)}&publicKey=${encodeURIComponent(publicKey)}&callBackUrl=${encodeURIComponent(callBackUrl || "")}`;
|
|
87
|
+
Linking.openURL(buildUrl);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
setLoading(false);
|
|
91
|
+
onLoading?.(false);
|
|
92
|
+
onError?.(error);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const handleUrl = (event) => {
|
|
97
|
+
if (callBackUrl && event.url.startsWith(callBackUrl))
|
|
98
|
+
handleCallback();
|
|
99
|
+
};
|
|
100
|
+
const linkSub = Linking.addEventListener("url", handleUrl);
|
|
101
|
+
const appStateSub = AppState.addEventListener("change", (state) => {
|
|
102
|
+
if (state === "active") {
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
handleCallback();
|
|
105
|
+
}, 700);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return () => {
|
|
109
|
+
linkSub.remove();
|
|
110
|
+
appStateSub.remove();
|
|
111
|
+
clearAuthTimeout();
|
|
112
|
+
};
|
|
113
|
+
}, [handleCallback, callBackUrl, clearAuthTimeout]);
|
|
114
|
+
return { initialize, loading };
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=usePelicanAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePelicanAuth.js","sourceRoot":"","sources":["../../src/hooks/usePelicanAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,aAAa,EAAkB,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAyB,EAAE,EAAE;IAC1D,MAAM,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,KAAK,EACL,WAAW,EACX,SAAS,EACT,OAAO,EACP,SAAS,GACV,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEnC,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACjC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,cAAc,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAC5C,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO;YACnE,OAAO;QAET,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;YAC5B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,gBAAgB,CAAC;gBAC/C,WAAW,EAAE,SAAS;gBACtB,QAAQ;gBACR,SAAS,EAAE,SAAS;gBACpB,SAAS,EAAE,SAAS,CAAC,OAAO;gBAC5B,KAAK;aACN,CAAC,CAAC;YAEH,MAAM,aAAa,GAAG,aAAa,CAAC,gBAAgB,CAAC;gBACnD,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;gBAC5B,SAAS,EAAE,UAAU,CAAC,OAAO;aAC9B,CAAC,CAAC;YAEH,IAAI,aAAa,EAAE,CAAC;gBAClB,gBAAgB,EAAE,CAAC;gBACnB,MAAM,MAAM,GAAmB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;gBACzD,SAAS,CAAC,MAAM,CAAC,CAAC;gBAClB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;gBAC1B,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;gBACzB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,EAAE,CAAC,KAAc,CAAC,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;QAC/B,CAAC;IACH,CAAC,EAAE;QACD,QAAQ;QACR,SAAS;QACT,SAAS;QACT,KAAK;QACL,SAAS;QACT,OAAO;QACP,SAAS;QACT,gBAAgB;KACjB,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,MAAM,UAAU,GAAG,mBAAmB,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,UAAU,CAAC,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC;YACH,gBAAgB,EAAE,CAAC;YACnB,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;YAElB,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,WAAW,CAAC;gBAClD,WAAW,EAAE,SAAS;gBACtB,QAAQ;gBACR,SAAS,EAAE,SAAS;gBACpB,KAAK;aACN,CAAC,CAAC;YAEH,UAAU,CAAC,OAAO,GAAG,aAAa,CAAC,oBAAoB,EAAE,CAAC;YAC1D,SAAS,CAAC,OAAO,GAAG,UAAU,CAAC;YAG/B,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBACnC,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;oBACtB,UAAU,CAAC,KAAK,CAAC,CAAC;oBAClB,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;oBACnB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;oBACzB,OAAO,EAAE,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAElB,MAAM,QAAQ,GAAG,GAAG,SAAS,eAAe,kBAAkB,CAC5D,UAAU,CAAC,OAAO,CACnB,cAAc,kBAAkB,CAC/B,SAAS,CAAC,OAAO,CAClB,aAAa,kBAAkB,CAC9B,QAAQ,CACT,cAAc,kBAAkB,CAC/B,SAAS,CACV,cAAc,kBAAkB,CAC/B,SAAS,CACV,gBAAgB,kBAAkB,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;YAEzD,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,CAAC,KAAK,CAAC,CAAC;YAClB,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,EAAE,CAAC,KAAc,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,CAAC,KAAsB,EAAE,EAAE;YAC3C,IAAI,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;gBAAE,cAAc,EAAE,CAAC;QACzE,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAChE,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACvB,UAAU,CAAC,GAAG,EAAE;oBACd,cAAc,EAAE,CAAC;gBACnB,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,MAAM,EAAE,CAAC;YACjB,WAAW,CAAC,MAAM,EAAE,CAAC;YACrB,gBAAgB,EAAE,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,cAAc,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEpD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
interface PelicanRNAuthProps extends Omit<PelicanAuthConfig, "continuousMode" | "forceQRCode"> {
|
|
7
|
-
appId: string;
|
|
8
|
-
onSuccess: (result: IdentityResult) => void;
|
|
9
|
-
onError?: (error: Error) => void;
|
|
10
|
-
onLoading?: (loading: boolean) => void;
|
|
11
|
-
buttonComponent?: React.ReactElement;
|
|
12
|
-
callBackUrl: string;
|
|
13
|
-
style?: StyleProp<ViewStyle>;
|
|
14
|
-
buttonTextStyle?: StyleProp<TextStyle>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
declare const PelicanAuth: (props: PelicanRNAuthProps) => react_jsx_runtime.JSX.Element;
|
|
18
|
-
|
|
19
|
-
declare const usePelicanAuth: (props: PelicanRNAuthProps) => {
|
|
20
|
-
initialize: () => Promise<void>;
|
|
21
|
-
loading: boolean;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export { PelicanAuth, type PelicanRNAuthProps, usePelicanAuth };
|
|
1
|
+
export { default as PelicanAuth } from "./components/PelicanAuth";
|
|
2
|
+
export { usePelicanAuth } from "./hooks/usePelicanAuth";
|
|
3
|
+
export type { PelicanRNAuthProps } from "./types/types";
|
|
4
|
+
export type * from "@pelican-identity/auth-core";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,258 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var reactNative = require('react-native');
|
|
4
|
-
require('react-native-get-random-values');
|
|
5
|
-
var react = require('react');
|
|
6
|
-
var authCore = require('@pelican-identity/auth-core');
|
|
7
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
-
|
|
9
|
-
// src/components/PelicanAuth.tsx
|
|
10
|
-
var getRelayUrl = async ({
|
|
11
|
-
businessKey,
|
|
12
|
-
authType,
|
|
13
|
-
projectID,
|
|
14
|
-
appId
|
|
15
|
-
}) => {
|
|
16
|
-
if (!businessKey) {
|
|
17
|
-
throw new Error("Business Key is required");
|
|
18
|
-
}
|
|
19
|
-
if (!authType) {
|
|
20
|
-
throw new Error("Auth Type is required");
|
|
21
|
-
}
|
|
22
|
-
if (!projectID) {
|
|
23
|
-
throw new Error("Project ID is required");
|
|
24
|
-
}
|
|
25
|
-
if (!appId) {
|
|
26
|
-
throw new Error("App ID is required");
|
|
27
|
-
}
|
|
28
|
-
const headers = {
|
|
29
|
-
"Content-Type": "application/json",
|
|
30
|
-
"X-App-ID": appId
|
|
31
|
-
};
|
|
32
|
-
const response = await fetch(
|
|
33
|
-
`${authCore.BASEURL}/relay?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}`,
|
|
34
|
-
{ headers }
|
|
35
|
-
);
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
const error = await response.text();
|
|
38
|
-
throw new Error(error);
|
|
39
|
-
}
|
|
40
|
-
return response.json();
|
|
41
|
-
};
|
|
42
|
-
var getEncryptedData = async ({
|
|
43
|
-
businessKey,
|
|
44
|
-
authType,
|
|
45
|
-
projectID,
|
|
46
|
-
sessionID,
|
|
47
|
-
appId
|
|
48
|
-
}) => {
|
|
49
|
-
if (!appId) {
|
|
50
|
-
throw new Error("App ID is required");
|
|
51
|
-
}
|
|
52
|
-
const headers = {
|
|
53
|
-
"Content-Type": "application/json",
|
|
54
|
-
"X-App-ID": appId
|
|
55
|
-
};
|
|
56
|
-
const response = await fetch(
|
|
57
|
-
`${authCore.BASEURL}/get-rn-sdk-encrypted-data?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}&session_id=${sessionID}`,
|
|
58
|
-
{ headers }
|
|
59
|
-
);
|
|
60
|
-
if (!response.ok) {
|
|
61
|
-
const error = await response.text();
|
|
62
|
-
throw new Error(error);
|
|
63
|
-
}
|
|
64
|
-
return response.json();
|
|
65
|
-
};
|
|
66
|
-
var validateCallbackUrl = (url) => {
|
|
67
|
-
if (!url) return { isValid: false, reason: "Callback URL is missing." };
|
|
68
|
-
const isExpo = url.startsWith("exp://");
|
|
69
|
-
const isStandardScheme = /^[a-z0-9]+:\/\//i.test(url);
|
|
70
|
-
if (!isStandardScheme && !isExpo) {
|
|
71
|
-
return {
|
|
72
|
-
isValid: false,
|
|
73
|
-
reason: "URL must include a scheme (e.g., 'myapp://' or 'exp://')."
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (reactNative.Platform.OS === "ios" && url.includes("_")) {
|
|
77
|
-
return {
|
|
78
|
-
isValid: false,
|
|
79
|
-
reason: "iOS Custom Schemes should not contain underscores as per Apple guidelines."
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
return { isValid: true };
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// src/hooks/usePelicanAuth.ts
|
|
86
|
-
var cryptoService = new authCore.CryptoService();
|
|
87
|
-
var usePelicanAuth = (props) => {
|
|
88
|
-
const {
|
|
89
|
-
authType,
|
|
90
|
-
projectId,
|
|
91
|
-
publicKey,
|
|
92
|
-
appId,
|
|
93
|
-
callBackUrl,
|
|
94
|
-
onSuccess,
|
|
95
|
-
onError,
|
|
96
|
-
onLoading
|
|
97
|
-
} = props;
|
|
98
|
-
const [loading, setLoading] = react.useState(false);
|
|
99
|
-
const sessionKey = react.useRef(null);
|
|
100
|
-
const sessionID = react.useRef(null);
|
|
101
|
-
const timeoutRef = react.useRef(null);
|
|
102
|
-
const isProcessing = react.useRef(false);
|
|
103
|
-
const clearAuthTimeout = react.useCallback(() => {
|
|
104
|
-
if (timeoutRef.current) {
|
|
105
|
-
clearTimeout(timeoutRef.current);
|
|
106
|
-
timeoutRef.current = null;
|
|
107
|
-
}
|
|
108
|
-
}, []);
|
|
109
|
-
const handleCallback = react.useCallback(async () => {
|
|
110
|
-
if (!sessionID.current || !sessionKey.current || isProcessing.current)
|
|
111
|
-
return;
|
|
112
|
-
try {
|
|
113
|
-
isProcessing.current = true;
|
|
114
|
-
const { cipher, nonce } = await getEncryptedData({
|
|
115
|
-
businessKey: publicKey,
|
|
116
|
-
authType,
|
|
117
|
-
projectID: projectId,
|
|
118
|
-
sessionID: sessionID.current,
|
|
119
|
-
appId
|
|
120
|
-
});
|
|
121
|
-
const decryptedData = cryptoService.decryptSymmetric({
|
|
122
|
-
encrypted: { cipher, nonce },
|
|
123
|
-
keyString: sessionKey.current
|
|
124
|
-
});
|
|
125
|
-
if (decryptedData) {
|
|
126
|
-
clearAuthTimeout();
|
|
127
|
-
const result = JSON.parse(decryptedData);
|
|
128
|
-
onSuccess(result);
|
|
129
|
-
sessionKey.current = null;
|
|
130
|
-
sessionID.current = null;
|
|
131
|
-
setLoading(false);
|
|
132
|
-
onLoading?.(false);
|
|
133
|
-
}
|
|
134
|
-
} catch (error) {
|
|
135
|
-
console.error("Pelican Callback Error:", error);
|
|
136
|
-
onError?.(error);
|
|
137
|
-
} finally {
|
|
138
|
-
isProcessing.current = false;
|
|
139
|
-
}
|
|
140
|
-
}, [
|
|
141
|
-
authType,
|
|
142
|
-
projectId,
|
|
143
|
-
publicKey,
|
|
144
|
-
appId,
|
|
145
|
-
onSuccess,
|
|
146
|
-
onError,
|
|
147
|
-
onLoading,
|
|
148
|
-
clearAuthTimeout
|
|
149
|
-
]);
|
|
150
|
-
const initialize = async () => {
|
|
151
|
-
const validation = validateCallbackUrl(callBackUrl || "");
|
|
152
|
-
if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);
|
|
153
|
-
try {
|
|
154
|
-
clearAuthTimeout();
|
|
155
|
-
setLoading(true);
|
|
156
|
-
onLoading?.(true);
|
|
157
|
-
const { relay_url, session_id } = await getRelayUrl({
|
|
158
|
-
businessKey: publicKey,
|
|
159
|
-
authType,
|
|
160
|
-
projectID: projectId,
|
|
161
|
-
appId
|
|
162
|
-
});
|
|
163
|
-
sessionKey.current = cryptoService.generateSymmetricKey();
|
|
164
|
-
sessionID.current = session_id;
|
|
165
|
-
timeoutRef.current = setTimeout(() => {
|
|
166
|
-
if (sessionID.current) {
|
|
167
|
-
setLoading(false);
|
|
168
|
-
onLoading?.(false);
|
|
169
|
-
sessionID.current = null;
|
|
170
|
-
onError?.(new Error("Authentication timed out"));
|
|
171
|
-
}
|
|
172
|
-
}, 5 * 60 * 1e3);
|
|
173
|
-
const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(
|
|
174
|
-
sessionKey.current
|
|
175
|
-
)}&sessionID=${encodeURIComponent(
|
|
176
|
-
sessionID.current
|
|
177
|
-
)}&authType=${encodeURIComponent(
|
|
178
|
-
authType
|
|
179
|
-
)}&projectId=${encodeURIComponent(
|
|
180
|
-
projectId
|
|
181
|
-
)}&publicKey=${encodeURIComponent(
|
|
182
|
-
publicKey
|
|
183
|
-
)}&callBackUrl=${encodeURIComponent(callBackUrl || "")}`;
|
|
184
|
-
reactNative.Linking.openURL(buildUrl);
|
|
185
|
-
} catch (error) {
|
|
186
|
-
setLoading(false);
|
|
187
|
-
onLoading?.(false);
|
|
188
|
-
onError?.(error);
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
react.useEffect(() => {
|
|
192
|
-
const handleUrl = (event) => {
|
|
193
|
-
if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();
|
|
194
|
-
};
|
|
195
|
-
const linkSub = reactNative.Linking.addEventListener("url", handleUrl);
|
|
196
|
-
const appStateSub = reactNative.AppState.addEventListener("change", (state) => {
|
|
197
|
-
if (state === "active") {
|
|
198
|
-
setTimeout(() => {
|
|
199
|
-
handleCallback();
|
|
200
|
-
}, 700);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
return () => {
|
|
204
|
-
linkSub.remove();
|
|
205
|
-
appStateSub.remove();
|
|
206
|
-
clearAuthTimeout();
|
|
207
|
-
};
|
|
208
|
-
}, [handleCallback, callBackUrl, clearAuthTimeout]);
|
|
209
|
-
return { initialize, loading };
|
|
210
|
-
};
|
|
211
|
-
var PelicanAuth = (props) => {
|
|
212
|
-
const { initialize, loading } = usePelicanAuth(props);
|
|
213
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: initialize, disabled: loading, children: props.buttonComponent || /* @__PURE__ */ jsxRuntime.jsxs(
|
|
214
|
-
reactNative.View,
|
|
215
|
-
{
|
|
216
|
-
style: [
|
|
217
|
-
{
|
|
218
|
-
flexDirection: "row",
|
|
219
|
-
alignItems: "center",
|
|
220
|
-
gap: 10,
|
|
221
|
-
paddingHorizontal: 10,
|
|
222
|
-
paddingVertical: 10,
|
|
223
|
-
borderRadius: 20,
|
|
224
|
-
borderWidth: 1
|
|
225
|
-
},
|
|
226
|
-
props.style
|
|
227
|
-
],
|
|
228
|
-
children: [
|
|
229
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
230
|
-
reactNative.Image,
|
|
231
|
-
{
|
|
232
|
-
source: {
|
|
233
|
-
uri: "https://res.cloudinary.com/de0jr8mcm/image/upload/v1765904735/pelican/pelican_icon_r9ghqw.png"
|
|
234
|
-
},
|
|
235
|
-
style: { width: 30, height: 30 }
|
|
236
|
-
}
|
|
237
|
-
),
|
|
238
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
239
|
-
reactNative.Text,
|
|
240
|
-
{
|
|
241
|
-
style: [
|
|
242
|
-
{ fontSize: 16, fontWeight: "600" },
|
|
243
|
-
props.buttonTextStyle
|
|
244
|
-
],
|
|
245
|
-
children: props.authType === "login" ? "Login with Pelican" : props.authType === "signup" ? "Signup with Pelican" : props.authType === "id-verification" ? "Verify with Pelican" : "Authenticate with Pelican"
|
|
246
|
-
}
|
|
247
|
-
),
|
|
248
|
-
loading && /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: "#000" })
|
|
249
|
-
]
|
|
250
|
-
}
|
|
251
|
-
) }) });
|
|
252
|
-
};
|
|
253
|
-
var PelicanAuth_default = PelicanAuth;
|
|
254
|
-
|
|
255
|
-
exports.PelicanAuth = PelicanAuth_default;
|
|
256
|
-
exports.usePelicanAuth = usePelicanAuth;
|
|
257
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { default as PelicanAuth } from "./components/PelicanAuth";
|
|
2
|
+
export { usePelicanAuth } from "./hooks/usePelicanAuth";
|
|
258
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utilities.ts","../src/hooks/usePelicanAuth.ts","../src/components/PelicanAuth.tsx"],"names":["BASEURL","Platform","CryptoService","useState","useRef","useCallback","Linking","useEffect","AppState","jsx","View","TouchableOpacity","jsxs","Image","Text","ActivityIndicator"],"mappings":"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","file":"index.js","sourcesContent":["import \"react-native-get-random-values\";\n\nimport { BASEURL, type AuthType } from \"@pelican-identity/auth-core\";\nimport { Platform } from \"react-native\";\n\nexport const getRelayUrl = async ({\n businessKey,\n authType,\n projectID,\n appId,\n}: {\n businessKey: string;\n authType: AuthType;\n projectID: string;\n appId: string;\n}) => {\n if (!businessKey) {\n throw new Error(\"Business Key is required\");\n }\n if (!authType) {\n throw new Error(\"Auth Type is required\");\n }\n if (!projectID) {\n throw new Error(\"Project ID is required\");\n }\n if (!appId) {\n throw new Error(\"App ID is required\");\n }\n const headers = {\n \"Content-Type\": \"application/json\",\n \"X-App-ID\": appId,\n };\n\n const response = await fetch(\n `${BASEURL}/relay?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}`,\n { headers }\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(error);\n }\n\n return response.json() as Promise<{ relay_url: string; session_id: string }>;\n};\n\nexport const getEncryptedData = async ({\n businessKey,\n authType,\n projectID,\n sessionID,\n appId,\n}: {\n businessKey: string;\n authType: AuthType;\n projectID: string;\n sessionID: string;\n appId: string;\n}) => {\n if (!appId) {\n throw new Error(\"App ID is required\");\n }\n const headers = {\n \"Content-Type\": \"application/json\",\n \"X-App-ID\": appId,\n };\n\n const response = await fetch(\n `${BASEURL}/get-rn-sdk-encrypted-data?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}&session_id=${sessionID}`,\n { headers }\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(error);\n }\n\n return response.json() as Promise<{ cipher: string; nonce: string }>;\n};\n\n/**\n * Validates if the provided callback URL is compatible with the\n * current environment (Expo vs Bare vs Production).\n */\nexport const validateCallbackUrl = (\n url: string\n): { isValid: boolean; reason?: string } => {\n if (!url) return { isValid: false, reason: \"Callback URL is missing.\" };\n\n // Check for common Expo development URLs\n const isExpo = url.startsWith(\"exp://\");\n const isStandardScheme = /^[a-z0-9]+:\\/\\//i.test(url);\n\n if (!isStandardScheme && !isExpo) {\n return {\n isValid: false,\n reason: \"URL must include a scheme (e.g., 'myapp://' or 'exp://').\",\n };\n }\n\n if (Platform.OS === \"ios\" && url.includes(\"_\")) {\n return {\n isValid: false,\n reason:\n \"iOS Custom Schemes should not contain underscores as per Apple guidelines.\",\n };\n }\n\n return { isValid: true };\n};\n","import { useState, useRef, useEffect, useCallback } from \"react\";\nimport { AppState, Linking } from \"react-native\";\nimport { CryptoService, IdentityResult } from \"@pelican-identity/auth-core\";\nimport {\n getRelayUrl,\n getEncryptedData,\n validateCallbackUrl,\n} from \"../utilities\";\nimport { PelicanRNAuthProps } from \"../types/types\";\n\nconst cryptoService = new CryptoService();\n\nexport const usePelicanAuth = (props: PelicanRNAuthProps) => {\n const {\n authType,\n projectId,\n publicKey,\n appId,\n callBackUrl,\n onSuccess,\n onError,\n onLoading,\n } = props;\n\n const [loading, setLoading] = useState(false);\n const sessionKey = useRef<string | null>(null);\n const sessionID = useRef<string | null>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isProcessing = useRef(false);\n\n const clearAuthTimeout = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n }, []);\n\n const handleCallback = useCallback(async () => {\n if (!sessionID.current || !sessionKey.current || isProcessing.current)\n return;\n\n try {\n isProcessing.current = true;\n const { cipher, nonce } = await getEncryptedData({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n sessionID: sessionID.current,\n appId,\n });\n\n const decryptedData = cryptoService.decryptSymmetric({\n encrypted: { cipher, nonce },\n keyString: sessionKey.current,\n });\n\n if (decryptedData) {\n clearAuthTimeout();\n const result: IdentityResult = JSON.parse(decryptedData);\n onSuccess(result);\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n }\n } catch (error) {\n console.error(\"Pelican Callback Error:\", error);\n onError?.(error as Error);\n } finally {\n isProcessing.current = false;\n }\n }, [\n authType,\n projectId,\n publicKey,\n appId,\n onSuccess,\n onError,\n onLoading,\n clearAuthTimeout,\n ]);\n\n const initialize = async () => {\n const validation = validateCallbackUrl(callBackUrl || \"\");\n if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);\n\n try {\n clearAuthTimeout();\n setLoading(true);\n onLoading?.(true);\n\n const { relay_url, session_id } = await getRelayUrl({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n appId,\n });\n\n sessionKey.current = cryptoService.generateSymmetricKey();\n sessionID.current = session_id;\n\n // Start 5-minute timeout\n timeoutRef.current = setTimeout(() => {\n if (sessionID.current) {\n setLoading(false);\n onLoading?.(false);\n sessionID.current = null;\n onError?.(new Error(\"Authentication timed out\"));\n }\n }, 5 * 60 * 1000);\n\n const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(\n sessionKey.current\n )}&sessionID=${encodeURIComponent(\n sessionID.current\n )}&authType=${encodeURIComponent(\n authType\n )}&projectId=${encodeURIComponent(\n projectId\n )}&publicKey=${encodeURIComponent(\n publicKey\n )}&callBackUrl=${encodeURIComponent(callBackUrl || \"\")}`;\n\n Linking.openURL(buildUrl);\n } catch (error) {\n setLoading(false);\n onLoading?.(false);\n onError?.(error as Error);\n }\n };\n\n useEffect(() => {\n const handleUrl = (event: { url: string }) => {\n if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();\n };\n\n const linkSub = Linking.addEventListener(\"url\", handleUrl);\n const appStateSub = AppState.addEventListener(\"change\", (state) => {\n if (state === \"active\") {\n setTimeout(() => {\n handleCallback();\n }, 700);\n }\n });\n\n return () => {\n linkSub.remove();\n appStateSub.remove();\n clearAuthTimeout();\n };\n }, [handleCallback, callBackUrl, clearAuthTimeout]);\n\n return { initialize, loading };\n};\n","import {\n ActivityIndicator,\n Image,\n Text,\n TouchableOpacity,\n View,\n} from \"react-native\";\nimport \"react-native-get-random-values\";\n\nimport { usePelicanAuth } from \"../hooks/usePelicanAuth\";\nimport { PelicanRNAuthProps } from \"../types/types\";\nconst PelicanAuth = (props: PelicanRNAuthProps) => {\n const { initialize, loading } = usePelicanAuth(props);\n return (\n <View>\n <TouchableOpacity onPress={initialize} disabled={loading}>\n {props.buttonComponent || (\n <View\n style={[\n {\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n paddingHorizontal: 10,\n paddingVertical: 10,\n borderRadius: 20,\n borderWidth: 1,\n },\n props.style,\n ]}\n >\n <Image\n source={{\n uri: \"https://res.cloudinary.com/de0jr8mcm/image/upload/v1765904735/pelican/pelican_icon_r9ghqw.png\",\n }}\n style={{ width: 30, height: 30 }}\n />\n <Text\n style={[\n { fontSize: 16, fontWeight: \"600\" },\n props.buttonTextStyle,\n ]}\n >\n {props.authType === \"login\"\n ? \"Login with Pelican\"\n : props.authType === \"signup\"\n ? \"Signup with Pelican\"\n : props.authType === \"id-verification\"\n ? \"Verify with Pelican\"\n : \"Authenticate with Pelican\"}\n </Text>\n {loading && <ActivityIndicator color={\"#000\"} />}\n </View>\n )}\n </TouchableOpacity>\n </View>\n );\n};\n\nexport default PelicanAuth;\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import "react-native-get-random-values";
|
|
2
|
+
import { type AuthType } from "@pelican-identity/auth-core";
|
|
3
|
+
export declare const getRelayUrl: ({ businessKey, authType, projectID, appId, }: {
|
|
4
|
+
businessKey: string;
|
|
5
|
+
authType: AuthType;
|
|
6
|
+
projectID: string;
|
|
7
|
+
appId: string;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
relay_url: string;
|
|
10
|
+
session_id: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const getEncryptedData: ({ businessKey, authType, projectID, sessionID, appId, }: {
|
|
13
|
+
businessKey: string;
|
|
14
|
+
authType: AuthType;
|
|
15
|
+
projectID: string;
|
|
16
|
+
sessionID: string;
|
|
17
|
+
appId: string;
|
|
18
|
+
}) => Promise<{
|
|
19
|
+
cipher: string;
|
|
20
|
+
nonce: string;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const validateCallbackUrl: (url: string) => {
|
|
23
|
+
isValid: boolean;
|
|
24
|
+
reason?: string;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=utilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA,OAAO,gCAAgC,CAAC;AAExC,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGrE,eAAO,MAAM,WAAW,GAAU,8CAK/B;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;eA4BgD,MAAM;gBAAc,MAAM;EAC1E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,yDAMpC;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;YAmB6C,MAAM;WAAS,MAAM;EAClE,CAAC;AAMF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,KACV;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAuBrC,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import "react-native-get-random-values";
|
|
2
|
+
import { BASEURL } from "@pelican-identity/auth-core";
|
|
3
|
+
import { Platform } from "react-native";
|
|
4
|
+
export const getRelayUrl = async ({ businessKey, authType, projectID, appId, }) => {
|
|
5
|
+
if (!businessKey) {
|
|
6
|
+
throw new Error("Business Key is required");
|
|
7
|
+
}
|
|
8
|
+
if (!authType) {
|
|
9
|
+
throw new Error("Auth Type is required");
|
|
10
|
+
}
|
|
11
|
+
if (!projectID) {
|
|
12
|
+
throw new Error("Project ID is required");
|
|
13
|
+
}
|
|
14
|
+
if (!appId) {
|
|
15
|
+
throw new Error("App ID is required");
|
|
16
|
+
}
|
|
17
|
+
const headers = {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
"X-App-ID": appId,
|
|
20
|
+
};
|
|
21
|
+
const response = await fetch(`${BASEURL}/relay?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}`, { headers });
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const error = await response.text();
|
|
24
|
+
throw new Error(error);
|
|
25
|
+
}
|
|
26
|
+
return response.json();
|
|
27
|
+
};
|
|
28
|
+
export const getEncryptedData = async ({ businessKey, authType, projectID, sessionID, appId, }) => {
|
|
29
|
+
if (!appId) {
|
|
30
|
+
throw new Error("App ID is required");
|
|
31
|
+
}
|
|
32
|
+
const headers = {
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
"X-App-ID": appId,
|
|
35
|
+
};
|
|
36
|
+
const response = await fetch(`${BASEURL}/get-rn-sdk-encrypted-data?public_key=${businessKey}&auth_type=${authType}&project_id=${projectID}&session_id=${sessionID}`, { headers });
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const error = await response.text();
|
|
39
|
+
throw new Error(error);
|
|
40
|
+
}
|
|
41
|
+
return response.json();
|
|
42
|
+
};
|
|
43
|
+
export const validateCallbackUrl = (url) => {
|
|
44
|
+
if (!url)
|
|
45
|
+
return { isValid: false, reason: "Callback URL is missing." };
|
|
46
|
+
const isExpo = url.startsWith("exp://");
|
|
47
|
+
const isStandardScheme = /^[a-z0-9]+:\/\//i.test(url);
|
|
48
|
+
if (!isStandardScheme && !isExpo) {
|
|
49
|
+
return {
|
|
50
|
+
isValid: false,
|
|
51
|
+
reason: "URL must include a scheme (e.g., 'myapp://' or 'exp://').",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (Platform.OS === "ios" && url.includes("_")) {
|
|
55
|
+
return {
|
|
56
|
+
isValid: false,
|
|
57
|
+
reason: "iOS Custom Schemes should not contain underscores as per Apple guidelines.",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return { isValid: true };
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pelican-identity/react-native",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.11",
|
|
4
4
|
"description": "React Native components for Pelican Identity authentication",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"react-native": "./src/index.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"react-native-get-random-values": "^1.7.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@pelican-identity/auth-core": "1.2.
|
|
25
|
+
"@pelican-identity/auth-core": "1.2.9"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.2.45",
|