@auth-craft/backend-sdk 0.0.1 → 0.1.0
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 +35 -11
- package/dist/index.cjs +34 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +34 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
>
|
|
7
7
|
> - No stability guarantee
|
|
8
8
|
> - Breaking changes may happen at any time
|
|
9
|
-
> - No documentation
|
|
10
9
|
> - No support
|
|
11
10
|
>
|
|
12
11
|
> Use at your own risk.
|
|
@@ -30,8 +29,8 @@ const client = createInternalClient({
|
|
|
30
29
|
baseUrl: 'https://auth.example.com',
|
|
31
30
|
basePath: '/system',
|
|
32
31
|
jwt: {
|
|
33
|
-
strategy: '
|
|
34
|
-
|
|
32
|
+
strategy: 'eddsa',
|
|
33
|
+
privateKey: process.env.INTERNAL_JWT_PRIVATE_KEY!, // hex string (64 chars = 32 bytes)
|
|
35
34
|
issuer: 'tenant-provisioning-service',
|
|
36
35
|
},
|
|
37
36
|
});
|
|
@@ -71,16 +70,16 @@ Creates an `InternalClient` instance.
|
|
|
71
70
|
The SDK supports four JWT signing strategies via Web Crypto API:
|
|
72
71
|
|
|
73
72
|
```typescript
|
|
74
|
-
//
|
|
75
|
-
jwt: { strategy: '
|
|
73
|
+
// EdDSA / Ed25519 (recommended — compact, fast, edge-native)
|
|
74
|
+
jwt: { strategy: 'eddsa', privateKey: '...' } // hex string (64 chars) or Uint8Array (32 bytes)
|
|
76
75
|
|
|
77
|
-
//
|
|
78
|
-
jwt: { strategy: '
|
|
76
|
+
// HMAC-SHA256 (symmetric — simple for same-service)
|
|
77
|
+
jwt: { strategy: 'hmac', secret: '...' }
|
|
79
78
|
|
|
80
|
-
// RS256 / RSA-SHA256 (asymmetric)
|
|
79
|
+
// RS256 / RSA-SHA256 (asymmetric — enterprise standard)
|
|
81
80
|
jwt: { strategy: 'rs256', privateKey: '...' } // PEM string or JsonWebKey
|
|
82
81
|
|
|
83
|
-
// ES256 / ECDSA P-256 (asymmetric)
|
|
82
|
+
// ES256 / ECDSA P-256 (asymmetric — compact, widely supported)
|
|
84
83
|
jwt: { strategy: 'es256', privateKey: '...' } // PEM string or JsonWebKey
|
|
85
84
|
```
|
|
86
85
|
|
|
@@ -100,6 +99,8 @@ Tokens are auto-cached and refreshed 60 seconds before expiry.
|
|
|
100
99
|
|
|
101
100
|
Bootstrap tenant owner — assign owner role to a user for a new tenant. Typically called by tenant-provisioning service after creating a tenant.
|
|
102
101
|
|
|
102
|
+
**Route:** `POST /internal/tenant/bootstrap-owner`
|
|
103
|
+
|
|
103
104
|
```typescript
|
|
104
105
|
const result = await client.bootstrapTenantOwner({
|
|
105
106
|
tenantId: 'tenant-abc',
|
|
@@ -114,7 +115,9 @@ if (result.isOkWithData()) {
|
|
|
114
115
|
|
|
115
116
|
#### `getTenantProfile(request)`
|
|
116
117
|
|
|
117
|
-
Get per-tenant user profile
|
|
118
|
+
Get per-tenant user profile with membership and permissions. Allows services to read tenant profiles without user authentication.
|
|
119
|
+
|
|
120
|
+
**Route:** `POST /internal/tenant/profile`
|
|
118
121
|
|
|
119
122
|
```typescript
|
|
120
123
|
const result = await client.getTenantProfile({
|
|
@@ -124,7 +127,20 @@ const result = await client.getTenantProfile({
|
|
|
124
127
|
|
|
125
128
|
if (result.isOkWithData()) {
|
|
126
129
|
console.log(result.data);
|
|
127
|
-
// {
|
|
130
|
+
// {
|
|
131
|
+
// tenantId: string,
|
|
132
|
+
// userId: string,
|
|
133
|
+
// status: string, // 'invited' | 'active' | 'suspended' | 'removed'
|
|
134
|
+
// role?: string,
|
|
135
|
+
// permMask: number, // business permission bitmask (0 = none)
|
|
136
|
+
// authPermMask: number, // internal auth permission bitmask (0 = none)
|
|
137
|
+
// isOwner: boolean,
|
|
138
|
+
// displayName?: string, // from per-tenant profile (may not exist yet)
|
|
139
|
+
// avatarUrl?: string,
|
|
140
|
+
// title?: string,
|
|
141
|
+
// bio?: string,
|
|
142
|
+
// metadata?: Record<string, unknown>,
|
|
143
|
+
// }
|
|
128
144
|
}
|
|
129
145
|
```
|
|
130
146
|
|
|
@@ -179,6 +195,14 @@ export type {
|
|
|
179
195
|
export { InternalClient, sdkErrors } from '@auth-craft/backend-sdk';
|
|
180
196
|
```
|
|
181
197
|
|
|
198
|
+
## Changelog
|
|
199
|
+
|
|
200
|
+
### 0.1.0
|
|
201
|
+
|
|
202
|
+
- **Breaking:** `getTenantProfile` now uses `POST` instead of `GET` (body instead of query params)
|
|
203
|
+
- **Breaking:** `TenantProfileResponse` now includes membership fields (`status`, `permMask`, `authPermMask`, `isOwner`). `permMask` and `authPermMask` are always present (default `0`)
|
|
204
|
+
- **Fix:** EdDSA private key import — wrap 32-byte seed in PKCS8 envelope (RFC 8410) for Node.js 20+ compatibility
|
|
205
|
+
|
|
182
206
|
## License
|
|
183
207
|
|
|
184
208
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -36,11 +36,32 @@ async function importHmacSigningKey(secret) {
|
|
|
36
36
|
["sign"]
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
|
+
var ED25519_PKCS8_PREFIX = new Uint8Array([
|
|
40
|
+
48,
|
|
41
|
+
46,
|
|
42
|
+
2,
|
|
43
|
+
1,
|
|
44
|
+
0,
|
|
45
|
+
48,
|
|
46
|
+
5,
|
|
47
|
+
6,
|
|
48
|
+
3,
|
|
49
|
+
43,
|
|
50
|
+
101,
|
|
51
|
+
112,
|
|
52
|
+
4,
|
|
53
|
+
34,
|
|
54
|
+
4,
|
|
55
|
+
32
|
|
56
|
+
]);
|
|
39
57
|
async function importEdDSAPrivateKey(privateKey) {
|
|
40
58
|
const keyBytes = typeof privateKey === "string" ? hexToUint8Array(privateKey) : privateKey;
|
|
59
|
+
const pkcs8 = new Uint8Array(ED25519_PKCS8_PREFIX.length + keyBytes.length);
|
|
60
|
+
pkcs8.set(ED25519_PKCS8_PREFIX);
|
|
61
|
+
pkcs8.set(keyBytes, ED25519_PKCS8_PREFIX.length);
|
|
41
62
|
return crypto.subtle.importKey(
|
|
42
|
-
"
|
|
43
|
-
|
|
63
|
+
"pkcs8",
|
|
64
|
+
pkcs8.buffer,
|
|
44
65
|
{ name: "Ed25519" },
|
|
45
66
|
false,
|
|
46
67
|
["sign"]
|
|
@@ -225,12 +246,11 @@ var HttpClient = class {
|
|
|
225
246
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
226
247
|
let response;
|
|
227
248
|
try {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
});
|
|
249
|
+
const init = { method, headers, signal: controller.signal };
|
|
250
|
+
if (_optionalChain([options, 'optionalAccess', _2 => _2.body]) !== void 0) {
|
|
251
|
+
init.body = JSON.stringify(options.body);
|
|
252
|
+
}
|
|
253
|
+
response = await this.fetchFn(url, init);
|
|
234
254
|
} finally {
|
|
235
255
|
clearTimeout(timeoutId);
|
|
236
256
|
}
|
|
@@ -239,22 +259,20 @@ var HttpClient = class {
|
|
|
239
259
|
envelope = await response.json();
|
|
240
260
|
} catch (e) {
|
|
241
261
|
return _tsmicroresult.err.call(void 0,
|
|
242
|
-
sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` })
|
|
243
|
-
void 0,
|
|
244
|
-
response.status
|
|
262
|
+
sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` })
|
|
245
263
|
);
|
|
246
264
|
}
|
|
247
265
|
if (envelope.ok && envelope.data !== void 0) {
|
|
248
266
|
return _tsmicroresult.ok.call(void 0, envelope.data, envelope.meta);
|
|
249
267
|
}
|
|
250
268
|
const errors = _nullishCoalesce(envelope.errors, () => ( [{ code: "UNKNOWN_ERROR", message: `HTTP ${response.status}` }]));
|
|
251
|
-
return _tsmicroresult.err.call(void 0, errors, envelope.meta
|
|
269
|
+
return _tsmicroresult.err.call(void 0, errors, envelope.meta);
|
|
252
270
|
} catch (error) {
|
|
253
271
|
if (error instanceof Error && error.name === "AbortError") {
|
|
254
|
-
return _tsmicroresult.err.call(void 0, sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` })
|
|
272
|
+
return _tsmicroresult.err.call(void 0, sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` }));
|
|
255
273
|
}
|
|
256
274
|
const message = error instanceof Error ? error.message : String(error);
|
|
257
|
-
return _tsmicroresult.err.call(void 0, sdkErrors.NETWORK_ERROR({ message })
|
|
275
|
+
return _tsmicroresult.err.call(void 0, sdkErrors.NETWORK_ERROR({ message }));
|
|
258
276
|
}
|
|
259
277
|
}
|
|
260
278
|
buildUrl(path, query) {
|
|
@@ -293,14 +311,9 @@ var InternalClient = class {
|
|
|
293
311
|
*/
|
|
294
312
|
async getTenantProfile(request) {
|
|
295
313
|
return this.http.request(
|
|
296
|
-
"
|
|
314
|
+
"POST",
|
|
297
315
|
"/tenant/profile",
|
|
298
|
-
{
|
|
299
|
-
query: {
|
|
300
|
-
tenantId: request.tenantId,
|
|
301
|
-
userId: request.userId
|
|
302
|
-
}
|
|
303
|
-
}
|
|
316
|
+
{ body: request }
|
|
304
317
|
);
|
|
305
318
|
}
|
|
306
319
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["d:\\NodeJS_Projects\\auth-craft\\packages\\backend-sdk\\dist\\index.cjs"],"names":[],"mappings":"AAAA;AACA,gDAAyC;AACzC;AACA;AACA,SAAS,eAAe,CAAC,IAAI,EAAE;AAC/B,EAAE,IAAI,OAAO,EAAE,EAAE;AACjB,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACxC,IAAI,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1C,EAAE;AACF,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AAChF;AACA,SAAS,eAAe,CAAC,GAAG,EAAE;AAC9B,EAAE,MAAM,MAAM,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9C,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE;AAC1C,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;AACxD,EAAE;AACF,EAAE,OAAO,KAAK;AACd;AACA,SAAS,cAAc,CAAC,GAAG,EAAE;AAC7B,EAAE,MAAM,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AAC9H,EAAE,MAAM,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;AAC9B,EAAE,MAAM,MAAM,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;AAC7C,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,IAAI,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AACnC,EAAE;AACF,EAAE,OAAO,KAAK;AACd;AACA,MAAM,SAAS,oBAAoB,CAAC,MAAM,EAAE;AAC5C,EAAE,MAAM,QAAQ,EAAE,IAAI,WAAW,CAAC,CAAC;AACnC,EAAE,MAAM,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AACxC,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS;AAChC,IAAI,KAAK;AACT,IAAI,OAAO,CAAC,MAAM;AAClB,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC;AACrC,IAAI,KAAK;AACT,IAAI,CAAC,MAAM;AACX,EAAE,CAAC;AACH;AACA,MAAM,SAAS,qBAAqB,CAAC,UAAU,EAAE;AACjD,EAAE,MAAM,SAAS,EAAE,OAAO,WAAW,IAAI,SAAS,EAAE,eAAe,CAAC,UAAU,EAAE,EAAE,UAAU;AAC5F,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS;AAChC,IAAI,
|
|
1
|
+
{"version":3,"sources":["d:\\NodeJS_Projects\\auth-craft\\packages\\backend-sdk\\dist\\index.cjs"],"names":[],"mappings":"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AAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA","file":"D:\\NodeJS_Projects\\auth-craft\\packages\\backend-sdk\\dist\\index.cjs","sourcesContent":[null]}
|
package/dist/index.d.cts
CHANGED
|
@@ -69,8 +69,13 @@ interface BootstrapTenantOwnerResponse {
|
|
|
69
69
|
role: string;
|
|
70
70
|
}
|
|
71
71
|
interface TenantProfileResponse {
|
|
72
|
-
userId: string;
|
|
73
72
|
tenantId: string;
|
|
73
|
+
userId: string;
|
|
74
|
+
status: string;
|
|
75
|
+
role?: string;
|
|
76
|
+
permMask: number;
|
|
77
|
+
authPermMask: number;
|
|
78
|
+
isOwner: boolean;
|
|
74
79
|
displayName?: string;
|
|
75
80
|
avatarUrl?: string;
|
|
76
81
|
title?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -69,8 +69,13 @@ interface BootstrapTenantOwnerResponse {
|
|
|
69
69
|
role: string;
|
|
70
70
|
}
|
|
71
71
|
interface TenantProfileResponse {
|
|
72
|
-
userId: string;
|
|
73
72
|
tenantId: string;
|
|
73
|
+
userId: string;
|
|
74
|
+
status: string;
|
|
75
|
+
role?: string;
|
|
76
|
+
permMask: number;
|
|
77
|
+
authPermMask: number;
|
|
78
|
+
isOwner: boolean;
|
|
74
79
|
displayName?: string;
|
|
75
80
|
avatarUrl?: string;
|
|
76
81
|
title?: string;
|
package/dist/index.js
CHANGED
|
@@ -36,11 +36,32 @@ async function importHmacSigningKey(secret) {
|
|
|
36
36
|
["sign"]
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
|
+
var ED25519_PKCS8_PREFIX = new Uint8Array([
|
|
40
|
+
48,
|
|
41
|
+
46,
|
|
42
|
+
2,
|
|
43
|
+
1,
|
|
44
|
+
0,
|
|
45
|
+
48,
|
|
46
|
+
5,
|
|
47
|
+
6,
|
|
48
|
+
3,
|
|
49
|
+
43,
|
|
50
|
+
101,
|
|
51
|
+
112,
|
|
52
|
+
4,
|
|
53
|
+
34,
|
|
54
|
+
4,
|
|
55
|
+
32
|
|
56
|
+
]);
|
|
39
57
|
async function importEdDSAPrivateKey(privateKey) {
|
|
40
58
|
const keyBytes = typeof privateKey === "string" ? hexToUint8Array(privateKey) : privateKey;
|
|
59
|
+
const pkcs8 = new Uint8Array(ED25519_PKCS8_PREFIX.length + keyBytes.length);
|
|
60
|
+
pkcs8.set(ED25519_PKCS8_PREFIX);
|
|
61
|
+
pkcs8.set(keyBytes, ED25519_PKCS8_PREFIX.length);
|
|
41
62
|
return crypto.subtle.importKey(
|
|
42
|
-
"
|
|
43
|
-
|
|
63
|
+
"pkcs8",
|
|
64
|
+
pkcs8.buffer,
|
|
44
65
|
{ name: "Ed25519" },
|
|
45
66
|
false,
|
|
46
67
|
["sign"]
|
|
@@ -225,12 +246,11 @@ var HttpClient = class {
|
|
|
225
246
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
226
247
|
let response;
|
|
227
248
|
try {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
});
|
|
249
|
+
const init = { method, headers, signal: controller.signal };
|
|
250
|
+
if (options?.body !== void 0) {
|
|
251
|
+
init.body = JSON.stringify(options.body);
|
|
252
|
+
}
|
|
253
|
+
response = await this.fetchFn(url, init);
|
|
234
254
|
} finally {
|
|
235
255
|
clearTimeout(timeoutId);
|
|
236
256
|
}
|
|
@@ -239,22 +259,20 @@ var HttpClient = class {
|
|
|
239
259
|
envelope = await response.json();
|
|
240
260
|
} catch {
|
|
241
261
|
return err(
|
|
242
|
-
sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` })
|
|
243
|
-
void 0,
|
|
244
|
-
response.status
|
|
262
|
+
sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` })
|
|
245
263
|
);
|
|
246
264
|
}
|
|
247
265
|
if (envelope.ok && envelope.data !== void 0) {
|
|
248
266
|
return ok(envelope.data, envelope.meta);
|
|
249
267
|
}
|
|
250
268
|
const errors = envelope.errors ?? [{ code: "UNKNOWN_ERROR", message: `HTTP ${response.status}` }];
|
|
251
|
-
return err(errors, envelope.meta
|
|
269
|
+
return err(errors, envelope.meta);
|
|
252
270
|
} catch (error) {
|
|
253
271
|
if (error instanceof Error && error.name === "AbortError") {
|
|
254
|
-
return err(sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` })
|
|
272
|
+
return err(sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` }));
|
|
255
273
|
}
|
|
256
274
|
const message = error instanceof Error ? error.message : String(error);
|
|
257
|
-
return err(sdkErrors.NETWORK_ERROR({ message })
|
|
275
|
+
return err(sdkErrors.NETWORK_ERROR({ message }));
|
|
258
276
|
}
|
|
259
277
|
}
|
|
260
278
|
buildUrl(path, query) {
|
|
@@ -293,14 +311,9 @@ var InternalClient = class {
|
|
|
293
311
|
*/
|
|
294
312
|
async getTenantProfile(request) {
|
|
295
313
|
return this.http.request(
|
|
296
|
-
"
|
|
314
|
+
"POST",
|
|
297
315
|
"/tenant/profile",
|
|
298
|
-
{
|
|
299
|
-
query: {
|
|
300
|
-
tenantId: request.tenantId,
|
|
301
|
-
userId: request.userId
|
|
302
|
-
}
|
|
303
|
-
}
|
|
316
|
+
{ body: request }
|
|
304
317
|
);
|
|
305
318
|
}
|
|
306
319
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/http-client.ts","../src/jwt-signer.ts","../src/errors.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Low-level HTTP Client\r\n * Wraps fetch with JWT auth, timeout, and Result<T> mapping.\r\n */\r\n\r\nimport { ok, err } from 'ts-micro-result';\r\nimport type { Result } from 'ts-micro-result';\r\nimport type { InternalClientConfig, ApiResponseEnvelope } from './types';\r\nimport { JwtSigner } from './jwt-signer';\r\nimport { sdkErrors } from './errors';\r\n\r\ntype HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\r\n\r\nexport class HttpClient {\r\n private readonly signer: JwtSigner;\r\n private readonly baseUrl: string;\r\n private readonly basePath: string;\r\n private readonly fetchFn: typeof fetch;\r\n private readonly timeout: number;\r\n private readonly customHeaders: Record<string, string>;\r\n\r\n constructor(config: InternalClientConfig) {\r\n this.signer = new JwtSigner(config.jwt);\r\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\r\n this.basePath = config.basePath ?? '';\r\n this.fetchFn = config.fetchImpl ?? globalThis.fetch;\r\n this.timeout = config.timeout ?? 30000;\r\n this.customHeaders = config.headers ?? {};\r\n }\r\n\r\n async request<T>(\r\n method: HttpMethod,\r\n path: string,\r\n options?: {\r\n body?: unknown;\r\n query?: Record<string, string>;\r\n }\r\n ): Promise<Result<T>> {\r\n try {\r\n // Get service JWT\r\n let token: string;\r\n try {\r\n token = await this.signer.getToken();\r\n } catch (signError) {\r\n const message = signError instanceof Error ? signError.message : String(signError);\r\n return err(sdkErrors.JWT_SIGN_FAILED({ message }));\r\n }\r\n\r\n // Build URL\r\n const url = this.buildUrl(path, options?.query);\r\n\r\n // Build headers\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${token}`,\r\n ...this.customHeaders,\r\n };\r\n\r\n // Timeout\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n // Make request\r\n let response: Response;\r\n try {\r\n response = await this.fetchFn(url, {\r\n method,\r\n headers,\r\n body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,\r\n signal: controller.signal,\r\n });\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n\r\n // Parse response\r\n let envelope: ApiResponseEnvelope<T>;\r\n try {\r\n envelope = await response.json() as ApiResponseEnvelope<T>;\r\n } catch {\r\n return err(\r\n sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` }),\r\n undefined,\r\n response.status\r\n );\r\n }\r\n\r\n // Map to Result\r\n if (envelope.ok && envelope.data !== undefined) {\r\n return ok(envelope.data, envelope.meta);\r\n }\r\n\r\n const errors = envelope.errors ?? [{ code: 'UNKNOWN_ERROR', message: `HTTP ${response.status}` }];\r\n return err(errors, envelope.meta, response.status);\r\n\r\n } catch (error) {\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n return err(sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` }), undefined, 408);\r\n }\r\n\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(sdkErrors.NETWORK_ERROR({ message }), undefined, 0);\r\n }\r\n }\r\n\r\n private buildUrl(path: string, query?: Record<string, string>): string {\r\n let url = `${this.baseUrl}${this.basePath}/internal${path}`;\r\n\r\n if (query) {\r\n const entries = Object.entries(query).filter(([, v]) => v !== undefined);\r\n if (entries.length > 0) {\r\n const params = new URLSearchParams(entries);\r\n url += `?${params.toString()}`;\r\n }\r\n }\r\n\r\n return url;\r\n }\r\n}\r\n","/**\r\n * Service JWT Signer\r\n * Creates and auto-refreshes JWTs for service-to-service authentication.\r\n * Uses Web Crypto API for edge compatibility — zero dependencies.\r\n *\r\n * Reuses pattern from auth-http-core/middleware/internal-auth.ts\r\n */\r\n\r\nimport type { JwtConfig, JwtHmacConfig, JwtEddsaConfig, JwtRs256Config, JwtEs256Config } from './types';\r\n\r\n// ============================================================\r\n// Base64url helpers\r\n// ============================================================\r\n\r\nfunction base64urlEncode(data: Uint8Array): string {\r\n let binary = '';\r\n for (let i = 0; i < data.length; i++) {\r\n binary += String.fromCharCode(data[i]!);\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\r\n}\r\n\r\nfunction hexToUint8Array(hex: string): Uint8Array {\r\n const bytes = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < hex.length; i += 2) {\r\n bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\r\n }\r\n return bytes;\r\n}\r\n\r\nfunction parsePemToSpki(pem: string): Uint8Array {\r\n const pemBody = pem\r\n .replace(/-----BEGIN PRIVATE KEY-----/g, '')\r\n .replace(/-----END PRIVATE KEY-----/g, '')\r\n .replace(/\\s/g, '');\r\n\r\n const binary = atob(pemBody);\r\n const bytes = new Uint8Array(binary.length);\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i);\r\n }\r\n return bytes;\r\n}\r\n\r\n// ============================================================\r\n// Key import helpers (Web Crypto API)\r\n// ============================================================\r\n\r\nasync function importHmacSigningKey(secret: string): Promise<CryptoKey> {\r\n const encoder = new TextEncoder();\r\n const keyData = encoder.encode(secret);\r\n return crypto.subtle.importKey(\r\n 'raw',\r\n keyData.buffer as ArrayBuffer,\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\nasync function importEdDSAPrivateKey(privateKey: string | Uint8Array): Promise<CryptoKey> {\r\n const keyBytes = typeof privateKey === 'string'\r\n ? hexToUint8Array(privateKey)\r\n : privateKey;\r\n\r\n return crypto.subtle.importKey(\r\n 'raw',\r\n keyBytes.buffer as ArrayBuffer,\r\n { name: 'Ed25519' } as Algorithm,\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\nasync function importRsaPrivateKey(privateKey: string | JsonWebKey): Promise<CryptoKey> {\r\n if (typeof privateKey === 'object') {\r\n return crypto.subtle.importKey(\r\n 'jwk',\r\n privateKey,\r\n { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n }\r\n\r\n const pkcs8Bytes = parsePemToSpki(privateKey);\r\n return crypto.subtle.importKey(\r\n 'pkcs8',\r\n pkcs8Bytes.buffer as ArrayBuffer,\r\n { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\nasync function importEcdsaPrivateKey(privateKey: string | JsonWebKey): Promise<CryptoKey> {\r\n if (typeof privateKey === 'object') {\r\n return crypto.subtle.importKey(\r\n 'jwk',\r\n privateKey,\r\n { name: 'ECDSA', namedCurve: 'P-256' },\r\n false,\r\n ['sign']\r\n );\r\n }\r\n\r\n const pkcs8Bytes = parsePemToSpki(privateKey);\r\n return crypto.subtle.importKey(\r\n 'pkcs8',\r\n pkcs8Bytes.buffer as ArrayBuffer,\r\n { name: 'ECDSA', namedCurve: 'P-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\n// ============================================================\r\n// Sign key info\r\n// ============================================================\r\n\r\ninterface SignKeyInfo {\r\n key: CryptoKey;\r\n jwtAlgorithm: string;\r\n cryptoAlgorithm: AlgorithmIdentifier;\r\n}\r\n\r\nasync function resolveSignKey(config: JwtConfig): Promise<SignKeyInfo> {\r\n const strategy = config.strategy;\r\n\r\n switch (strategy) {\r\n case 'hmac': {\r\n const c = config as JwtHmacConfig;\r\n return {\r\n key: await importHmacSigningKey(c.secret),\r\n jwtAlgorithm: 'HS256',\r\n cryptoAlgorithm: 'HMAC',\r\n };\r\n }\r\n case 'eddsa': {\r\n const c = config as JwtEddsaConfig;\r\n return {\r\n key: await importEdDSAPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'EdDSA',\r\n cryptoAlgorithm: { name: 'Ed25519' } as Algorithm,\r\n };\r\n }\r\n case 'rs256': {\r\n const c = config as JwtRs256Config;\r\n return {\r\n key: await importRsaPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'RS256',\r\n cryptoAlgorithm: 'RSASSA-PKCS1-v1_5',\r\n };\r\n }\r\n case 'es256': {\r\n const c = config as JwtEs256Config;\r\n return {\r\n key: await importEcdsaPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'ES256',\r\n cryptoAlgorithm: { name: 'ECDSA', hash: 'SHA-256' } as EcdsaParams,\r\n };\r\n }\r\n }\r\n}\r\n\r\n// ============================================================\r\n// JWT Signer\r\n// ============================================================\r\n\r\n/** Minimum remaining TTL (seconds) before auto-refreshing the token */\r\nconst REFRESH_BUFFER_SECONDS = 60;\r\n\r\nexport class JwtSigner {\r\n private cachedKeyInfo: SignKeyInfo | null = null;\r\n private cachedToken: string | null = null;\r\n private cachedExp: number = 0;\r\n\r\n constructor(private readonly config: JwtConfig) {}\r\n\r\n /**\r\n * Get a valid service JWT token.\r\n * Automatically signs a new token when the current one is about to expire.\r\n */\r\n async getToken(): Promise<string> {\r\n const nowSeconds = Math.floor(Date.now() / 1000);\r\n\r\n // Return cached token if still valid (with buffer)\r\n if (this.cachedToken && nowSeconds < this.cachedExp - REFRESH_BUFFER_SECONDS) {\r\n return this.cachedToken;\r\n }\r\n\r\n // Sign new token\r\n return this.signNewToken();\r\n }\r\n\r\n private async signNewToken(): Promise<string> {\r\n const keyInfo = await this.getKeyInfo();\r\n const encoder = new TextEncoder();\r\n const expiresInSeconds = this.config.expiresInSeconds ?? 300;\r\n const nowSeconds = Math.floor(Date.now() / 1000);\r\n\r\n // Header\r\n const header = base64urlEncode(\r\n encoder.encode(JSON.stringify({ alg: keyInfo.jwtAlgorithm, typ: 'JWT' }))\r\n );\r\n\r\n // Payload\r\n const payload: Record<string, unknown> = {\r\n iat: nowSeconds,\r\n exp: nowSeconds + expiresInSeconds,\r\n };\r\n\r\n if (this.config.issuer !== undefined) {\r\n payload.iss = this.config.issuer;\r\n }\r\n if (this.config.audience !== undefined) {\r\n payload.aud = this.config.audience;\r\n }\r\n\r\n const payloadB64 = base64urlEncode(encoder.encode(JSON.stringify(payload)));\r\n\r\n // Sign\r\n const signData = encoder.encode(`${header}.${payloadB64}`);\r\n const signatureBytes = new Uint8Array(\r\n await crypto.subtle.sign(\r\n keyInfo.cryptoAlgorithm,\r\n keyInfo.key,\r\n signData.buffer as ArrayBuffer\r\n )\r\n );\r\n const signature = base64urlEncode(signatureBytes);\r\n\r\n const token = `${header}.${payloadB64}.${signature}`;\r\n\r\n // Cache\r\n this.cachedToken = token;\r\n this.cachedExp = nowSeconds + expiresInSeconds;\r\n\r\n return token;\r\n }\r\n\r\n private async getKeyInfo(): Promise<SignKeyInfo> {\r\n if (!this.cachedKeyInfo) {\r\n this.cachedKeyInfo = await resolveSignKey(this.config);\r\n }\r\n return this.cachedKeyInfo;\r\n }\r\n}\r\n","/**\r\n * Backend SDK Error Definitions\r\n */\r\n\r\nimport { defineError } from 'ts-micro-result';\r\n\r\nexport const sdkErrors = {\r\n NETWORK_ERROR: defineError('SDK_NETWORK_ERROR', 'Network request failed'),\r\n TIMEOUT: defineError('SDK_TIMEOUT', 'Request timed out'),\r\n INVALID_RESPONSE: defineError('SDK_INVALID_RESPONSE', 'Invalid response from auth service'),\r\n JWT_SIGN_FAILED: defineError('SDK_JWT_SIGN_FAILED', 'Failed to sign service JWT'),\r\n} as const;\r\n","/**\r\n * Internal Client\r\n * Type-safe client for auth service internal (service-to-service) API.\r\n */\r\n\r\nimport type { Result } from 'ts-micro-result';\r\nimport type {\r\n InternalClientConfig,\r\n BootstrapTenantOwnerRequest,\r\n BootstrapTenantOwnerResponse,\r\n GetTenantProfileRequest,\r\n TenantProfileResponse,\r\n} from './types';\r\nimport { HttpClient } from './http-client';\r\n\r\nexport class InternalClient {\r\n private readonly http: HttpClient;\r\n\r\n constructor(config: InternalClientConfig) {\r\n this.http = new HttpClient(config);\r\n }\r\n\r\n /**\r\n * Bootstrap tenant owner (assign owner role to a user for a new tenant).\r\n * Typically called by tenant-provisioning service after creating a tenant.\r\n */\r\n async bootstrapTenantOwner(\r\n request: BootstrapTenantOwnerRequest\r\n ): Promise<Result<BootstrapTenantOwnerResponse>> {\r\n return this.http.request<BootstrapTenantOwnerResponse>(\r\n 'POST',\r\n '/tenant/bootstrap-owner',\r\n { body: request }\r\n );\r\n }\r\n\r\n /**\r\n * Get per-tenant user profile (internal).\r\n * Allows services to read tenant profiles without user authentication.\r\n */\r\n async getTenantProfile(\r\n request: GetTenantProfileRequest\r\n ): Promise<Result<TenantProfileResponse>> {\r\n return this.http.request<TenantProfileResponse>(\r\n 'GET',\r\n '/tenant/profile',\r\n {\r\n query: {\r\n tenantId: request.tenantId,\r\n userId: request.userId,\r\n },\r\n }\r\n );\r\n }\r\n}\r\n","/**\r\n * @auth-craft/backend-sdk\r\n * Type-safe internal service SDK for Auth-Craft service-to-service calls.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createInternalClient } from '@auth-craft/backend-sdk';\r\n *\r\n * const client = createInternalClient({\r\n * baseUrl: 'https://auth.example.com',\r\n * basePath: '/system',\r\n * jwt: {\r\n * strategy: 'hmac',\r\n * secret: process.env.INTERNAL_JWT_SECRET!,\r\n * issuer: 'tenant-provisioning-service',\r\n * },\r\n * });\r\n *\r\n * const result = await client.bootstrapTenantOwner({ tenantId, userId });\r\n * ```\r\n */\r\n\r\nimport { InternalClient } from './client';\r\nimport type { InternalClientConfig } from './types';\r\n\r\n/**\r\n * Create an internal service client for Auth-Craft.\r\n *\r\n * The client auto-signs service JWTs and refreshes them before expiry.\r\n */\r\nexport function createInternalClient(config: InternalClientConfig): InternalClient {\r\n return new InternalClient(config);\r\n}\r\n\r\n// Explicit type exports\r\nexport type {\r\n InternalClientConfig,\r\n JwtConfig,\r\n JwtHmacConfig,\r\n JwtEddsaConfig,\r\n JwtRs256Config,\r\n JwtEs256Config,\r\n BootstrapTenantOwnerRequest,\r\n BootstrapTenantOwnerResponse,\r\n GetTenantProfileRequest,\r\n TenantProfileResponse,\r\n} from './types';\r\n\r\nexport { InternalClient } from './client';\r\nexport { sdkErrors } from './errors';\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/http-client.ts","../src/jwt-signer.ts","../src/errors.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Low-level HTTP Client\r\n * Wraps fetch with JWT auth, timeout, and Result<T> mapping.\r\n */\r\n\r\nimport { ok, err } from 'ts-micro-result';\r\nimport type { Result } from 'ts-micro-result';\r\nimport type { InternalClientConfig, ApiResponseEnvelope } from './types';\r\nimport { JwtSigner } from './jwt-signer';\r\nimport { sdkErrors } from './errors';\r\n\r\ntype HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';\r\n\r\nexport class HttpClient {\r\n private readonly signer: JwtSigner;\r\n private readonly baseUrl: string;\r\n private readonly basePath: string;\r\n private readonly fetchFn: typeof fetch;\r\n private readonly timeout: number;\r\n private readonly customHeaders: Record<string, string>;\r\n\r\n constructor(config: InternalClientConfig) {\r\n this.signer = new JwtSigner(config.jwt);\r\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\r\n this.basePath = config.basePath ?? '';\r\n this.fetchFn = config.fetchImpl ?? globalThis.fetch;\r\n this.timeout = config.timeout ?? 30000;\r\n this.customHeaders = config.headers ?? {};\r\n }\r\n\r\n async request<T>(\r\n method: HttpMethod,\r\n path: string,\r\n options?: {\r\n body?: unknown;\r\n query?: Record<string, string>;\r\n }\r\n ): Promise<Result<T>> {\r\n try {\r\n // Get service JWT\r\n let token: string;\r\n try {\r\n token = await this.signer.getToken();\r\n } catch (signError) {\r\n const message = signError instanceof Error ? signError.message : String(signError);\r\n return err(sdkErrors.JWT_SIGN_FAILED({ message }));\r\n }\r\n\r\n // Build URL\r\n const url = this.buildUrl(path, options?.query);\r\n\r\n // Build headers\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${token}`,\r\n ...this.customHeaders,\r\n };\r\n\r\n // Timeout\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n // Make request — use conditional init to satisfy exactOptionalPropertyTypes\r\n let response: Response;\r\n try {\r\n const init: RequestInit = { method, headers, signal: controller.signal };\r\n if (options?.body !== undefined) {\r\n init.body = JSON.stringify(options.body);\r\n }\r\n response = await this.fetchFn(url, init);\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n\r\n // Parse response\r\n let envelope: ApiResponseEnvelope<T>;\r\n try {\r\n envelope = await response.json() as ApiResponseEnvelope<T>;\r\n } catch {\r\n return err(\r\n sdkErrors.INVALID_RESPONSE({ message: `HTTP ${response.status}: non-JSON response` })\r\n );\r\n }\r\n\r\n // Map to Result\r\n if (envelope.ok && envelope.data !== undefined) {\r\n return ok(envelope.data, envelope.meta);\r\n }\r\n\r\n const errors = envelope.errors ?? [{ code: 'UNKNOWN_ERROR', message: `HTTP ${response.status}` }];\r\n return err(errors, envelope.meta);\r\n\r\n } catch (error) {\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n return err(sdkErrors.TIMEOUT({ message: `Request timed out after ${this.timeout}ms` }));\r\n }\r\n\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(sdkErrors.NETWORK_ERROR({ message }));\r\n }\r\n }\r\n\r\n private buildUrl(path: string, query?: Record<string, string>): string {\r\n let url = `${this.baseUrl}${this.basePath}/internal${path}`;\r\n\r\n if (query) {\r\n const entries = Object.entries(query).filter(([, v]) => v !== undefined);\r\n if (entries.length > 0) {\r\n const params = new URLSearchParams(entries);\r\n url += `?${params.toString()}`;\r\n }\r\n }\r\n\r\n return url;\r\n }\r\n}\r\n","/**\r\n * Service JWT Signer\r\n * Creates and auto-refreshes JWTs for service-to-service authentication.\r\n * Uses Web Crypto API for edge compatibility — zero dependencies.\r\n *\r\n * Reuses pattern from auth-http-core/middleware/internal-auth.ts\r\n */\r\n\r\nimport type { JwtConfig, JwtHmacConfig, JwtEddsaConfig, JwtRs256Config, JwtEs256Config } from './types';\r\n\r\n// ============================================================\r\n// Base64url helpers\r\n// ============================================================\r\n\r\nfunction base64urlEncode(data: Uint8Array): string {\r\n let binary = '';\r\n for (let i = 0; i < data.length; i++) {\r\n binary += String.fromCharCode(data[i]!);\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\r\n}\r\n\r\nfunction hexToUint8Array(hex: string): Uint8Array {\r\n const bytes = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < hex.length; i += 2) {\r\n bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\r\n }\r\n return bytes;\r\n}\r\n\r\nfunction parsePemToSpki(pem: string): Uint8Array {\r\n const pemBody = pem\r\n .replace(/-----BEGIN PRIVATE KEY-----/g, '')\r\n .replace(/-----END PRIVATE KEY-----/g, '')\r\n .replace(/\\s/g, '');\r\n\r\n const binary = atob(pemBody);\r\n const bytes = new Uint8Array(binary.length);\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i);\r\n }\r\n return bytes;\r\n}\r\n\r\n// ============================================================\r\n// Key import helpers (Web Crypto API)\r\n// ============================================================\r\n\r\nasync function importHmacSigningKey(secret: string): Promise<CryptoKey> {\r\n const encoder = new TextEncoder();\r\n const keyData = encoder.encode(secret);\r\n return crypto.subtle.importKey(\r\n 'raw',\r\n keyData.buffer as ArrayBuffer,\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\n/** PKCS8 ASN.1 prefix for Ed25519 private key (RFC 8410) */\r\nconst ED25519_PKCS8_PREFIX = new Uint8Array([\r\n 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,\r\n 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20,\r\n]);\r\n\r\nasync function importEdDSAPrivateKey(privateKey: string | Uint8Array): Promise<CryptoKey> {\r\n const keyBytes = typeof privateKey === 'string'\r\n ? hexToUint8Array(privateKey)\r\n : privateKey;\r\n\r\n // Wrap 32-byte seed in PKCS8 envelope — Node.js 20+ requires \"pkcs8\" format for signing keys\r\n const pkcs8 = new Uint8Array(ED25519_PKCS8_PREFIX.length + keyBytes.length);\r\n pkcs8.set(ED25519_PKCS8_PREFIX);\r\n pkcs8.set(keyBytes, ED25519_PKCS8_PREFIX.length);\r\n\r\n return crypto.subtle.importKey(\r\n 'pkcs8',\r\n pkcs8.buffer as ArrayBuffer,\r\n { name: 'Ed25519' } as Algorithm,\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\nasync function importRsaPrivateKey(privateKey: string | JsonWebKey): Promise<CryptoKey> {\r\n if (typeof privateKey === 'object') {\r\n return crypto.subtle.importKey(\r\n 'jwk',\r\n privateKey,\r\n { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n }\r\n\r\n const pkcs8Bytes = parsePemToSpki(privateKey);\r\n return crypto.subtle.importKey(\r\n 'pkcs8',\r\n pkcs8Bytes.buffer as ArrayBuffer,\r\n { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\nasync function importEcdsaPrivateKey(privateKey: string | JsonWebKey): Promise<CryptoKey> {\r\n if (typeof privateKey === 'object') {\r\n return crypto.subtle.importKey(\r\n 'jwk',\r\n privateKey,\r\n { name: 'ECDSA', namedCurve: 'P-256' },\r\n false,\r\n ['sign']\r\n );\r\n }\r\n\r\n const pkcs8Bytes = parsePemToSpki(privateKey);\r\n return crypto.subtle.importKey(\r\n 'pkcs8',\r\n pkcs8Bytes.buffer as ArrayBuffer,\r\n { name: 'ECDSA', namedCurve: 'P-256' },\r\n false,\r\n ['sign']\r\n );\r\n}\r\n\r\n// ============================================================\r\n// Sign key info\r\n// ============================================================\r\n\r\ninterface SignKeyInfo {\r\n key: CryptoKey;\r\n jwtAlgorithm: string;\r\n cryptoAlgorithm: AlgorithmIdentifier;\r\n}\r\n\r\nasync function resolveSignKey(config: JwtConfig): Promise<SignKeyInfo> {\r\n const strategy = config.strategy;\r\n\r\n switch (strategy) {\r\n case 'hmac': {\r\n const c = config as JwtHmacConfig;\r\n return {\r\n key: await importHmacSigningKey(c.secret),\r\n jwtAlgorithm: 'HS256',\r\n cryptoAlgorithm: 'HMAC',\r\n };\r\n }\r\n case 'eddsa': {\r\n const c = config as JwtEddsaConfig;\r\n return {\r\n key: await importEdDSAPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'EdDSA',\r\n cryptoAlgorithm: { name: 'Ed25519' } as Algorithm,\r\n };\r\n }\r\n case 'rs256': {\r\n const c = config as JwtRs256Config;\r\n return {\r\n key: await importRsaPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'RS256',\r\n cryptoAlgorithm: 'RSASSA-PKCS1-v1_5',\r\n };\r\n }\r\n case 'es256': {\r\n const c = config as JwtEs256Config;\r\n return {\r\n key: await importEcdsaPrivateKey(c.privateKey),\r\n jwtAlgorithm: 'ES256',\r\n cryptoAlgorithm: { name: 'ECDSA', hash: 'SHA-256' } as EcdsaParams,\r\n };\r\n }\r\n }\r\n}\r\n\r\n// ============================================================\r\n// JWT Signer\r\n// ============================================================\r\n\r\n/** Minimum remaining TTL (seconds) before auto-refreshing the token */\r\nconst REFRESH_BUFFER_SECONDS = 60;\r\n\r\nexport class JwtSigner {\r\n private cachedKeyInfo: SignKeyInfo | null = null;\r\n private cachedToken: string | null = null;\r\n private cachedExp: number = 0;\r\n\r\n constructor(private readonly config: JwtConfig) {}\r\n\r\n /**\r\n * Get a valid service JWT token.\r\n * Automatically signs a new token when the current one is about to expire.\r\n */\r\n async getToken(): Promise<string> {\r\n const nowSeconds = Math.floor(Date.now() / 1000);\r\n\r\n // Return cached token if still valid (with buffer)\r\n if (this.cachedToken && nowSeconds < this.cachedExp - REFRESH_BUFFER_SECONDS) {\r\n return this.cachedToken;\r\n }\r\n\r\n // Sign new token\r\n return this.signNewToken();\r\n }\r\n\r\n private async signNewToken(): Promise<string> {\r\n const keyInfo = await this.getKeyInfo();\r\n const encoder = new TextEncoder();\r\n const expiresInSeconds = this.config.expiresInSeconds ?? 300;\r\n const nowSeconds = Math.floor(Date.now() / 1000);\r\n\r\n // Header\r\n const header = base64urlEncode(\r\n encoder.encode(JSON.stringify({ alg: keyInfo.jwtAlgorithm, typ: 'JWT' }))\r\n );\r\n\r\n // Payload\r\n const payload: Record<string, unknown> = {\r\n iat: nowSeconds,\r\n exp: nowSeconds + expiresInSeconds,\r\n };\r\n\r\n if (this.config.issuer !== undefined) {\r\n payload.iss = this.config.issuer;\r\n }\r\n if (this.config.audience !== undefined) {\r\n payload.aud = this.config.audience;\r\n }\r\n\r\n const payloadB64 = base64urlEncode(encoder.encode(JSON.stringify(payload)));\r\n\r\n // Sign\r\n const signData = encoder.encode(`${header}.${payloadB64}`);\r\n const signatureBytes = new Uint8Array(\r\n await crypto.subtle.sign(\r\n keyInfo.cryptoAlgorithm,\r\n keyInfo.key,\r\n signData.buffer as ArrayBuffer\r\n )\r\n );\r\n const signature = base64urlEncode(signatureBytes);\r\n\r\n const token = `${header}.${payloadB64}.${signature}`;\r\n\r\n // Cache\r\n this.cachedToken = token;\r\n this.cachedExp = nowSeconds + expiresInSeconds;\r\n\r\n return token;\r\n }\r\n\r\n private async getKeyInfo(): Promise<SignKeyInfo> {\r\n if (!this.cachedKeyInfo) {\r\n this.cachedKeyInfo = await resolveSignKey(this.config);\r\n }\r\n return this.cachedKeyInfo;\r\n }\r\n}\r\n","/**\r\n * Backend SDK Error Definitions\r\n */\r\n\r\nimport { defineError } from 'ts-micro-result';\r\n\r\nexport const sdkErrors = {\r\n NETWORK_ERROR: defineError('SDK_NETWORK_ERROR', 'Network request failed'),\r\n TIMEOUT: defineError('SDK_TIMEOUT', 'Request timed out'),\r\n INVALID_RESPONSE: defineError('SDK_INVALID_RESPONSE', 'Invalid response from auth service'),\r\n JWT_SIGN_FAILED: defineError('SDK_JWT_SIGN_FAILED', 'Failed to sign service JWT'),\r\n} as const;\r\n","/**\r\n * Internal Client\r\n * Type-safe client for auth service internal (service-to-service) API.\r\n */\r\n\r\nimport type { Result } from 'ts-micro-result';\r\nimport type {\r\n InternalClientConfig,\r\n BootstrapTenantOwnerRequest,\r\n BootstrapTenantOwnerResponse,\r\n GetTenantProfileRequest,\r\n TenantProfileResponse,\r\n} from './types';\r\nimport { HttpClient } from './http-client';\r\n\r\nexport class InternalClient {\r\n private readonly http: HttpClient;\r\n\r\n constructor(config: InternalClientConfig) {\r\n this.http = new HttpClient(config);\r\n }\r\n\r\n /**\r\n * Bootstrap tenant owner (assign owner role to a user for a new tenant).\r\n * Typically called by tenant-provisioning service after creating a tenant.\r\n */\r\n async bootstrapTenantOwner(\r\n request: BootstrapTenantOwnerRequest\r\n ): Promise<Result<BootstrapTenantOwnerResponse>> {\r\n return this.http.request<BootstrapTenantOwnerResponse>(\r\n 'POST',\r\n '/tenant/bootstrap-owner',\r\n { body: request }\r\n );\r\n }\r\n\r\n /**\r\n * Get per-tenant user profile (internal).\r\n * Allows services to read tenant profiles without user authentication.\r\n */\r\n async getTenantProfile(\r\n request: GetTenantProfileRequest\r\n ): Promise<Result<TenantProfileResponse>> {\r\n return this.http.request<TenantProfileResponse>(\r\n 'POST',\r\n '/tenant/profile',\r\n { body: request }\r\n );\r\n }\r\n}\r\n","/**\r\n * @auth-craft/backend-sdk\r\n * Type-safe internal service SDK for Auth-Craft service-to-service calls.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createInternalClient } from '@auth-craft/backend-sdk';\r\n *\r\n * const client = createInternalClient({\r\n * baseUrl: 'https://auth.example.com',\r\n * basePath: '/system',\r\n * jwt: {\r\n * strategy: 'hmac',\r\n * secret: process.env.INTERNAL_JWT_SECRET!,\r\n * issuer: 'tenant-provisioning-service',\r\n * },\r\n * });\r\n *\r\n * const result = await client.bootstrapTenantOwner({ tenantId, userId });\r\n * ```\r\n */\r\n\r\nimport { InternalClient } from './client';\r\nimport type { InternalClientConfig } from './types';\r\n\r\n/**\r\n * Create an internal service client for Auth-Craft.\r\n *\r\n * The client auto-signs service JWTs and refreshes them before expiry.\r\n */\r\nexport function createInternalClient(config: InternalClientConfig): InternalClient {\r\n return new InternalClient(config);\r\n}\r\n\r\n// Explicit type exports\r\nexport type {\r\n InternalClientConfig,\r\n JwtConfig,\r\n JwtHmacConfig,\r\n JwtEddsaConfig,\r\n JwtRs256Config,\r\n JwtEs256Config,\r\n BootstrapTenantOwnerRequest,\r\n BootstrapTenantOwnerResponse,\r\n GetTenantProfileRequest,\r\n TenantProfileResponse,\r\n} from './types';\r\n\r\nexport { InternalClient } from './client';\r\nexport { sdkErrors } from './errors';\r\n"],"mappings":"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","names":[]}
|