@pelican-identity/react-native 1.2.6 → 1.2.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 CHANGED
@@ -210,7 +210,7 @@ Main authentication component.
210
210
  | `appId` | `string` | ✅ | App bundle identifier |
211
211
  | `authType` | `"signup" \| "login" \| "id-verification"` | ✅ | Authentication flow |
212
212
  | `onSuccess` | `(data: IdentityResult) => void` | ✅ | Success callback containing authenticated user data |
213
- | `callBackUrl` | `string` | Optional | Deeplink to return to app |
213
+ | `callBackUrl` | `string` | | Deeplink to return to app |
214
214
  | `onError` | `(error) => void` | Optional | Error callback |
215
215
  | `onLoading` | `(loading: boolean) => void` | Optional | Loading callback, useful for loading stares |
216
216
  | `buttonComponent` | `ReactNode` | Optional | Custom trigger UI |
package/dist/index.d.mts CHANGED
@@ -1,16 +1,23 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { PelicanAuthConfig, IdentityResult } from '@pelican-identity/auth-core';
3
3
  export * from '@pelican-identity/auth-core';
4
+ import { StyleProp, ViewStyle } from 'react-native';
4
5
 
5
- interface PelicanRNAuthProps extends PelicanAuthConfig {
6
+ interface PelicanRNAuthProps extends Omit<PelicanAuthConfig, "continuousMode" | "forceQRCode"> {
6
7
  appId: string;
7
8
  onSuccess: (result: IdentityResult) => void;
8
9
  onError?: (error: Error) => void;
9
10
  onLoading?: (loading: boolean) => void;
10
- buttonComponent?: React.ReactNode;
11
- callBackUrl?: string;
11
+ buttonComponent?: React.ReactElement;
12
+ callBackUrl: string;
13
+ style?: StyleProp<ViewStyle>;
12
14
  }
13
15
 
14
- declare const PelicanAuth: ({ authType, projectId, publicKey, onSuccess, callBackUrl, onError, buttonComponent, onLoading, appId, }: PelicanRNAuthProps) => react_jsx_runtime.JSX.Element;
16
+ declare const PelicanAuth: (props: PelicanRNAuthProps) => react_jsx_runtime.JSX.Element;
15
17
 
16
- export { PelicanAuth };
18
+ declare const usePelicanAuth: (props: PelicanRNAuthProps) => {
19
+ initialize: () => Promise<void>;
20
+ loading: boolean;
21
+ };
22
+
23
+ export { PelicanAuth, type PelicanRNAuthProps, usePelicanAuth };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,23 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { PelicanAuthConfig, IdentityResult } from '@pelican-identity/auth-core';
3
3
  export * from '@pelican-identity/auth-core';
4
+ import { StyleProp, ViewStyle } from 'react-native';
4
5
 
5
- interface PelicanRNAuthProps extends PelicanAuthConfig {
6
+ interface PelicanRNAuthProps extends Omit<PelicanAuthConfig, "continuousMode" | "forceQRCode"> {
6
7
  appId: string;
7
8
  onSuccess: (result: IdentityResult) => void;
8
9
  onError?: (error: Error) => void;
9
10
  onLoading?: (loading: boolean) => void;
10
- buttonComponent?: React.ReactNode;
11
- callBackUrl?: string;
11
+ buttonComponent?: React.ReactElement;
12
+ callBackUrl: string;
13
+ style?: StyleProp<ViewStyle>;
12
14
  }
13
15
 
14
- declare const PelicanAuth: ({ authType, projectId, publicKey, onSuccess, callBackUrl, onError, buttonComponent, onLoading, appId, }: PelicanRNAuthProps) => react_jsx_runtime.JSX.Element;
16
+ declare const PelicanAuth: (props: PelicanRNAuthProps) => react_jsx_runtime.JSX.Element;
15
17
 
16
- export { PelicanAuth };
18
+ declare const usePelicanAuth: (props: PelicanRNAuthProps) => {
19
+ initialize: () => Promise<void>;
20
+ loading: boolean;
21
+ };
22
+
23
+ export { PelicanAuth, type PelicanRNAuthProps, usePelicanAuth };
package/dist/index.js CHANGED
@@ -1,15 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var React = require('react');
4
3
  var reactNative = require('react-native');
5
4
  require('react-native-get-random-values');
5
+ var react = require('react');
6
6
  var authCore = require('@pelican-identity/auth-core');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
 
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var React__default = /*#__PURE__*/_interopDefault(React);
12
-
13
9
  // src/components/PelicanAuth.tsx
14
10
  var getRelayUrl = async ({
15
11
  businessKey,
@@ -39,7 +35,7 @@ var getRelayUrl = async ({
39
35
  );
40
36
  if (!response.ok) {
41
37
  const error = await response.text();
42
- throw new Error(`Failed to initiate authentication: ${error}`);
38
+ throw new Error(error);
43
39
  }
44
40
  return response.json();
45
41
  };
@@ -63,27 +59,94 @@ var getEncryptedData = async ({
63
59
  );
64
60
  if (!response.ok) {
65
61
  const error = await response.text();
66
- throw new Error(`Failed to retrieve authentication session data: ${error}`);
62
+ throw new Error(error);
67
63
  }
68
64
  return response.json();
69
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
70
86
  var cryptoService = new authCore.CryptoService();
71
- var PelicanAuth = ({
72
- authType,
73
- projectId,
74
- publicKey,
75
- onSuccess,
76
- callBackUrl,
77
- onError,
78
- buttonComponent,
79
- onLoading,
80
- appId
81
- }) => {
82
- const sessionKey = React__default.default.useRef(null);
83
- const sessionID = React__default.default.useRef(null);
84
- const [loading, setLoading] = React.useState(false);
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 clearAuthTimeout = react.useCallback(() => {
103
+ if (timeoutRef.current) {
104
+ clearTimeout(timeoutRef.current);
105
+ timeoutRef.current = null;
106
+ }
107
+ }, []);
108
+ const handleCallback = react.useCallback(async () => {
109
+ if (!sessionID.current || !sessionKey.current) return;
110
+ try {
111
+ const { cipher, nonce } = await getEncryptedData({
112
+ businessKey: publicKey,
113
+ authType,
114
+ projectID: projectId,
115
+ sessionID: sessionID.current,
116
+ appId
117
+ });
118
+ const decryptedData = cryptoService.decryptSymmetric({
119
+ encrypted: { cipher, nonce },
120
+ keyString: sessionKey.current
121
+ });
122
+ if (decryptedData) {
123
+ clearAuthTimeout();
124
+ const result = JSON.parse(decryptedData);
125
+ onSuccess(result);
126
+ sessionKey.current = null;
127
+ sessionID.current = null;
128
+ setLoading(false);
129
+ onLoading?.(false);
130
+ }
131
+ } catch (error) {
132
+ console.error("Pelican Callback Error:", error);
133
+ onError?.(error);
134
+ }
135
+ }, [
136
+ authType,
137
+ projectId,
138
+ publicKey,
139
+ appId,
140
+ onSuccess,
141
+ onError,
142
+ onLoading,
143
+ clearAuthTimeout
144
+ ]);
85
145
  const initialize = async () => {
146
+ const validation = validateCallbackUrl(callBackUrl || "");
147
+ if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);
86
148
  try {
149
+ clearAuthTimeout();
87
150
  setLoading(true);
88
151
  onLoading?.(true);
89
152
  const { relay_url, session_id } = await getRelayUrl({
@@ -92,18 +155,20 @@ var PelicanAuth = ({
92
155
  projectID: projectId,
93
156
  appId
94
157
  });
95
- if (!relay_url || !session_id) {
96
- setLoading(false);
97
- onLoading?.(false);
98
- onError?.(new Error("Failed to get relay URL"));
99
- return;
100
- }
101
158
  sessionKey.current = cryptoService.generateSymmetricKey();
102
159
  sessionID.current = session_id;
160
+ timeoutRef.current = setTimeout(() => {
161
+ if (sessionID.current) {
162
+ setLoading(false);
163
+ onLoading?.(false);
164
+ sessionID.current = null;
165
+ onError?.(new Error("Authentication timed out"));
166
+ }
167
+ }, 5 * 60 * 1e3);
103
168
  const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(
104
- sessionKey.current || ""
169
+ sessionKey.current
105
170
  )}&sessionID=${encodeURIComponent(
106
- sessionID.current || ""
171
+ sessionID.current
107
172
  )}&authType=${encodeURIComponent(
108
173
  authType
109
174
  )}&projectId=${encodeURIComponent(
@@ -113,77 +178,44 @@ var PelicanAuth = ({
113
178
  )}&callBackUrl=${encodeURIComponent(callBackUrl || "")}`;
114
179
  reactNative.Linking.openURL(buildUrl);
115
180
  } catch (error) {
116
- sessionKey.current = null;
117
- sessionID.current = null;
118
181
  setLoading(false);
119
182
  onLoading?.(false);
120
183
  onError?.(error);
121
184
  }
122
185
  };
123
- const handleCallback = async () => {
124
- try {
125
- if (!sessionID.current) {
126
- return;
127
- }
128
- if (!sessionKey.current) {
129
- return;
130
- }
131
- const { cipher, nonce } = await getEncryptedData({
132
- businessKey: publicKey,
133
- authType,
134
- projectID: projectId,
135
- sessionID: sessionID.current,
136
- appId
137
- });
138
- const decryptedData = cryptoService.decryptSymmetric({
139
- encrypted: { cipher, nonce },
140
- keyString: sessionKey.current
141
- });
142
- if (decryptedData) {
143
- const result = JSON.parse(decryptedData);
144
- onSuccess(result);
145
- sessionKey.current = null;
146
- sessionID.current = null;
147
- setLoading(false);
148
- onLoading?.(false);
149
- } else {
150
- onError?.(new Error("Failed to get identity result"));
151
- sessionKey.current = null;
152
- sessionID.current = null;
153
- setLoading(false);
154
- onLoading?.(false);
155
- }
156
- } catch (error) {
157
- console.log(error);
158
- onError?.(error);
159
- sessionKey.current = null;
160
- sessionID.current = null;
161
- setLoading(false);
162
- onLoading?.(false);
163
- }
164
- };
165
- React__default.default.useEffect(() => {
166
- const subscription = reactNative.AppState.addEventListener("change", (nextAppState) => {
167
- if (nextAppState === "active") {
168
- handleCallback();
169
- }
186
+ react.useEffect(() => {
187
+ const handleUrl = (event) => {
188
+ if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();
189
+ };
190
+ const linkSub = reactNative.Linking.addEventListener("url", handleUrl);
191
+ const appStateSub = reactNative.AppState.addEventListener("change", (state) => {
192
+ if (state === "active") handleCallback();
170
193
  });
171
194
  return () => {
172
- subscription.remove();
195
+ linkSub.remove();
196
+ appStateSub.remove();
197
+ clearAuthTimeout();
173
198
  };
174
- }, []);
175
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: initialize, disabled: loading, children: buttonComponent || /* @__PURE__ */ jsxRuntime.jsxs(
199
+ }, [handleCallback, callBackUrl, clearAuthTimeout]);
200
+ return { initialize, loading };
201
+ };
202
+ var PelicanAuth = (props) => {
203
+ const { initialize, loading } = usePelicanAuth(props);
204
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: initialize, disabled: loading, children: props.buttonComponent || /* @__PURE__ */ jsxRuntime.jsxs(
176
205
  reactNative.View,
177
206
  {
178
- style: {
179
- flexDirection: "row",
180
- alignItems: "center",
181
- gap: 10,
182
- paddingHorizontal: 10,
183
- paddingVertical: 10,
184
- borderRadius: 20,
185
- borderWidth: 1
186
- },
207
+ style: [
208
+ {
209
+ flexDirection: "row",
210
+ alignItems: "center",
211
+ gap: 10,
212
+ paddingHorizontal: 10,
213
+ paddingVertical: 10,
214
+ borderRadius: 20,
215
+ borderWidth: 1
216
+ },
217
+ props.style
218
+ ],
187
219
  children: [
188
220
  /* @__PURE__ */ jsxRuntime.jsx(
189
221
  reactNative.Image,
@@ -194,7 +226,7 @@ var PelicanAuth = ({
194
226
  style: { width: 30, height: 30 }
195
227
  }
196
228
  ),
197
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 16, fontWeight: "600" }, children: authType === "login" ? "Login with Pelican" : authType === "signup" ? "Signup with Pelican" : authType === "id-verification" ? "Verify identity with Pelican" : "Authenticate with Pelican" }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { fontSize: 16, fontWeight: "600" }, children: props.authType === "login" ? "Login with Pelican" : props.authType === "signup" ? "Signup with Pelican" : props.authType === "id-verification" ? "Verify with Pelican" : "Authenticate with Pelican" }),
198
230
  loading && /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: "#000" })
199
231
  ]
200
232
  }
@@ -203,5 +235,6 @@ var PelicanAuth = ({
203
235
  var PelicanAuth_default = PelicanAuth;
204
236
 
205
237
  exports.PelicanAuth = PelicanAuth_default;
238
+ exports.usePelicanAuth = usePelicanAuth;
206
239
  //# sourceMappingURL=index.js.map
207
240
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utilities.ts","../src/components/PelicanAuth.tsx"],"names":["BASEURL","CryptoService","React","useState","Linking","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\";\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(`Failed to initiate authentication: ${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(`Failed to retrieve authentication session data: ${error}`);\n }\n\n return response.json() as Promise<{ cipher: string; nonce: string }>;\n};\n","import React, { useState } from \"react\";\nimport {\n ActivityIndicator,\n AppState,\n Image,\n Linking,\n Text,\n TouchableOpacity,\n View,\n} from \"react-native\";\nimport \"react-native-get-random-values\";\n\nimport { getEncryptedData, getRelayUrl } from \"../utilities\";\nimport { PelicanRNAuthProps } from \"../types\";\nimport { IdentityResult, CryptoService } from \"@pelican-identity/auth-core\";\n\nconst cryptoService = new CryptoService();\nconst PelicanAuth = ({\n authType,\n projectId,\n publicKey,\n onSuccess,\n callBackUrl,\n onError,\n buttonComponent,\n onLoading,\n appId,\n}: PelicanRNAuthProps) => {\n const sessionKey = React.useRef<string | null>(null);\n const sessionID = React.useRef<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n const initialize = async () => {\n try {\n setLoading(true);\n onLoading?.(true);\n const { relay_url, session_id } = await getRelayUrl({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n appId,\n });\n\n if (!relay_url || !session_id) {\n setLoading(false);\n onLoading?.(false);\n onError?.(new Error(\"Failed to get relay URL\"));\n return;\n }\n\n sessionKey.current = cryptoService.generateSymmetricKey();\n sessionID.current = session_id;\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 Linking.openURL(buildUrl);\n } catch (error) {\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n onError?.(error as Error);\n }\n };\n\n const handleCallback = async () => {\n try {\n if (!sessionID.current) {\n return;\n }\n if (!sessionKey.current) {\n return;\n }\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 const result: IdentityResult = JSON.parse(decryptedData);\n\n onSuccess(result);\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n } else {\n onError?.(new Error(\"Failed to get identity result\"));\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n }\n } catch (error) {\n console.log(error);\n onError?.(error as Error);\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n React.useEffect(() => {\n const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n if (nextAppState === \"active\") {\n handleCallback();\n }\n });\n return () => {\n subscription.remove();\n };\n }, []);\n\n return (\n <View>\n <TouchableOpacity onPress={initialize} disabled={loading}>\n {buttonComponent || (\n <View\n style={{\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n paddingHorizontal: 10,\n paddingVertical: 10,\n borderRadius: 20,\n borderWidth: 1,\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 style={{ fontSize: 16, fontWeight: \"600\" }}>\n {authType === \"login\"\n ? \"Login with Pelican\"\n : authType === \"signup\"\n ? \"Signup with Pelican\"\n : authType === \"id-verification\"\n ? \"Verify identity 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,"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\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) return;\n\n try {\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 }\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\") handleCallback();\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 style={{ fontSize: 16, fontWeight: \"600\" }}>\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"]}
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import React, { useState } from 'react';
2
- import { AppState, View, TouchableOpacity, Image, Text, ActivityIndicator, Linking } from 'react-native';
1
+ import { Linking, AppState, View, TouchableOpacity, Image, Text, ActivityIndicator, Platform } from 'react-native';
3
2
  import 'react-native-get-random-values';
3
+ import { useState, useRef, useCallback, useEffect } from 'react';
4
4
  import { CryptoService, BASEURL } from '@pelican-identity/auth-core';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
 
@@ -33,7 +33,7 @@ var getRelayUrl = async ({
33
33
  );
34
34
  if (!response.ok) {
35
35
  const error = await response.text();
36
- throw new Error(`Failed to initiate authentication: ${error}`);
36
+ throw new Error(error);
37
37
  }
38
38
  return response.json();
39
39
  };
@@ -57,27 +57,94 @@ var getEncryptedData = async ({
57
57
  );
58
58
  if (!response.ok) {
59
59
  const error = await response.text();
60
- throw new Error(`Failed to retrieve authentication session data: ${error}`);
60
+ throw new Error(error);
61
61
  }
62
62
  return response.json();
63
63
  };
64
+ var validateCallbackUrl = (url) => {
65
+ if (!url) return { isValid: false, reason: "Callback URL is missing." };
66
+ const isExpo = url.startsWith("exp://");
67
+ const isStandardScheme = /^[a-z0-9]+:\/\//i.test(url);
68
+ if (!isStandardScheme && !isExpo) {
69
+ return {
70
+ isValid: false,
71
+ reason: "URL must include a scheme (e.g., 'myapp://' or 'exp://')."
72
+ };
73
+ }
74
+ if (Platform.OS === "ios" && url.includes("_")) {
75
+ return {
76
+ isValid: false,
77
+ reason: "iOS Custom Schemes should not contain underscores as per Apple guidelines."
78
+ };
79
+ }
80
+ return { isValid: true };
81
+ };
82
+
83
+ // src/hooks/usePelicanAuth.ts
64
84
  var cryptoService = new CryptoService();
65
- var PelicanAuth = ({
66
- authType,
67
- projectId,
68
- publicKey,
69
- onSuccess,
70
- callBackUrl,
71
- onError,
72
- buttonComponent,
73
- onLoading,
74
- appId
75
- }) => {
76
- const sessionKey = React.useRef(null);
77
- const sessionID = React.useRef(null);
85
+ var usePelicanAuth = (props) => {
86
+ const {
87
+ authType,
88
+ projectId,
89
+ publicKey,
90
+ appId,
91
+ callBackUrl,
92
+ onSuccess,
93
+ onError,
94
+ onLoading
95
+ } = props;
78
96
  const [loading, setLoading] = useState(false);
97
+ const sessionKey = useRef(null);
98
+ const sessionID = useRef(null);
99
+ const timeoutRef = useRef(null);
100
+ const clearAuthTimeout = useCallback(() => {
101
+ if (timeoutRef.current) {
102
+ clearTimeout(timeoutRef.current);
103
+ timeoutRef.current = null;
104
+ }
105
+ }, []);
106
+ const handleCallback = useCallback(async () => {
107
+ if (!sessionID.current || !sessionKey.current) return;
108
+ try {
109
+ const { cipher, nonce } = await getEncryptedData({
110
+ businessKey: publicKey,
111
+ authType,
112
+ projectID: projectId,
113
+ sessionID: sessionID.current,
114
+ appId
115
+ });
116
+ const decryptedData = cryptoService.decryptSymmetric({
117
+ encrypted: { cipher, nonce },
118
+ keyString: sessionKey.current
119
+ });
120
+ if (decryptedData) {
121
+ clearAuthTimeout();
122
+ const result = JSON.parse(decryptedData);
123
+ onSuccess(result);
124
+ sessionKey.current = null;
125
+ sessionID.current = null;
126
+ setLoading(false);
127
+ onLoading?.(false);
128
+ }
129
+ } catch (error) {
130
+ console.error("Pelican Callback Error:", error);
131
+ onError?.(error);
132
+ }
133
+ }, [
134
+ authType,
135
+ projectId,
136
+ publicKey,
137
+ appId,
138
+ onSuccess,
139
+ onError,
140
+ onLoading,
141
+ clearAuthTimeout
142
+ ]);
79
143
  const initialize = async () => {
144
+ const validation = validateCallbackUrl(callBackUrl || "");
145
+ if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);
80
146
  try {
147
+ clearAuthTimeout();
81
148
  setLoading(true);
82
149
  onLoading?.(true);
83
150
  const { relay_url, session_id } = await getRelayUrl({
@@ -86,18 +153,20 @@ var PelicanAuth = ({
86
153
  projectID: projectId,
87
154
  appId
88
155
  });
89
- if (!relay_url || !session_id) {
90
- setLoading(false);
91
- onLoading?.(false);
92
- onError?.(new Error("Failed to get relay URL"));
93
- return;
94
- }
95
156
  sessionKey.current = cryptoService.generateSymmetricKey();
96
157
  sessionID.current = session_id;
158
+ timeoutRef.current = setTimeout(() => {
159
+ if (sessionID.current) {
160
+ setLoading(false);
161
+ onLoading?.(false);
162
+ sessionID.current = null;
163
+ onError?.(new Error("Authentication timed out"));
164
+ }
165
+ }, 5 * 60 * 1e3);
97
166
  const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(
98
- sessionKey.current || ""
167
+ sessionKey.current
99
168
  )}&sessionID=${encodeURIComponent(
100
- sessionID.current || ""
169
+ sessionID.current
101
170
  )}&authType=${encodeURIComponent(
102
171
  authType
103
172
  )}&projectId=${encodeURIComponent(
@@ -107,77 +176,44 @@ var PelicanAuth = ({
107
176
  )}&callBackUrl=${encodeURIComponent(callBackUrl || "")}`;
108
177
  Linking.openURL(buildUrl);
109
178
  } catch (error) {
110
- sessionKey.current = null;
111
- sessionID.current = null;
112
179
  setLoading(false);
113
180
  onLoading?.(false);
114
181
  onError?.(error);
115
182
  }
116
183
  };
117
- const handleCallback = async () => {
118
- try {
119
- if (!sessionID.current) {
120
- return;
121
- }
122
- if (!sessionKey.current) {
123
- return;
124
- }
125
- const { cipher, nonce } = await getEncryptedData({
126
- businessKey: publicKey,
127
- authType,
128
- projectID: projectId,
129
- sessionID: sessionID.current,
130
- appId
131
- });
132
- const decryptedData = cryptoService.decryptSymmetric({
133
- encrypted: { cipher, nonce },
134
- keyString: sessionKey.current
135
- });
136
- if (decryptedData) {
137
- const result = JSON.parse(decryptedData);
138
- onSuccess(result);
139
- sessionKey.current = null;
140
- sessionID.current = null;
141
- setLoading(false);
142
- onLoading?.(false);
143
- } else {
144
- onError?.(new Error("Failed to get identity result"));
145
- sessionKey.current = null;
146
- sessionID.current = null;
147
- setLoading(false);
148
- onLoading?.(false);
149
- }
150
- } catch (error) {
151
- console.log(error);
152
- onError?.(error);
153
- sessionKey.current = null;
154
- sessionID.current = null;
155
- setLoading(false);
156
- onLoading?.(false);
157
- }
158
- };
159
- React.useEffect(() => {
160
- const subscription = AppState.addEventListener("change", (nextAppState) => {
161
- if (nextAppState === "active") {
162
- handleCallback();
163
- }
184
+ useEffect(() => {
185
+ const handleUrl = (event) => {
186
+ if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();
187
+ };
188
+ const linkSub = Linking.addEventListener("url", handleUrl);
189
+ const appStateSub = AppState.addEventListener("change", (state) => {
190
+ if (state === "active") handleCallback();
164
191
  });
165
192
  return () => {
166
- subscription.remove();
193
+ linkSub.remove();
194
+ appStateSub.remove();
195
+ clearAuthTimeout();
167
196
  };
168
- }, []);
169
- return /* @__PURE__ */ jsx(View, { children: /* @__PURE__ */ jsx(TouchableOpacity, { onPress: initialize, disabled: loading, children: buttonComponent || /* @__PURE__ */ jsxs(
197
+ }, [handleCallback, callBackUrl, clearAuthTimeout]);
198
+ return { initialize, loading };
199
+ };
200
+ var PelicanAuth = (props) => {
201
+ const { initialize, loading } = usePelicanAuth(props);
202
+ return /* @__PURE__ */ jsx(View, { children: /* @__PURE__ */ jsx(TouchableOpacity, { onPress: initialize, disabled: loading, children: props.buttonComponent || /* @__PURE__ */ jsxs(
170
203
  View,
171
204
  {
172
- style: {
173
- flexDirection: "row",
174
- alignItems: "center",
175
- gap: 10,
176
- paddingHorizontal: 10,
177
- paddingVertical: 10,
178
- borderRadius: 20,
179
- borderWidth: 1
180
- },
205
+ style: [
206
+ {
207
+ flexDirection: "row",
208
+ alignItems: "center",
209
+ gap: 10,
210
+ paddingHorizontal: 10,
211
+ paddingVertical: 10,
212
+ borderRadius: 20,
213
+ borderWidth: 1
214
+ },
215
+ props.style
216
+ ],
181
217
  children: [
182
218
  /* @__PURE__ */ jsx(
183
219
  Image,
@@ -188,7 +224,7 @@ var PelicanAuth = ({
188
224
  style: { width: 30, height: 30 }
189
225
  }
190
226
  ),
191
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 16, fontWeight: "600" }, children: authType === "login" ? "Login with Pelican" : authType === "signup" ? "Signup with Pelican" : authType === "id-verification" ? "Verify identity with Pelican" : "Authenticate with Pelican" }),
227
+ /* @__PURE__ */ jsx(Text, { style: { fontSize: 16, fontWeight: "600" }, children: props.authType === "login" ? "Login with Pelican" : props.authType === "signup" ? "Signup with Pelican" : props.authType === "id-verification" ? "Verify with Pelican" : "Authenticate with Pelican" }),
192
228
  loading && /* @__PURE__ */ jsx(ActivityIndicator, { color: "#000" })
193
229
  ]
194
230
  }
@@ -196,6 +232,6 @@ var PelicanAuth = ({
196
232
  };
197
233
  var PelicanAuth_default = PelicanAuth;
198
234
 
199
- export { PelicanAuth_default as PelicanAuth };
235
+ export { PelicanAuth_default as PelicanAuth, usePelicanAuth };
200
236
  //# sourceMappingURL=index.mjs.map
201
237
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utilities.ts","../src/components/PelicanAuth.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import \"react-native-get-random-values\";\n\nimport { BASEURL, type AuthType } from \"@pelican-identity/auth-core\";\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(`Failed to initiate authentication: ${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(`Failed to retrieve authentication session data: ${error}`);\n }\n\n return response.json() as Promise<{ cipher: string; nonce: string }>;\n};\n","import React, { useState } from \"react\";\nimport {\n ActivityIndicator,\n AppState,\n Image,\n Linking,\n Text,\n TouchableOpacity,\n View,\n} from \"react-native\";\nimport \"react-native-get-random-values\";\n\nimport { getEncryptedData, getRelayUrl } from \"../utilities\";\nimport { PelicanRNAuthProps } from \"../types\";\nimport { IdentityResult, CryptoService } from \"@pelican-identity/auth-core\";\n\nconst cryptoService = new CryptoService();\nconst PelicanAuth = ({\n authType,\n projectId,\n publicKey,\n onSuccess,\n callBackUrl,\n onError,\n buttonComponent,\n onLoading,\n appId,\n}: PelicanRNAuthProps) => {\n const sessionKey = React.useRef<string | null>(null);\n const sessionID = React.useRef<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n const initialize = async () => {\n try {\n setLoading(true);\n onLoading?.(true);\n const { relay_url, session_id } = await getRelayUrl({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n appId,\n });\n\n if (!relay_url || !session_id) {\n setLoading(false);\n onLoading?.(false);\n onError?.(new Error(\"Failed to get relay URL\"));\n return;\n }\n\n sessionKey.current = cryptoService.generateSymmetricKey();\n sessionID.current = session_id;\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 Linking.openURL(buildUrl);\n } catch (error) {\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n onError?.(error as Error);\n }\n };\n\n const handleCallback = async () => {\n try {\n if (!sessionID.current) {\n return;\n }\n if (!sessionKey.current) {\n return;\n }\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 const result: IdentityResult = JSON.parse(decryptedData);\n\n onSuccess(result);\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n } else {\n onError?.(new Error(\"Failed to get identity result\"));\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n }\n } catch (error) {\n console.log(error);\n onError?.(error as Error);\n sessionKey.current = null;\n sessionID.current = null;\n setLoading(false);\n onLoading?.(false);\n }\n };\n\n React.useEffect(() => {\n const subscription = AppState.addEventListener(\"change\", (nextAppState) => {\n if (nextAppState === \"active\") {\n handleCallback();\n }\n });\n return () => {\n subscription.remove();\n };\n }, []);\n\n return (\n <View>\n <TouchableOpacity onPress={initialize} disabled={loading}>\n {buttonComponent || (\n <View\n style={{\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 10,\n paddingHorizontal: 10,\n paddingVertical: 10,\n borderRadius: 20,\n borderWidth: 1,\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 style={{ fontSize: 16, fontWeight: \"600\" }}>\n {authType === \"login\"\n ? \"Login with Pelican\"\n : authType === \"signup\"\n ? \"Signup with Pelican\"\n : authType === \"id-verification\"\n ? \"Verify identity 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,"sources":["../src/utilities.ts","../src/hooks/usePelicanAuth.ts","../src/components/PelicanAuth.tsx"],"names":[],"mappings":"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","file":"index.mjs","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\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) return;\n\n try {\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 }\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\") handleCallback();\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 style={{ fontSize: 16, fontWeight: \"600\" }}>\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pelican-identity/react-native",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
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.5"
25
+ "@pelican-identity/auth-core": "1.2.6"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.2.45",