@pelican-identity/react-native 1.2.18 → 1.2.20
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 +52 -0
- package/dist/index.js +90 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +90 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/components/PelicanAuth.d.ts.map +0 -1
- package/dist/hooks/usePelicanAuth.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types/types.d.ts.map +0 -1
- package/dist/utilities.d.ts.map +0 -1
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
|
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
|
|
70
|
-
if (!
|
|
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
|
|
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
|
|
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(
|
|
110
|
-
|
|
111
|
-
return;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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)
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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))
|
|
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":";;;;;;;;;AAKO,IAAM,cAAc,OAAO;AAAA,EAChC,WAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,KAKM;AACJ,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,EAC1C;AACA,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AACA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,cAAA,EAAgB,kBAAA;AAAA,IAChB,UAAA,EAAY;AAAA,GACd;AAEA,EAAA,MAAM,WAAW,MAAM,KAAA;AAAA,IACrB,GAAGA,gBAAO,CAAA,kBAAA,EAAqB,WAAW,CAAA,WAAA,EAAc,QAAQ,eAAe,SAAS,CAAA,CAAA;AAAA,IACxF,EAAE,OAAA;AAAQ,GACZ;AAEA,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,MAAM,KAAK,CAAA;AAAA,EACvB;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB,CAAA;AAEO,IAAM,mBAAmB,OAAO;AAAA,EACrC,WAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,KAMM;AACJ,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AACA,EAAA,MAAM,OAAA,GAAU;AAAA,IACd,cAAA,EAAgB,kBAAA;AAAA,IAChB,UAAA,EAAY;AAAA,GACd;AAEA,EAAA,MAAM,WAAW,MAAM,KAAA;AAAA,IACrB,CAAA,EAAGA,gBAAO,CAAA,sCAAA,EAAyC,WAAW,cAAc,QAAQ,CAAA,YAAA,EAAe,SAAS,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA;AAAA,IACpI,EAAE,OAAA;AAAQ,GACZ;AAEA,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,MAAM,KAAK,CAAA;AAAA,EACvB;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB,CAAA;AAMO,IAAM,mBAAA,GAAsB,CACjC,GAAA,KAC0C;AAC1C,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,QAAQ,0BAAA,EAA2B;AAGtE,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,UAAA,CAAW,QAAQ,CAAA;AACtC,EAAA,MAAM,gBAAA,GAAmB,kBAAA,CAAmB,IAAA,CAAK,GAAG,CAAA;AAEpD,EAAA,IAAI,CAAC,gBAAA,IAAoB,CAAC,MAAA,EAAQ;AAChC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,IAAIC,qBAAS,EAAA,KAAO,KAAA,IAAS,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAC9C,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EACE;AAAA,KACJ;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,SAAS,IAAA,EAAK;AACzB,CAAA;;;ACnGA,IAAM,aAAA,GAAgB,IAAIC,sBAAA,EAAc;AAEjC,IAAM,cAAA,GAAiB,CAAC,KAAA,KAA8B;AAC3D,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAEJ,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,UAAA,GAAaC,aAAsB,IAAI,CAAA;AAC7C,EAAA,MAAM,SAAA,GAAYA,aAAsB,IAAI,CAAA;AAC5C,EAAA,MAAM,UAAA,GAAaA,aAA8B,IAAI,CAAA;AACrD,EAAA,MAAM,YAAA,GAAeA,aAAO,KAAK,CAAA;AAEjC,EAAA,MAAM,gBAAA,GAAmBC,kBAAY,MAAM;AACzC,IAAA,IAAI,WAAW,OAAA,EAAS;AACtB,MAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,cAAA,GAAiBA,kBAAY,YAAY;AAC7C,IAAA,IAAI,CAAC,SAAA,CAAU,OAAA,IAAW,CAAC,UAAA,CAAW,WAAW,YAAA,CAAa,OAAA;AAC5D,MAAA;AAEF,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,MAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,MAAM,gBAAA,CAAiB;AAAA,QAC/C,WAAA,EAAa,SAAA;AAAA,QACb,QAAA;AAAA,QACA,SAAA,EAAW,SAAA;AAAA,QACX,WAAW,SAAA,CAAU,OAAA;AAAA,QACrB;AAAA,OACD,CAAA;AAED,MAAA,MAAM,aAAA,GAAgB,cAAc,gBAAA,CAAiB;AAAA,QACnD,SAAA,EAAW,EAAE,MAAA,EAAQ,KAAA,EAAM;AAAA,QAC3B,WAAW,UAAA,CAAW;AAAA,OACvB,CAAA;AAED,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,gBAAA,EAAiB;AACjB,QAAA,MAAM,MAAA,GAAyB,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AACvD,QAAA,SAAA,CAAU,MAAM,CAAA;AAChB,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,QAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,QAAA,UAAA,CAAW,KAAK,CAAA;AAChB,QAAA,SAAA,GAAY,KAAK,CAAA;AAAA,MACnB;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAC9C,MAAA,OAAA,GAAU,KAAc,CAAA;AAAA,IAC1B,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG;AAAA,IACD,QAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,aAAa,YAAY;AAC7B,IAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,WAAA,IAAe,EAAE,CAAA;AACxD,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,UAAA,CAAW,MAAM,CAAA,CAAE,CAAA;AAEtE,IAAA,IAAI;AACF,MAAA,gBAAA,EAAiB;AACjB,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,SAAA,GAAY,IAAI,CAAA;AAEhB,MAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAW,GAAI,MAAM,WAAA,CAAY;AAAA,QAClD,WAAA,EAAa,SAAA;AAAA,QACb,QAAA;AAAA,QACA,SAAA,EAAW,SAAA;AAAA,QACX;AAAA,OACD,CAAA;AAED,MAAA,UAAA,CAAW,OAAA,GAAU,cAAc,oBAAA,EAAqB;AACxD,MAAA,SAAA,CAAU,OAAA,GAAU,UAAA;AAGpB,MAAA,UAAA,CAAW,OAAA,GAAU,WAAW,MAAM;AACpC,QAAA,IAAI,UAAU,OAAA,EAAS;AACrB,UAAA,UAAA,CAAW,KAAK,CAAA;AAChB,UAAA,SAAA,GAAY,KAAK,CAAA;AACjB,UAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,UAAA,OAAA,GAAU,IAAI,KAAA,CAAM,0BAA0B,CAAC,CAAA;AAAA,QACjD;AAAA,MACF,CAAA,EAAG,CAAA,GAAI,EAAA,GAAK,GAAI,CAAA;AAEhB,MAAA,MAAM,QAAA,GAAW,CAAA,EAAG,SAAS,CAAA,YAAA,EAAe,kBAAA;AAAA,QAC1C,UAAA,CAAW;AAAA,OACZ,CAAA,WAAA,EAAc,kBAAA;AAAA,QACb,SAAA,CAAU;AAAA,OACX,CAAA,UAAA,EAAa,kBAAA;AAAA,QACZ;AAAA,OACD,CAAA,WAAA,EAAc,kBAAA;AAAA,QACb;AAAA,OACD,CAAA,WAAA,EAAc,kBAAA;AAAA,QACb;AAAA,OACD,CAAA,aAAA,EAAgB,kBAAA,CAAmB,WAAA,IAAe,EAAE,CAAC,CAAA,CAAA;AAEtD,MAAAC,mBAAA,CAAQ,QAAQ,QAAQ,CAAA;AAAA,IAC1B,SAAS,KAAA,EAAO;AACd,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA,SAAA,GAAY,KAAK,CAAA;AACjB,MAAA,OAAA,GAAU,KAAc,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAA2B;AAC5C,MAAA,IAAI,eAAe,KAAA,CAAM,GAAA,CAAI,UAAA,CAAW,WAAW,GAAG,cAAA,EAAe;AAAA,IACvE,CAAA;AAEA,IAAA,MAAM,OAAA,GAAUD,mBAAA,CAAQ,gBAAA,CAAiB,KAAA,EAAO,SAAS,CAAA;AACzD,IAAA,MAAM,WAAA,GAAcE,oBAAA,CAAS,gBAAA,CAAiB,QAAA,EAAU,CAAC,KAAA,KAAU;AACjE,MAAA,IAAI,UAAU,QAAA,EAAU;AACtB,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,cAAA,EAAe;AAAA,QACjB,GAAG,GAAG,CAAA;AAAA,MACR;AAAA,IACF,CAAC,CAAA;AAED,IAAA,OAAO,MAAM;AACX,MAAA,OAAA,CAAQ,MAAA,EAAO;AACf,MAAA,WAAA,CAAY,MAAA,EAAO;AACnB,MAAA,gBAAA,EAAiB;AAAA,IACnB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,cAAA,EAAgB,WAAA,EAAa,gBAAgB,CAAC,CAAA;AAElD,EAAA,OAAO,EAAE,YAAY,OAAA,EAAQ;AAC/B;AC9IA,IAAM,WAAA,GAAc,CAAC,KAAA,KAA8B;AACjD,EAAA,MAAM,EAAE,UAAA,EAAY,OAAA,EAAQ,GAAI,eAAe,KAAK,CAAA;AACpD,EAAA,uBACEC,cAAA,CAACC,oBACC,QAAA,kBAAAD,cAAA,CAACE,4BAAA,EAAA,EAAiB,SAAS,UAAA,EAAY,QAAA,EAAU,OAAA,EAC9C,QAAA,EAAA,KAAA,CAAM,eAAA,oBACLC,eAAA;AAAA,IAACF,gBAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL;AAAA,UACE,aAAA,EAAe,KAAA;AAAA,UACf,UAAA,EAAY,QAAA;AAAA,UACZ,GAAA,EAAK,EAAA;AAAA,UACL,iBAAA,EAAmB,EAAA;AAAA,UACnB,eAAA,EAAiB,EAAA;AAAA,UACjB,YAAA,EAAc,EAAA;AAAA,UACd,WAAA,EAAa;AAAA,SACf;AAAA,QACA,KAAA,CAAM;AAAA,OACR;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAD,cAAA;AAAA,UAACI,iBAAA;AAAA,UAAA;AAAA,YACC,MAAA,EAAQ;AAAA,cACN,GAAA,EAAK;AAAA,aACP;AAAA,YACA,KAAA,EAAO,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA;AAAG;AAAA,SACjC;AAAA,wBACAJ,cAAA;AAAA,UAACK,gBAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,EAAE,QAAA,EAAU,EAAA,EAAI,UAAA,EAAY,KAAA,EAAM;AAAA,cAClC,KAAA,CAAM;AAAA,aACR;AAAA,YAEC,QAAA,EAAA,KAAA,CAAM,QAAA,KAAa,OAAA,GAChB,oBAAA,GACA,KAAA,CAAM,QAAA,KAAa,QAAA,GACnB,qBAAA,GACA,KAAA,CAAM,QAAA,KAAa,iBAAA,GACnB,qBAAA,GACA;AAAA;AAAA,SACN;AAAA,QACC,OAAA,oBAAWL,cAAA,CAACM,6BAAA,EAAA,EAAkB,KAAA,EAAO,MAAA,EAAQ;AAAA;AAAA;AAAA,KAGpD,CAAA,EACF,CAAA;AAEJ,CAAA;AAEA,IAAO,mBAAA,GAAQ","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
|
|
68
|
-
if (!
|
|
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
|
|
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
|
|
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(
|
|
108
|
-
|
|
109
|
-
return;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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)
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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))
|
|
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) => {
|
package/dist/index.mjs.map
CHANGED
|
@@ -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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pelican-identity/react-native",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.20",
|
|
4
4
|
"description": "React Native components for Pelican Identity authentication",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"react-native": "./src/index.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"react-native-get-random-values": "^1.7.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@pelican-identity/auth-core": "1.2.
|
|
25
|
+
"@pelican-identity/auth-core": "1.2.18"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.2.45",
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
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;;;CA6IvD,CAAC"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/utilities.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA,OAAO,gCAAgC,CAAC;AAExC,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGrE,eAAO,MAAM,WAAW,GAAU,8CAK/B;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;eA4BgD,MAAM;gBAAc,MAAM;EAC1E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,yDAMpC;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;YAmB6C,MAAM;WAAS,MAAM;EAClE,CAAC;AAMF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,KACV;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAuBrC,CAAC"}
|