@pelican-identity/react-native 1.2.17 → 1.2.19

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
@@ -107,6 +107,58 @@ In `app.json`:
107
107
  callBackUrl = "myapp://auth-callback";
108
108
  ```
109
109
 
110
+ ## ⚠️ Important: Callback URL Constraints
111
+
112
+ The Pelican SDK uses a secure handshake mechanism.
113
+ To ensure maximum compatibility across mobile operating systems and to prevent URI manipulation attacks, **do not append query parameters** to your `callBackUrl`.
114
+
115
+ ---
116
+
117
+ ### ✅ Correct Configuration
118
+
119
+ Your `callBackUrl` must be a clean **Custom Scheme** or **Universal Link path**.
120
+ The SDK and the Pelican App handle all data transmission internally.
121
+
122
+ | Status | Format | Example |
123
+ | ------------ | --------------- | ------------------------------------- |
124
+ | ✅ Correct | Custom Scheme | `my-app://auth-callback` |
125
+ | ✅ Correct | Universal Link | `https://my-domain.com/auth-callback` |
126
+ | ❌ Incorrect | With Parameters | `my-app://auth?user=123` |
127
+
128
+ ---
129
+
130
+ ### 🔐 Why This Is Required
131
+
132
+ Appending parameters to the `callBackUrl` can break Pelican’s signature verification process.
133
+
134
+ The Pelican App expects a **Base Path only**, which it uses to redirect the user back to your application securely.
135
+
136
+ Once the user returns:
137
+
138
+ - The SDK automatically retrieves the encrypted payload
139
+ - Using the `sessionID` established during `initialize()`
140
+ - Without exposing sensitive data in the URL
141
+
142
+ ---
143
+
144
+ ### 📌 Recommended Flow (No-Query Environment)
145
+
146
+ Since query strings are not supported:
147
+
148
+ - The Pelican App redirects to the base callback path
149
+ - Your SDK listens for the callback event
150
+ - Your app then securely polls the backend using the existing `sessionID`
151
+
152
+ This ensures:
153
+
154
+ ✅ Tamper resistance
155
+ ✅ Cross-platform reliability
156
+ ✅ Zero sensitive data in URLs
157
+
158
+ ---
159
+
160
+ > **Never pass authentication data via URL parameters. Always rely on Pelican’s secure session-based retrieval flow.**
161
+
110
162
  Configure deep linking:
111
163
 
112
164
  - **iOS:** Xcode → Info → URL Types
@@ -247,6 +299,10 @@ interface IdentityResult {
247
299
  /** Deterministic unique user identifier specific to your business */
248
300
  user_id: string;
249
301
 
302
+ /** Authentication Assurance level */
303
+ /** AAL1 - Passcode */
304
+ /** AAL2 - Biometric */
305
+ assurance_level: { level: number; type: "passcode" | "biometric" };
250
306
  /** Basic user profile and contact information (if available) */
251
307
  user_data?: IUserData;
252
308
 
@@ -274,6 +330,17 @@ interface IdentityResult {
274
330
 
275
331
  ---
276
332
 
333
+ ## Assurance Level (`assurance_level`)
334
+
335
+ Pelican will prompt users to authenticate using the required assurance level configured in the project settings when possible. Authentication may still succeed with a lower level, but the achieved assurance level is always returned in the response. Your application is responsible for enforcing access based on this level.
336
+
337
+ ```ts
338
+ interface AssuranceLevel {
339
+ level: number;
340
+ type: "passcode" | "biometric";
341
+ }
342
+ ```
343
+
277
344
  ## User Data (`user_data`)
278
345
 
279
346
  Returned when available and permitted by the authentication flow.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PelicanAuth.d.ts","sourceRoot":"","sources":["../../src/components/PelicanAuth.tsx"],"names":[],"mappings":"AAOA,OAAO,gCAAgC,CAAC;AAGxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,QAAA,MAAM,WAAW,GAAI,OAAO,kBAAkB,4CA8C7C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePelicanAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/usePelicanAuth.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAIpD,eAAO,MAAM,cAAc,GAAI,OAAO,kBAAkB;;;CA0KvD,CAAC"}
@@ -0,0 +1,135 @@
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 (url) => {
20
+ if (isProcessing.current)
21
+ return;
22
+ let activeSessionID = sessionID.current;
23
+ if (url) {
24
+ const params = url.split("?")[1];
25
+ if (params) {
26
+ const pair = params
27
+ .split("&")
28
+ .find((p) => p.startsWith("sessionID="));
29
+ if (pair) {
30
+ activeSessionID = decodeURIComponent(pair.split("=")[1] || "");
31
+ }
32
+ }
33
+ }
34
+ if (!activeSessionID || !sessionKey.current) {
35
+ console.warn("[Pelican] Missing Session ID or Key for decryption");
36
+ return;
37
+ }
38
+ try {
39
+ isProcessing.current = true;
40
+ const { cipher, nonce } = await getEncryptedData({
41
+ businessKey: publicKey,
42
+ authType,
43
+ projectID: projectId,
44
+ sessionID: activeSessionID,
45
+ appId,
46
+ });
47
+ const decryptedData = cryptoService.decryptSymmetric({
48
+ encrypted: { cipher, nonce },
49
+ keyString: sessionKey.current,
50
+ });
51
+ if (decryptedData) {
52
+ clearAuthTimeout();
53
+ const result = JSON.parse(decryptedData);
54
+ onSuccess(result);
55
+ sessionKey.current = null;
56
+ sessionID.current = null;
57
+ setLoading(false);
58
+ onLoading?.(false);
59
+ }
60
+ }
61
+ catch (error) {
62
+ console.error("[Pelican] Callback Error:", error);
63
+ onError?.(error);
64
+ }
65
+ finally {
66
+ isProcessing.current = false;
67
+ }
68
+ }, [
69
+ authType,
70
+ projectId,
71
+ publicKey,
72
+ appId,
73
+ onSuccess,
74
+ onError,
75
+ onLoading,
76
+ clearAuthTimeout,
77
+ ]);
78
+ const initialize = async () => {
79
+ const validation = validateCallbackUrl(callBackUrl || "");
80
+ if (!validation.isValid) {
81
+ console.warn(`[Pelican] ${validation.reason}`);
82
+ onError?.(new Error(validation.reason));
83
+ return;
84
+ }
85
+ try {
86
+ clearAuthTimeout();
87
+ setLoading(true);
88
+ onLoading?.(true);
89
+ const { relay_url, session_id } = await getRelayUrl({
90
+ businessKey: publicKey,
91
+ authType,
92
+ projectID: projectId,
93
+ appId,
94
+ });
95
+ sessionKey.current = cryptoService.generateSymmetricKey();
96
+ sessionID.current = session_id;
97
+ timeoutRef.current = setTimeout(() => {
98
+ if (sessionID.current) {
99
+ setLoading(false);
100
+ onLoading?.(false);
101
+ sessionID.current = null;
102
+ onError?.(new Error("Authentication timed out"));
103
+ }
104
+ }, 5 * 60 * 1000);
105
+ const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(sessionKey.current)}&sessionID=${encodeURIComponent(sessionID.current)}&authType=${encodeURIComponent(authType)}&projectId=${encodeURIComponent(projectId)}&publicKey=${encodeURIComponent(publicKey)}&callBackUrl=${encodeURIComponent(callBackUrl || "")}`;
106
+ Linking.openURL(buildUrl);
107
+ }
108
+ catch (error) {
109
+ setLoading(false);
110
+ onLoading?.(false);
111
+ onError?.(error);
112
+ }
113
+ };
114
+ useEffect(() => {
115
+ const handleUrl = (event) => {
116
+ if (callBackUrl && event.url.startsWith(callBackUrl))
117
+ handleCallback(event.url);
118
+ };
119
+ const linkSub = Linking.addEventListener("url", handleUrl);
120
+ const appStateSub = AppState.addEventListener("change", (state) => {
121
+ if (state === "active") {
122
+ setTimeout(() => {
123
+ handleCallback();
124
+ }, 700);
125
+ }
126
+ });
127
+ return () => {
128
+ linkSub.remove();
129
+ appStateSub.remove();
130
+ clearAuthTimeout();
131
+ };
132
+ }, [handleCallback, callBackUrl, clearAuthTimeout]);
133
+ return { initialize, loading };
134
+ };
135
+ //# sourceMappingURL=usePelicanAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePelicanAuth.js","sourceRoot":"","sources":["../../src/hooks/usePelicanAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","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;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxD,mBAAmB,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -65,18 +65,30 @@ var getEncryptedData = async ({
65
65
  };
66
66
  var validateCallbackUrl = (url) => {
67
67
  if (!url) return { isValid: false, reason: "Callback URL is missing." };
68
+ if (url.startsWith("https://") || url.startsWith("http://")) {
69
+ return {
70
+ isValid: false,
71
+ reason: "Universal Links (https) are not permitted. Please use your app's Custom Scheme (e.g., 'myapp://callback') to ensure a reliable redirect."
72
+ };
73
+ }
68
74
  const isExpo = url.startsWith("exp://");
69
- const isStandardScheme = /^[a-z0-9]+:\/\//i.test(url);
70
- if (!isStandardScheme && !isExpo) {
75
+ const isCustomScheme = /^[a-z0-9+.-]+:\/\//i.test(url);
76
+ if (!isCustomScheme && !isExpo) {
71
77
  return {
72
78
  isValid: false,
73
- reason: "URL must include a scheme (e.g., 'myapp://' or 'exp://')."
79
+ reason: "URL must include a valid Custom Scheme (e.g., 'myapp://')."
80
+ };
81
+ }
82
+ if (url.includes("?") || url.includes("&")) {
83
+ return {
84
+ isValid: false,
85
+ reason: "## DO NOT ADD URL PARAMETERS TO YOUR CALLBACK URL. The SDK handles session state automatically."
74
86
  };
75
87
  }
76
88
  if (reactNative.Platform.OS === "ios" && url.includes("_")) {
77
89
  return {
78
90
  isValid: false,
79
- reason: "iOS Custom Schemes should not contain underscores as per Apple guidelines."
91
+ reason: "iOS Custom Schemes cannot contain underscores. Use hyphens (e.g., 'my-app://')."
80
92
  };
81
93
  }
82
94
  return { isValid: true };
@@ -106,50 +118,70 @@ var usePelicanAuth = (props) => {
106
118
  timeoutRef.current = null;
107
119
  }
108
120
  }, []);
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);
121
+ const handleCallback = react.useCallback(
122
+ async (url) => {
123
+ if (isProcessing.current) return;
124
+ let activeSessionID = sessionID.current;
125
+ if (url) {
126
+ const params = url.split("?")[1];
127
+ if (params) {
128
+ const pair = params.split("&").find((p) => p.startsWith("sessionID="));
129
+ if (pair) {
130
+ activeSessionID = decodeURIComponent(pair.split("=")[1] || "");
131
+ }
132
+ }
133
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
- ]);
134
+ if (!activeSessionID || !sessionKey.current) {
135
+ console.warn("[Pelican] Missing Session ID or Key for decryption");
136
+ return;
137
+ }
138
+ try {
139
+ isProcessing.current = true;
140
+ const { cipher, nonce } = await getEncryptedData({
141
+ businessKey: publicKey,
142
+ authType,
143
+ projectID: projectId,
144
+ sessionID: activeSessionID,
145
+ appId
146
+ });
147
+ const decryptedData = cryptoService.decryptSymmetric({
148
+ encrypted: { cipher, nonce },
149
+ keyString: sessionKey.current
150
+ });
151
+ if (decryptedData) {
152
+ clearAuthTimeout();
153
+ const result = JSON.parse(decryptedData);
154
+ onSuccess(result);
155
+ sessionKey.current = null;
156
+ sessionID.current = null;
157
+ setLoading(false);
158
+ onLoading?.(false);
159
+ }
160
+ } catch (error) {
161
+ console.error("[Pelican] Callback Error:", error);
162
+ onError?.(error);
163
+ } finally {
164
+ isProcessing.current = false;
165
+ }
166
+ },
167
+ [
168
+ authType,
169
+ projectId,
170
+ publicKey,
171
+ appId,
172
+ onSuccess,
173
+ onError,
174
+ onLoading,
175
+ clearAuthTimeout
176
+ ]
177
+ );
150
178
  const initialize = async () => {
151
179
  const validation = validateCallbackUrl(callBackUrl || "");
152
- if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);
180
+ if (!validation.isValid) {
181
+ console.warn(`[Pelican] ${validation.reason}`);
182
+ onError?.(new Error(validation.reason));
183
+ return;
184
+ }
153
185
  try {
154
186
  clearAuthTimeout();
155
187
  setLoading(true);
@@ -162,14 +194,17 @@ var usePelicanAuth = (props) => {
162
194
  });
163
195
  sessionKey.current = cryptoService.generateSymmetricKey();
164
196
  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);
197
+ timeoutRef.current = setTimeout(
198
+ () => {
199
+ if (sessionID.current) {
200
+ setLoading(false);
201
+ onLoading?.(false);
202
+ sessionID.current = null;
203
+ onError?.(new Error("Authentication timed out"));
204
+ }
205
+ },
206
+ 5 * 60 * 1e3
207
+ );
173
208
  const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(
174
209
  sessionKey.current
175
210
  )}&sessionID=${encodeURIComponent(
@@ -190,7 +225,8 @@ var usePelicanAuth = (props) => {
190
225
  };
191
226
  react.useEffect(() => {
192
227
  const handleUrl = (event) => {
193
- if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();
228
+ if (callBackUrl && event.url.startsWith(callBackUrl))
229
+ handleCallback(event.url);
194
230
  };
195
231
  const linkSub = reactNative.Linking.addEventListener("url", handleUrl);
196
232
  const appStateSub = reactNative.AppState.addEventListener("change", (state) => {
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,"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 // 1. Explicitly block Web/Universal Links\n if (url.startsWith(\"https://\") || url.startsWith(\"http://\")) {\n return {\n isValid: false,\n reason:\n \"Universal Links (https) are not permitted. Please use your app's Custom Scheme (e.g., 'myapp://callback') to ensure a reliable redirect.\",\n };\n }\n\n const isExpo = url.startsWith(\"exp://\");\n const isCustomScheme = /^[a-z0-9+.-]+:\\/\\//i.test(url);\n\n // 2. Ensure it follows a scheme format\n if (!isCustomScheme && !isExpo) {\n return {\n isValid: false,\n reason: \"URL must include a valid Custom Scheme (e.g., 'myapp://').\",\n };\n }\n\n // 3. The \"No Query\" Guard\n if (url.includes(\"?\") || url.includes(\"&\")) {\n return {\n isValid: false,\n reason:\n \"## DO NOT ADD URL PARAMETERS TO YOUR CALLBACK URL. The SDK handles session state automatically.\",\n };\n }\n\n // 4. Apple naming convention guard\n if (Platform.OS === \"ios\" && url.includes(\"_\")) {\n return {\n isValid: false,\n reason:\n \"iOS Custom Schemes cannot contain underscores. Use hyphens (e.g., 'my-app://').\",\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(\n async (url?: string) => {\n if (isProcessing.current) return;\n\n let activeSessionID = sessionID.current;\n\n if (url) {\n const params = url.split(\"?\")[1];\n if (params) {\n const pair = params\n .split(\"&\")\n .find((p) => p.startsWith(\"sessionID=\"));\n if (pair) {\n activeSessionID = decodeURIComponent(pair.split(\"=\")[1] || \"\");\n }\n }\n }\n\n if (!activeSessionID || !sessionKey.current) {\n console.warn(\"[Pelican] Missing Session ID or Key for decryption\");\n return;\n }\n\n try {\n isProcessing.current = true;\n const { cipher, nonce } = await getEncryptedData({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n sessionID: activeSessionID,\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 [\n authType,\n projectId,\n publicKey,\n appId,\n onSuccess,\n onError,\n onLoading,\n clearAuthTimeout,\n ],\n );\n\n const initialize = async () => {\n const validation = validateCallbackUrl(callBackUrl || \"\");\n if (!validation.isValid) {\n console.warn(`[Pelican] ${validation.reason}`);\n onError?.(new Error(validation.reason));\n return;\n }\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 () => {\n if (sessionID.current) {\n setLoading(false);\n onLoading?.(false);\n sessionID.current = null;\n onError?.(new Error(\"Authentication timed out\"));\n }\n },\n 5 * 60 * 1000,\n );\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))\n handleCallback(event.url);\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"]}
package/dist/index.mjs CHANGED
@@ -63,18 +63,30 @@ var getEncryptedData = async ({
63
63
  };
64
64
  var validateCallbackUrl = (url) => {
65
65
  if (!url) return { isValid: false, reason: "Callback URL is missing." };
66
+ if (url.startsWith("https://") || url.startsWith("http://")) {
67
+ return {
68
+ isValid: false,
69
+ reason: "Universal Links (https) are not permitted. Please use your app's Custom Scheme (e.g., 'myapp://callback') to ensure a reliable redirect."
70
+ };
71
+ }
66
72
  const isExpo = url.startsWith("exp://");
67
- const isStandardScheme = /^[a-z0-9]+:\/\//i.test(url);
68
- if (!isStandardScheme && !isExpo) {
73
+ const isCustomScheme = /^[a-z0-9+.-]+:\/\//i.test(url);
74
+ if (!isCustomScheme && !isExpo) {
69
75
  return {
70
76
  isValid: false,
71
- reason: "URL must include a scheme (e.g., 'myapp://' or 'exp://')."
77
+ reason: "URL must include a valid Custom Scheme (e.g., 'myapp://')."
78
+ };
79
+ }
80
+ if (url.includes("?") || url.includes("&")) {
81
+ return {
82
+ isValid: false,
83
+ reason: "## DO NOT ADD URL PARAMETERS TO YOUR CALLBACK URL. The SDK handles session state automatically."
72
84
  };
73
85
  }
74
86
  if (Platform.OS === "ios" && url.includes("_")) {
75
87
  return {
76
88
  isValid: false,
77
- reason: "iOS Custom Schemes should not contain underscores as per Apple guidelines."
89
+ reason: "iOS Custom Schemes cannot contain underscores. Use hyphens (e.g., 'my-app://')."
78
90
  };
79
91
  }
80
92
  return { isValid: true };
@@ -104,50 +116,70 @@ var usePelicanAuth = (props) => {
104
116
  timeoutRef.current = null;
105
117
  }
106
118
  }, []);
107
- const handleCallback = useCallback(async () => {
108
- if (!sessionID.current || !sessionKey.current || isProcessing.current)
109
- return;
110
- try {
111
- isProcessing.current = true;
112
- const { cipher, nonce } = await getEncryptedData({
113
- businessKey: publicKey,
114
- authType,
115
- projectID: projectId,
116
- sessionID: sessionID.current,
117
- appId
118
- });
119
- const decryptedData = cryptoService.decryptSymmetric({
120
- encrypted: { cipher, nonce },
121
- keyString: sessionKey.current
122
- });
123
- if (decryptedData) {
124
- clearAuthTimeout();
125
- const result = JSON.parse(decryptedData);
126
- onSuccess(result);
127
- sessionKey.current = null;
128
- sessionID.current = null;
129
- setLoading(false);
130
- onLoading?.(false);
119
+ const handleCallback = useCallback(
120
+ async (url) => {
121
+ if (isProcessing.current) return;
122
+ let activeSessionID = sessionID.current;
123
+ if (url) {
124
+ const params = url.split("?")[1];
125
+ if (params) {
126
+ const pair = params.split("&").find((p) => p.startsWith("sessionID="));
127
+ if (pair) {
128
+ activeSessionID = decodeURIComponent(pair.split("=")[1] || "");
129
+ }
130
+ }
131
131
  }
132
- } catch (error) {
133
- console.error("Pelican Callback Error:", error);
134
- onError?.(error);
135
- } finally {
136
- isProcessing.current = false;
137
- }
138
- }, [
139
- authType,
140
- projectId,
141
- publicKey,
142
- appId,
143
- onSuccess,
144
- onError,
145
- onLoading,
146
- clearAuthTimeout
147
- ]);
132
+ if (!activeSessionID || !sessionKey.current) {
133
+ console.warn("[Pelican] Missing Session ID or Key for decryption");
134
+ return;
135
+ }
136
+ try {
137
+ isProcessing.current = true;
138
+ const { cipher, nonce } = await getEncryptedData({
139
+ businessKey: publicKey,
140
+ authType,
141
+ projectID: projectId,
142
+ sessionID: activeSessionID,
143
+ appId
144
+ });
145
+ const decryptedData = cryptoService.decryptSymmetric({
146
+ encrypted: { cipher, nonce },
147
+ keyString: sessionKey.current
148
+ });
149
+ if (decryptedData) {
150
+ clearAuthTimeout();
151
+ const result = JSON.parse(decryptedData);
152
+ onSuccess(result);
153
+ sessionKey.current = null;
154
+ sessionID.current = null;
155
+ setLoading(false);
156
+ onLoading?.(false);
157
+ }
158
+ } catch (error) {
159
+ console.error("[Pelican] Callback Error:", error);
160
+ onError?.(error);
161
+ } finally {
162
+ isProcessing.current = false;
163
+ }
164
+ },
165
+ [
166
+ authType,
167
+ projectId,
168
+ publicKey,
169
+ appId,
170
+ onSuccess,
171
+ onError,
172
+ onLoading,
173
+ clearAuthTimeout
174
+ ]
175
+ );
148
176
  const initialize = async () => {
149
177
  const validation = validateCallbackUrl(callBackUrl || "");
150
- if (!validation.isValid) console.warn(`[Pelican] ${validation.reason}`);
178
+ if (!validation.isValid) {
179
+ console.warn(`[Pelican] ${validation.reason}`);
180
+ onError?.(new Error(validation.reason));
181
+ return;
182
+ }
151
183
  try {
152
184
  clearAuthTimeout();
153
185
  setLoading(true);
@@ -160,14 +192,17 @@ var usePelicanAuth = (props) => {
160
192
  });
161
193
  sessionKey.current = cryptoService.generateSymmetricKey();
162
194
  sessionID.current = session_id;
163
- timeoutRef.current = setTimeout(() => {
164
- if (sessionID.current) {
165
- setLoading(false);
166
- onLoading?.(false);
167
- sessionID.current = null;
168
- onError?.(new Error("Authentication timed out"));
169
- }
170
- }, 5 * 60 * 1e3);
195
+ timeoutRef.current = setTimeout(
196
+ () => {
197
+ if (sessionID.current) {
198
+ setLoading(false);
199
+ onLoading?.(false);
200
+ sessionID.current = null;
201
+ onError?.(new Error("Authentication timed out"));
202
+ }
203
+ },
204
+ 5 * 60 * 1e3
205
+ );
171
206
  const buildUrl = `${relay_url}?sessionKey=${encodeURIComponent(
172
207
  sessionKey.current
173
208
  )}&sessionID=${encodeURIComponent(
@@ -188,7 +223,8 @@ var usePelicanAuth = (props) => {
188
223
  };
189
224
  useEffect(() => {
190
225
  const handleUrl = (event) => {
191
- if (callBackUrl && event.url.startsWith(callBackUrl)) handleCallback();
226
+ if (callBackUrl && event.url.startsWith(callBackUrl))
227
+ handleCallback(event.url);
192
228
  };
193
229
  const linkSub = Linking.addEventListener("url", handleUrl);
194
230
  const appStateSub = AppState.addEventListener("change", (state) => {
@@ -1 +1 @@
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 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,"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 // 1. Explicitly block Web/Universal Links\n if (url.startsWith(\"https://\") || url.startsWith(\"http://\")) {\n return {\n isValid: false,\n reason:\n \"Universal Links (https) are not permitted. Please use your app's Custom Scheme (e.g., 'myapp://callback') to ensure a reliable redirect.\",\n };\n }\n\n const isExpo = url.startsWith(\"exp://\");\n const isCustomScheme = /^[a-z0-9+.-]+:\\/\\//i.test(url);\n\n // 2. Ensure it follows a scheme format\n if (!isCustomScheme && !isExpo) {\n return {\n isValid: false,\n reason: \"URL must include a valid Custom Scheme (e.g., 'myapp://').\",\n };\n }\n\n // 3. The \"No Query\" Guard\n if (url.includes(\"?\") || url.includes(\"&\")) {\n return {\n isValid: false,\n reason:\n \"## DO NOT ADD URL PARAMETERS TO YOUR CALLBACK URL. The SDK handles session state automatically.\",\n };\n }\n\n // 4. Apple naming convention guard\n if (Platform.OS === \"ios\" && url.includes(\"_\")) {\n return {\n isValid: false,\n reason:\n \"iOS Custom Schemes cannot contain underscores. Use hyphens (e.g., 'my-app://').\",\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(\n async (url?: string) => {\n if (isProcessing.current) return;\n\n let activeSessionID = sessionID.current;\n\n if (url) {\n const params = url.split(\"?\")[1];\n if (params) {\n const pair = params\n .split(\"&\")\n .find((p) => p.startsWith(\"sessionID=\"));\n if (pair) {\n activeSessionID = decodeURIComponent(pair.split(\"=\")[1] || \"\");\n }\n }\n }\n\n if (!activeSessionID || !sessionKey.current) {\n console.warn(\"[Pelican] Missing Session ID or Key for decryption\");\n return;\n }\n\n try {\n isProcessing.current = true;\n const { cipher, nonce } = await getEncryptedData({\n businessKey: publicKey,\n authType,\n projectID: projectId,\n sessionID: activeSessionID,\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 [\n authType,\n projectId,\n publicKey,\n appId,\n onSuccess,\n onError,\n onLoading,\n clearAuthTimeout,\n ],\n );\n\n const initialize = async () => {\n const validation = validateCallbackUrl(callBackUrl || \"\");\n if (!validation.isValid) {\n console.warn(`[Pelican] ${validation.reason}`);\n onError?.(new Error(validation.reason));\n return;\n }\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 () => {\n if (sessionID.current) {\n setLoading(false);\n onLoading?.(false);\n sessionID.current = null;\n onError?.(new Error(\"Authentication timed out\"));\n }\n },\n 5 * 60 * 1000,\n );\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))\n handleCallback(event.url);\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"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC/D,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,GAAG,aAAa,CAAC;IAKjE,KAAK,EAAE,MAAM,CAAC;IAOd,SAAS,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAO5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAOjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAOvC,eAAe,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAIrC,WAAW,EAAE,MAAM,CAAC;IAKpB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAI7B,eAAe,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CACxC"}
@@ -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;CA0CrC,CAAC"}
@@ -0,0 +1,74 @@
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
+ if (url.startsWith("https://") || url.startsWith("http://")) {
47
+ return {
48
+ isValid: false,
49
+ reason: "Universal Links (https) are not permitted. Please use your app's Custom Scheme (e.g., 'myapp://callback') to ensure a reliable redirect.",
50
+ };
51
+ }
52
+ const isExpo = url.startsWith("exp://");
53
+ const isCustomScheme = /^[a-z0-9+.-]+:\/\//i.test(url);
54
+ if (!isCustomScheme && !isExpo) {
55
+ return {
56
+ isValid: false,
57
+ reason: "URL must include a valid Custom Scheme (e.g., 'myapp://').",
58
+ };
59
+ }
60
+ if (url.includes("?") || url.includes("&")) {
61
+ return {
62
+ isValid: false,
63
+ reason: "## DO NOT ADD URL PARAMETERS TO YOUR CALLBACK URL. The SDK handles session state automatically.",
64
+ };
65
+ }
66
+ if (Platform.OS === "ios" && url.includes("_")) {
67
+ return {
68
+ isValid: false,
69
+ reason: "iOS Custom Schemes cannot contain underscores. Use hyphens (e.g., 'my-app://').",
70
+ };
71
+ }
72
+ return { isValid: true };
73
+ };
74
+ //# 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.17",
3
+ "version": "1.2.19",
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.15"
25
+ "@pelican-identity/auth-core": "1.2.17"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.2.45",