@pelican-identity/vanilla 1.0.4 → 1.0.6
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 +149 -258
- package/dist/index.min.js +136 -92
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +136 -92
- package/dist/index.mjs.map +1 -1
- package/dist/pelican.css +63 -28
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,319 +1,210 @@
|
|
|
1
|
-
# Pelican Identity
|
|
1
|
+
# Pelican Identity Vanilla SDK
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
👉 **Pelican Dashboard:** https://dash.pelicanidentity.com
|
|
5
|
-
|
|
6
|
-
---
|
|
3
|
+
The Vanilla SDK provides a framework-agnostic way to integrate Pelican authentication. It includes a high-level UI wrapper that mirrors the React experience and a low-level Core Engine for custom implementations.
|
|
7
4
|
|
|
8
5
|
## Installation
|
|
9
6
|
|
|
10
|
-
###
|
|
7
|
+
### 1. Via CDN (Easiest)
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
npm install @pelican-identity/react
|
|
14
|
-
```
|
|
9
|
+
Ideal for projects without a build step. Includes the UI and logic in a single file.
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
```html
|
|
12
|
+
<link
|
|
13
|
+
rel="stylesheet"
|
|
14
|
+
href="https://cdn.jsdelivr.net/npm/@pelican-identity/vanilla@1.0.4/dist/pelican.css"
|
|
15
|
+
/>
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
yarn add @pelican-identity/react
|
|
20
|
-
```
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/npm/@pelican-identity/vanilla@1.0.4/dist/index.min.js"></script>
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
<div id="pelican-auth-root"></div>
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
<script>
|
|
22
|
+
const auth = Pelican.createPelicanAuth("pelican-auth-root", {
|
|
23
|
+
publicKey: "your-business-public-key",
|
|
24
|
+
projectId: "your-project-id",
|
|
25
|
+
authType: "login",
|
|
26
|
+
onSuccess: (data) => console.log("Success:", data),
|
|
27
|
+
onError: (err) => console.error("Error:", err),
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
26
30
|
```
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## Requirements
|
|
31
|
-
|
|
32
|
-
- React **17, 18, or 19**
|
|
33
|
-
- A modern browser environment
|
|
34
|
-
- A Pelican project configured in the Pelican dashboard
|
|
35
|
-
|
|
36
|
-
> This SDK is **browser-only** and must be used in client-side React components.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Required Setup
|
|
41
|
-
|
|
42
|
-
### 1. Whitelist your domain in Pelican Dashboard
|
|
43
|
-
|
|
44
|
-
You must add your website’s domain (e.g. `example.com`, `app.example.com`, or `localhost`) to your project’s whitelist in the Pelican dashboard.
|
|
45
|
-
|
|
46
|
-
Pelican validates **explicit domain ownership** on every authentication attempt.
|
|
47
|
-
👉 **Pelican Dashboard:** https://dash.pelicanidentity.com
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
### 2. Client-side usage only (important)
|
|
32
|
+
### 2. Via NPM/PNPM
|
|
52
33
|
|
|
53
|
-
|
|
34
|
+
Ideal for modern web apps (Vue, Svelte, or Vanilla TS) using a bundler like Vite or Webpack.
|
|
54
35
|
|
|
55
|
-
|
|
36
|
+
```bash
|
|
37
|
+
npm install @pelican-identity/vanilla
|
|
56
38
|
|
|
57
|
-
```tsx
|
|
58
|
-
"use client";
|
|
59
39
|
```
|
|
60
40
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
onSuccess={(data) => {
|
|
77
|
-
console.log("Authentication successful:", data);
|
|
78
|
-
}}
|
|
79
|
-
onError={(error) => {
|
|
80
|
-
console.error("Authentication failed:", error);
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
41
|
+
```typescript
|
|
42
|
+
import { createPelicanAuth } from "@pelican-identity/vanilla";
|
|
43
|
+
import "@pelican-identity/vanilla/dist/pelican.css";
|
|
44
|
+
|
|
45
|
+
const cleanup = createPelicanAuth("container-id", {
|
|
46
|
+
publicKey: "...",
|
|
47
|
+
projectId: "...",
|
|
48
|
+
authType: "login",
|
|
49
|
+
onSuccess: (identity) => {
|
|
50
|
+
console.log(identity.user_id);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// To stop and cleanup the instance
|
|
55
|
+
// cleanup();
|
|
85
56
|
```
|
|
86
57
|
|
|
87
|
-
|
|
58
|
+
```
|
|
59
|
+
<script>
|
|
60
|
+
import { onMount } from 'svelte';
|
|
61
|
+
|
|
62
|
+
onMount(() => {
|
|
63
|
+
// Pelican is available globally because of the CDN <script> tag
|
|
64
|
+
const auth = window.Pelican.createPelicanAuth('pelican-container', {
|
|
65
|
+
publicKey: "your-key",
|
|
66
|
+
projectId: "your-id",
|
|
67
|
+
authType: "login",
|
|
68
|
+
onSuccess: (data) => console.log(data)
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Cleanup when component is destroyed
|
|
72
|
+
return () => auth();
|
|
73
|
+
});
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<div id="pelican-container"></div>
|
|
77
|
+
```
|
|
88
78
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
import {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
authType="login"
|
|
109
|
-
onSuccess={(data) => {
|
|
110
|
-
setUser(data);
|
|
111
|
-
setError(null);
|
|
112
|
-
}}
|
|
113
|
-
onError={(err) => {
|
|
114
|
-
setError(err.message);
|
|
115
|
-
setUser(null);
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
|
|
119
|
-
{user && <p>Authenticated successfully</p>}
|
|
120
|
-
{error && <p style={{ color: "red" }}>{error}</p>}
|
|
121
|
-
</div>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
79
|
+
```vue
|
|
80
|
+
<template>
|
|
81
|
+
<div id="pelican-container"></div>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup>
|
|
85
|
+
import { onMounted } from "vue";
|
|
86
|
+
|
|
87
|
+
onMounted(() => {
|
|
88
|
+
const auth = window.Pelican.createPelicanAuth("pelican-container", {
|
|
89
|
+
publicKey: "your-key",
|
|
90
|
+
projectId: "your-id",
|
|
91
|
+
authType: "login",
|
|
92
|
+
onSuccess: (data) => console.log(data),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return () => auth();
|
|
96
|
+
});
|
|
97
|
+
</script>
|
|
124
98
|
```
|
|
125
99
|
|
|
126
100
|
---
|
|
127
101
|
|
|
128
|
-
## API Reference
|
|
129
|
-
|
|
130
|
-
### `PelicanAuth`
|
|
131
|
-
|
|
132
|
-
Main authentication component.
|
|
133
|
-
|
|
134
|
-
#### Props
|
|
135
|
-
|
|
136
|
-
| Prop | Type | Required | Description |
|
|
137
|
-
| ----------------- | ------------------------------------------ | -------- | --------------------------------------------------- |
|
|
138
|
-
| `publicKey` | `string` | ✅ | Business public key from Pelican dashboard |
|
|
139
|
-
| `projectId` | `string` | ✅ | Project ID from Pelican dashboard |
|
|
140
|
-
| `authType` | `"signup" \| "login" \| "id-verification"` | ✅ | Authentication flow |
|
|
141
|
-
| `onSuccess` | `(data: IdentityResult) => void` | ✅ | Success callback containing authenticated user data |
|
|
142
|
-
| `onError` | `(error: Error) => void` | Optional | Error callback |
|
|
143
|
-
| `buttonComponent` | `ReactNode` | Optional | Custom trigger UI |
|
|
144
|
-
| `forceQRCode` | `boolean` | Optional | Always show QR code instead of deep link |
|
|
145
|
-
| `continuousMode` | `boolean` | Optional | Automatically restart auth after completion |
|
|
146
|
-
|
|
147
|
-
> If `publicKey` or `projectId` is invalid, Pelican will fail immediately.
|
|
148
|
-
|
|
149
|
-
## 👉 **Pelican Dashboard:** https://dash.pelicanidentity.com
|
|
150
|
-
|
|
151
|
-
## Authentication Flow
|
|
152
|
-
|
|
153
|
-
Pelican Web authentication works using:
|
|
102
|
+
## UI Wrapper API Reference (`createPelicanAuth`)
|
|
154
103
|
|
|
155
|
-
|
|
156
|
-
- **Deep links** (mobile browsers)
|
|
104
|
+
The `createPelicanAuth` function initializes the Pelican UI inside a target DOM element.
|
|
157
105
|
|
|
158
|
-
|
|
106
|
+
| Option | Type | Required | Description |
|
|
107
|
+
| ---------------- | ---------- | -------- | --------------------------------------------- |
|
|
108
|
+
| `publicKey` | `string` | ✅ | Business public key from Pelican dashboard |
|
|
109
|
+
| `projectId` | `string` | ✅ | Project ID from Pelican dashboard |
|
|
110
|
+
| `authType` | `AuthType` | ✅ | `"signup"`, `"login"`, or `"id-verification"` |
|
|
111
|
+
| `onSuccess` | `Function` | ✅ | Callback with `IdentityResult` |
|
|
112
|
+
| `onError` | `Function` | ❌ | Callback for errors |
|
|
113
|
+
| `onClose` | `Function` | ❌ | Callback when the user closes the modal |
|
|
114
|
+
| `continuousMode` | `boolean` | ❌ | Auto-restart auth after completion |
|
|
115
|
+
| `forceQRCode` | `boolean` | ❌ | Always show QR even on mobile |
|
|
116
|
+
| `buttonText` | `string` | ❌ | Custom text for the Pelican button |
|
|
159
117
|
|
|
160
118
|
---
|
|
161
119
|
|
|
162
|
-
##
|
|
120
|
+
## Low-Level Core Usage (Custom UI)
|
|
163
121
|
|
|
164
|
-
|
|
122
|
+
If you want to build your own UI from scratch, use the `@pelican-identity/auth-core` package directly. This provides the event-driven state machine without any HTML/CSS.
|
|
165
123
|
|
|
166
|
-
|
|
124
|
+
### Basic Implementation
|
|
167
125
|
|
|
168
|
-
|
|
126
|
+
```typescript
|
|
127
|
+
import { PelicanAuthentication } from "@pelican-identity/auth-core";
|
|
169
128
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
129
|
+
const pelican = new PelicanAuthentication({
|
|
130
|
+
publicKey: "your-key",
|
|
131
|
+
projectId: "your-id",
|
|
132
|
+
authType: "login",
|
|
133
|
+
});
|
|
173
134
|
|
|
174
|
-
|
|
135
|
+
// 1. Listen for the QR code
|
|
136
|
+
pelican.on("qr", (qrDataUrl) => {
|
|
137
|
+
document.getElementById("my-qr").src = qrDataUrl;
|
|
138
|
+
});
|
|
175
139
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
/** Deterministic unique user identifier specific to your business */
|
|
181
|
-
user_id: string;
|
|
140
|
+
// 2. Listen for Mobile Deep Links
|
|
141
|
+
pelican.on("deeplink", (url) => {
|
|
142
|
+
document.getElementById("mobile-link").href = url;
|
|
143
|
+
});
|
|
182
144
|
|
|
183
|
-
|
|
184
|
-
|
|
145
|
+
// 3. Track State Changes
|
|
146
|
+
pelican.on("state", (state) => {
|
|
147
|
+
console.log("Current state:", state); // 'initializing', 'paired', etc.
|
|
148
|
+
});
|
|
185
149
|
|
|
186
|
-
|
|
187
|
-
|
|
150
|
+
// 4. Handle Completion
|
|
151
|
+
pelican.on("success", (identity) => {
|
|
152
|
+
alert(`Welcome ${identity.user_id}`);
|
|
153
|
+
});
|
|
188
154
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
front_of_card?: string;
|
|
192
|
-
back_of_card?: string;
|
|
193
|
-
};
|
|
194
|
-
}
|
|
155
|
+
// Start the engine
|
|
156
|
+
pelican.start();
|
|
195
157
|
```
|
|
196
158
|
|
|
197
159
|
---
|
|
198
160
|
|
|
199
|
-
##
|
|
161
|
+
## Authentication Flow logic
|
|
200
162
|
|
|
201
|
-
|
|
202
|
-
- Unique **per business**, not global.
|
|
203
|
-
- Safe to store and use as your internal user reference.
|
|
204
|
-
- Does **not** expose personally identifiable information (PII).
|
|
163
|
+
The SDK manages the transition between Desktop and Mobile automatically:
|
|
205
164
|
|
|
206
|
-
|
|
165
|
+
1. **Desktop:** Emits a `qr` event containing a Base64 Data URL.
|
|
166
|
+
2. **Mobile:** Emits a `deeplink` event. Browsers should provide a "Open App" button using this URL.
|
|
167
|
+
3. **Paired:** Once the user scans/clicks, the state moves to `paired`.
|
|
168
|
+
4. **Success:** After biometric/PIN approval in the Pelican app, the `success` event fires with user data.
|
|
207
169
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
Returned when available and permitted by the authentication flow.
|
|
211
|
-
|
|
212
|
-
```ts
|
|
213
|
-
interface IUserData {
|
|
214
|
-
first_name?: string;
|
|
215
|
-
last_name?: string;
|
|
216
|
-
other_names?: string;
|
|
217
|
-
email?: IEmail;
|
|
218
|
-
phone?: IPhone;
|
|
219
|
-
dob?: string | Date;
|
|
220
|
-
gender?: "male" | "female" | "other";
|
|
221
|
-
country?: string;
|
|
222
|
-
state?: string;
|
|
223
|
-
city?: string;
|
|
224
|
-
address?: string;
|
|
225
|
-
occupation?: string;
|
|
226
|
-
company?: string;
|
|
227
|
-
website?: string;
|
|
228
|
-
}
|
|
229
|
-
```
|
|
170
|
+
---
|
|
230
171
|
|
|
231
|
-
|
|
172
|
+
## Identity Result Structure
|
|
232
173
|
|
|
233
|
-
|
|
174
|
+
Regardless of which integration path you choose, the successful authentication returns this object:
|
|
234
175
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
| "residence permit";
|
|
248
|
-
document_number?: string;
|
|
249
|
-
nationality?: string;
|
|
250
|
-
age?: number;
|
|
251
|
-
verified_at?: string | Date;
|
|
176
|
+
```typescript
|
|
177
|
+
interface IdentityResult {
|
|
178
|
+
user_id: string; // Unique business-scoped identifier
|
|
179
|
+
user_data?: {
|
|
180
|
+
first_name?: string;
|
|
181
|
+
email?: { value: string; verified: boolean };
|
|
182
|
+
phone?: { number: string; verified: boolean };
|
|
183
|
+
};
|
|
184
|
+
id_verification?: {
|
|
185
|
+
status: "Approved" | "Declined";
|
|
186
|
+
document_type: string;
|
|
187
|
+
};
|
|
252
188
|
}
|
|
253
189
|
```
|
|
254
190
|
|
|
255
191
|
---
|
|
256
192
|
|
|
257
|
-
## Authentication Flow Differences
|
|
258
|
-
|
|
259
|
-
| Auth Type | Returned Data |
|
|
260
|
-
| ----------------- | ------------------------------------------- |
|
|
261
|
-
| `signup` | `user_id`, basic `user_data` |
|
|
262
|
-
| `login` | `user_id` |
|
|
263
|
-
| `id-verification` | `user_id`, `id_verification`, document URLs |
|
|
264
|
-
|
|
265
|
-
Returned fields depend on:
|
|
266
|
-
|
|
267
|
-
- User consent
|
|
268
|
-
- Project configuration
|
|
269
|
-
- Regulatory requirements
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
193
|
## Troubleshooting
|
|
274
194
|
|
|
275
|
-
###
|
|
276
|
-
|
|
277
|
-
- Ensure the SDK is running client-side
|
|
278
|
-
- Confirm your domain is whitelisted
|
|
279
|
-
|
|
280
|
-
### Authentication never completes
|
|
195
|
+
### `crypto.randomUUID is not a function`
|
|
281
196
|
|
|
282
|
-
|
|
197
|
+
**Cause:** Browsers only allow the Crypto API in **Secure Contexts** (HTTPS or localhost).
|
|
198
|
+
**Fix:** Ensure you are serving your site over HTTPS or using `http://localhost`.
|
|
283
199
|
|
|
284
|
-
###
|
|
200
|
+
### QR Code not showing
|
|
285
201
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
### Billing issues, please contact this site owner
|
|
289
|
-
|
|
290
|
-
- Ensure your business wallet has sufficient balance
|
|
291
|
-
- Low balance alerts can be configured in the Pelican dashboard
|
|
292
|
-
👉 **Pelican Dashboard:** https://dash.pelicanidentity.com
|
|
293
|
-
|
|
294
|
-
---
|
|
202
|
+
**Cause:** The engine might be in `initializing` state or the domain isn't whitelisted.
|
|
203
|
+
**Fix:** Check your Pelican Dashboard and ensure your current domain (including port if applicable) is added to the project whitelist.
|
|
295
204
|
|
|
296
|
-
|
|
205
|
+
### Styles not applying
|
|
297
206
|
|
|
298
|
-
|
|
299
|
-
-
|
|
300
|
-
- Identifiers are scoped per business.
|
|
301
|
-
- Domains are validated on every authentication request.
|
|
207
|
+
**Cause:** The CSS file is missing.
|
|
208
|
+
**Fix:** If using NPM, ensure you import `@pelican-identity/vanilla/dist/pelican.css`. If using the CDN `.min.js` version with `injectStyle: true`, this should be automatic.
|
|
302
209
|
|
|
303
210
|
---
|
|
304
|
-
|
|
305
|
-
### Final note
|
|
306
|
-
|
|
307
|
-
Pelican deliberately separates:
|
|
308
|
-
|
|
309
|
-
- **Identity** (who the user is)
|
|
310
|
-
- **Authentication** (this session)
|
|
311
|
-
- **Verification** (confidence level)
|
|
312
|
-
|
|
313
|
-
This ensures your web application remains secure, flexible, and compliant.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## License
|
|
318
|
-
|
|
319
|
-
MIT
|