@bloque/sdk-identity 0.0.6 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +336 -2
- package/dist/api-types.d.ts +21 -0
- package/dist/origins/client.d.ts +12 -0
- package/dist/origins/origin.d.ts +7 -0
- package/dist/origins/types.d.ts +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# @bloque/sdk-identity
|
|
2
2
|
|
|
3
|
-
Identity and
|
|
3
|
+
Identity, aliases, and OTP authentication API client for the Bloque SDK.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Aliases**: Get user identity information by email or phone
|
|
8
|
+
- **OTP Origins**: Send OTP codes via WhatsApp or Email
|
|
9
|
+
- **Custom Origins**: Support for custom authentication origins
|
|
10
|
+
- **TypeScript First**: Built with TypeScript for complete type safety
|
|
4
11
|
|
|
5
12
|
## Installation
|
|
6
13
|
|
|
@@ -27,11 +34,23 @@ const identity = new IdentityClient(httpClient);
|
|
|
27
34
|
const alias = await identity.aliases.get('user@example.com');
|
|
28
35
|
console.log('User URN:', alias.urn);
|
|
29
36
|
console.log('Alias status:', alias.status);
|
|
37
|
+
|
|
38
|
+
// Send OTP via WhatsApp
|
|
39
|
+
const otpWhatsApp = await identity.origins.whatsapp.assert('+1234567890');
|
|
40
|
+
console.log('OTP sent to:', otpWhatsApp.value.phone);
|
|
41
|
+
console.log('Expires at:', otpWhatsApp.value.expires_at);
|
|
42
|
+
|
|
43
|
+
// Send OTP via Email
|
|
44
|
+
const otpEmail = await identity.origins.email.assert('user@example.com');
|
|
45
|
+
console.log('OTP sent to:', otpEmail.value.email);
|
|
46
|
+
console.log('Attempts remaining:', otpEmail.params.attempts_remaining);
|
|
30
47
|
```
|
|
31
48
|
|
|
32
49
|
## API Reference
|
|
33
50
|
|
|
34
|
-
###
|
|
51
|
+
### Aliases
|
|
52
|
+
|
|
53
|
+
#### `aliases.get(alias)`
|
|
35
54
|
|
|
36
55
|
Retrieve alias information by the alias value (email or phone):
|
|
37
56
|
|
|
@@ -39,6 +58,9 @@ Retrieve alias information by the alias value (email or phone):
|
|
|
39
58
|
const alias = await identity.aliases.get('user@example.com');
|
|
40
59
|
```
|
|
41
60
|
|
|
61
|
+
**Parameters**:
|
|
62
|
+
- `alias` (string): Email address or phone number
|
|
63
|
+
|
|
42
64
|
**Response**:
|
|
43
65
|
|
|
44
66
|
```typescript
|
|
@@ -63,6 +85,76 @@ interface Alias {
|
|
|
63
85
|
}
|
|
64
86
|
```
|
|
65
87
|
|
|
88
|
+
### Origins
|
|
89
|
+
|
|
90
|
+
Origins provide OTP (One-Time Password) authentication flows for different channels.
|
|
91
|
+
|
|
92
|
+
#### `origins.whatsapp.assert(phone)`
|
|
93
|
+
|
|
94
|
+
Send an OTP code via WhatsApp to the specified phone number:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const otp = await identity.origins.whatsapp.assert('+1234567890');
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Parameters**:
|
|
101
|
+
- `phone` (string): Phone number in international format (e.g., '+1234567890')
|
|
102
|
+
|
|
103
|
+
**Response**:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
interface OTPAssertionWhatsApp {
|
|
107
|
+
type: 'OTP';
|
|
108
|
+
params: {
|
|
109
|
+
attempts_remaining: number; // Number of remaining OTP attempts
|
|
110
|
+
};
|
|
111
|
+
value: {
|
|
112
|
+
phone: string; // Phone number where OTP was sent
|
|
113
|
+
expires_at: number; // Unix timestamp when OTP expires
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### `origins.email.assert(email)`
|
|
119
|
+
|
|
120
|
+
Send an OTP code via Email to the specified email address:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const otp = await identity.origins.email.assert('user@example.com');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Parameters**:
|
|
127
|
+
- `email` (string): Email address
|
|
128
|
+
|
|
129
|
+
**Response**:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
interface OTPAssertionEmail {
|
|
133
|
+
type: 'OTP';
|
|
134
|
+
params: {
|
|
135
|
+
attempts_remaining: number; // Number of remaining OTP attempts
|
|
136
|
+
};
|
|
137
|
+
value: {
|
|
138
|
+
email: string; // Email address where OTP was sent
|
|
139
|
+
expires_at: number; // Unix timestamp when OTP expires
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### `origins.custom(origin)`
|
|
145
|
+
|
|
146
|
+
Create a custom origin client for custom authentication origins:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const customOrigin = identity.origins.custom('my-custom-origin');
|
|
150
|
+
const otp = await customOrigin.assert('identifier');
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Parameters**:
|
|
154
|
+
- `origin` (string): Custom origin identifier
|
|
155
|
+
|
|
156
|
+
**Returns**: `OriginClient<OTPAssertion>` instance with `assert()` method
|
|
157
|
+
|
|
66
158
|
## Examples
|
|
67
159
|
|
|
68
160
|
### Get Email Alias
|
|
@@ -92,6 +184,246 @@ try {
|
|
|
92
184
|
}
|
|
93
185
|
```
|
|
94
186
|
|
|
187
|
+
### Send OTP via WhatsApp
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { SDK } from '@bloque/sdk';
|
|
191
|
+
|
|
192
|
+
const bloque = new SDK({
|
|
193
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
194
|
+
mode: 'production',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const otp = await bloque.identity.origins.whatsapp.assert('+1234567890');
|
|
199
|
+
|
|
200
|
+
console.log('OTP sent to:', otp.value.phone);
|
|
201
|
+
console.log('Expires at:', new Date(otp.value.expires_at * 1000));
|
|
202
|
+
console.log('Attempts remaining:', otp.params.attempts_remaining);
|
|
203
|
+
|
|
204
|
+
// Now user can verify the OTP code they received
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('Failed to send OTP:', error);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Send OTP via Email
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { SDK } from '@bloque/sdk';
|
|
214
|
+
|
|
215
|
+
const bloque = new SDK({
|
|
216
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
217
|
+
mode: 'production',
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const otp = await bloque.identity.origins.email.assert('user@example.com');
|
|
222
|
+
|
|
223
|
+
console.log('OTP sent to:', otp.value.email);
|
|
224
|
+
console.log('Expires at:', new Date(otp.value.expires_at * 1000));
|
|
225
|
+
console.log('Attempts remaining:', otp.params.attempts_remaining);
|
|
226
|
+
|
|
227
|
+
// Now user can verify the OTP code they received
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('Failed to send OTP:', error);
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Complete OTP Flow Example
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { SDK } from '@bloque/sdk';
|
|
237
|
+
|
|
238
|
+
const bloque = new SDK({
|
|
239
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
240
|
+
mode: 'production',
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
async function authenticateUser(email: string) {
|
|
244
|
+
try {
|
|
245
|
+
// Step 1: Check if user exists
|
|
246
|
+
const alias = await bloque.identity.aliases.get(email);
|
|
247
|
+
|
|
248
|
+
if (alias.status !== 'active') {
|
|
249
|
+
throw new Error('User is not active');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Step 2: Send OTP
|
|
253
|
+
const otp = await bloque.identity.origins.email.assert(email);
|
|
254
|
+
|
|
255
|
+
console.log('OTP sent successfully to:', otp.value.email);
|
|
256
|
+
console.log('User has', otp.params.attempts_remaining, 'attempts remaining');
|
|
257
|
+
console.log('OTP expires at:', new Date(otp.value.expires_at * 1000));
|
|
258
|
+
|
|
259
|
+
// Step 3: User would now verify the OTP code
|
|
260
|
+
// (verification would be done through your app's verification endpoint)
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
userUrn: alias.urn,
|
|
264
|
+
otpSent: true,
|
|
265
|
+
expiresAt: otp.value.expires_at,
|
|
266
|
+
};
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error('Authentication failed:', error);
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Usage
|
|
274
|
+
await authenticateUser('user@example.com');
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Using Custom Origin
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
import { SDK } from '@bloque/sdk';
|
|
281
|
+
|
|
282
|
+
const bloque = new SDK({
|
|
283
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
284
|
+
mode: 'production',
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// Create a custom origin client
|
|
288
|
+
const customOrigin = bloque.identity.origins.custom('my-custom-sms-provider');
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const otp = await customOrigin.assert('+1234567890');
|
|
292
|
+
|
|
293
|
+
console.log('OTP sent via custom origin');
|
|
294
|
+
console.log('Attempts remaining:', otp.params.attempts_remaining);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error('Failed to send OTP via custom origin:', error);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Error Handling with Rate Limiting
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
import { SDK } from '@bloque/sdk';
|
|
304
|
+
|
|
305
|
+
const bloque = new SDK({
|
|
306
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
307
|
+
mode: 'production',
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
async function sendOTPWithRetry(phone: string, maxRetries = 3) {
|
|
311
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
312
|
+
try {
|
|
313
|
+
const otp = await bloque.identity.origins.whatsapp.assert(phone);
|
|
314
|
+
|
|
315
|
+
if (otp.params.attempts_remaining === 0) {
|
|
316
|
+
console.warn('No OTP attempts remaining!');
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
console.log('OTP sent successfully');
|
|
321
|
+
console.log('Attempts remaining:', otp.params.attempts_remaining);
|
|
322
|
+
|
|
323
|
+
return otp;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
console.error(`Attempt ${attempt} failed:`, error);
|
|
326
|
+
|
|
327
|
+
if (attempt === maxRetries) {
|
|
328
|
+
throw new Error('Max retries reached');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Wait before retrying
|
|
332
|
+
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
await sendOTPWithRetry('+1234567890');
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## TypeScript Support
|
|
341
|
+
|
|
342
|
+
This package is written in TypeScript and includes complete type definitions:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
import type {
|
|
346
|
+
Alias,
|
|
347
|
+
OTPAssertionEmail,
|
|
348
|
+
OTPAssertionWhatsApp,
|
|
349
|
+
OTPAssertion,
|
|
350
|
+
IdentityClient,
|
|
351
|
+
AliasesClient,
|
|
352
|
+
OriginsClient,
|
|
353
|
+
OriginClient,
|
|
354
|
+
} from '@bloque/sdk-identity';
|
|
355
|
+
|
|
356
|
+
// Type-safe alias retrieval
|
|
357
|
+
const alias: Alias = await identity.aliases.get('user@example.com');
|
|
358
|
+
|
|
359
|
+
// Type-safe OTP with WhatsApp
|
|
360
|
+
const whatsappOTP: OTPAssertionWhatsApp =
|
|
361
|
+
await identity.origins.whatsapp.assert('+1234567890');
|
|
362
|
+
|
|
363
|
+
// Type-safe OTP with Email
|
|
364
|
+
const emailOTP: OTPAssertionEmail =
|
|
365
|
+
await identity.origins.email.assert('user@example.com');
|
|
366
|
+
|
|
367
|
+
// Generic OTP type
|
|
368
|
+
const otp: OTPAssertion =
|
|
369
|
+
await identity.origins.email.assert('user@example.com');
|
|
370
|
+
|
|
371
|
+
// Custom origin client
|
|
372
|
+
const customOrigin: OriginClient<OTPAssertion> =
|
|
373
|
+
identity.origins.custom('my-origin');
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Use with Main SDK
|
|
377
|
+
|
|
378
|
+
When using through the main `@bloque/sdk` package:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import { SDK } from '@bloque/sdk';
|
|
382
|
+
|
|
383
|
+
const bloque = new SDK({
|
|
384
|
+
apiKey: process.env.BLOQUE_API_KEY!,
|
|
385
|
+
mode: 'production',
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// All identity features are available under bloque.identity
|
|
389
|
+
const alias = await bloque.identity.aliases.get('user@example.com');
|
|
390
|
+
const otp = await bloque.identity.origins.whatsapp.assert('+1234567890');
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## Key Features
|
|
394
|
+
|
|
395
|
+
### OTP Authentication Channels
|
|
396
|
+
|
|
397
|
+
- **WhatsApp**: Send OTP codes via WhatsApp messages
|
|
398
|
+
- **Email**: Send OTP codes via email
|
|
399
|
+
- **Custom Origins**: Integrate custom authentication providers
|
|
400
|
+
|
|
401
|
+
### Rate Limiting & Security
|
|
402
|
+
|
|
403
|
+
OTP assertions include built-in rate limiting:
|
|
404
|
+
- `attempts_remaining`: Track remaining OTP attempts
|
|
405
|
+
- `expires_at`: Unix timestamp for OTP expiration
|
|
406
|
+
- Automatic retry protection
|
|
407
|
+
|
|
408
|
+
### Alias Management
|
|
409
|
+
|
|
410
|
+
- Retrieve user information by email or phone
|
|
411
|
+
- Check user status (active, inactive, revoked)
|
|
412
|
+
- Support for primary and public aliases
|
|
413
|
+
- Rich metadata support
|
|
414
|
+
|
|
415
|
+
## Requirements
|
|
416
|
+
|
|
417
|
+
- Node.js 22.x or higher / Bun 1.x or higher
|
|
418
|
+
- TypeScript 5.x or higher (for TypeScript projects)
|
|
419
|
+
|
|
420
|
+
## Links
|
|
421
|
+
|
|
422
|
+
- [Homepage](https://www.bloque.app)
|
|
423
|
+
- [Main SDK Documentation](../sdk/README.md)
|
|
424
|
+
- [GitHub Repository](https://github.com/bloque-app/sdk)
|
|
425
|
+
- [Issue Tracker](https://github.com/bloque-app/sdk/issues)
|
|
426
|
+
|
|
95
427
|
## Development
|
|
96
428
|
|
|
97
429
|
```bash
|
|
@@ -111,3 +443,5 @@ bun run check
|
|
|
111
443
|
## License
|
|
112
444
|
|
|
113
445
|
[MIT](../../LICENSE)
|
|
446
|
+
|
|
447
|
+
Copyright (c) 2025-present Bloque Copilot Inc.
|
package/dist/api-types.d.ts
CHANGED
|
@@ -17,3 +17,24 @@ export type AliasResponse = {
|
|
|
17
17
|
created_at: string;
|
|
18
18
|
updated_at: string;
|
|
19
19
|
};
|
|
20
|
+
interface OTPBase {
|
|
21
|
+
type: 'OTP';
|
|
22
|
+
params: {
|
|
23
|
+
attempts_remaining: number;
|
|
24
|
+
};
|
|
25
|
+
value: {
|
|
26
|
+
expires_at: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface OTPAssertionEmail extends OTPBase {
|
|
30
|
+
value: OTPBase['value'] & {
|
|
31
|
+
email: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface OTPAssertionWhatsApp extends OTPBase {
|
|
35
|
+
value: OTPBase['value'] & {
|
|
36
|
+
phone: string;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export type OTPAssertion = OTPAssertionEmail | OTPAssertionWhatsApp;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HttpClient } from '@bloque/sdk-core';
|
|
2
|
+
import type { OTPAssertion, OTPAssertionEmail, OTPAssertionWhatsApp } from '../api-types';
|
|
3
|
+
import { OriginClient } from './origin';
|
|
4
|
+
import type { Alias } from './types';
|
|
5
|
+
export declare class OriginsClient {
|
|
6
|
+
readonly whatsapp: OriginClient<OTPAssertionWhatsApp>;
|
|
7
|
+
readonly email: OriginClient<OTPAssertionEmail>;
|
|
8
|
+
private readonly httpClient;
|
|
9
|
+
constructor(httpClient: HttpClient);
|
|
10
|
+
get(alias: string): Promise<Alias>;
|
|
11
|
+
custom(origin: string): OriginClient<OTPAssertion>;
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bloque/sdk-identity",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bloque",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"node": ">=22"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
|
-
"
|
|
37
|
+
"release": "bun publish",
|
|
38
38
|
"build": "rslib build",
|
|
39
39
|
"dev": "rslib build --watch",
|
|
40
40
|
"clean": "rm -rf node_modules && rm -rf dist",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"typecheck": "tsgo --noEmit"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@bloque/sdk-core": "0.0.
|
|
45
|
+
"@bloque/sdk-core": "0.0.11"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@rslib/core": "^0.18.4",
|