@anysoftinc/anydb-sdk 0.4.0 → 0.5.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 +30 -0
- package/dist/auth.d.ts +28 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +52 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -214,6 +214,36 @@ export default NextAuth({
|
|
|
214
214
|
});
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
## Auth Helpers (Server-side)
|
|
218
|
+
|
|
219
|
+
Issue AnyDB-compatible HS256 tokens and normalize subjects consistently across apps:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { createServiceTokenProvider, signFromSessionClaims } from "@anysoftinc/anydb-sdk/auth";
|
|
223
|
+
|
|
224
|
+
// 1) Service token provider (e.g., for adapters/bootstrap)
|
|
225
|
+
const getServiceToken = createServiceTokenProvider({
|
|
226
|
+
secret: process.env.JWT_SECRET!,
|
|
227
|
+
storageAlias: "dev",
|
|
228
|
+
dbName: "app",
|
|
229
|
+
iss: "my-app-service",
|
|
230
|
+
ttlSeconds: 3600,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Use with DatomicClient
|
|
234
|
+
// new DatomicClient({ baseUrl, getAuthToken: getServiceToken })
|
|
235
|
+
|
|
236
|
+
// 2) Per-user token from NextAuth claims (re-signs JWS for AnyDB)
|
|
237
|
+
const token = signFromSessionClaims({
|
|
238
|
+
claims: nextAuthClaims, // from next-auth/jwt getToken()
|
|
239
|
+
secret: process.env.JWT_SECRET!,
|
|
240
|
+
storageAlias: "dev",
|
|
241
|
+
dbName: "app",
|
|
242
|
+
iss: "my-app-auth",
|
|
243
|
+
ttlSeconds: 900,
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
217
247
|
## Error Handling
|
|
218
248
|
|
|
219
249
|
The SDK provides detailed error information:
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface SignAnyDBTokenOptions {
|
|
2
|
+
secret: string;
|
|
3
|
+
sub: string;
|
|
4
|
+
aud: string;
|
|
5
|
+
iss?: string;
|
|
6
|
+
ttlSeconds?: number;
|
|
7
|
+
iat?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function signAnyDBToken(opts: SignAnyDBTokenOptions): string;
|
|
10
|
+
export interface ServiceTokenProviderOptions {
|
|
11
|
+
secret: string;
|
|
12
|
+
storageAlias: string;
|
|
13
|
+
dbName: string;
|
|
14
|
+
iss?: string;
|
|
15
|
+
ttlSeconds?: number;
|
|
16
|
+
sub?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function createServiceTokenProvider(opts: ServiceTokenProviderOptions): () => string;
|
|
19
|
+
export interface SignFromSessionClaimsOptions {
|
|
20
|
+
claims: Record<string, any>;
|
|
21
|
+
secret: string;
|
|
22
|
+
storageAlias: string;
|
|
23
|
+
dbName: string;
|
|
24
|
+
iss?: string;
|
|
25
|
+
ttlSeconds?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function signFromSessionClaims(opts: SignFromSessionClaimsOptions): string;
|
|
28
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAgBlE;AAKD,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,2BAA2B,GAChC,MAAM,MAAM,CAQd;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,4BAA4B,GACjC,MAAM,CAUR"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Auth utilities for issuing AnyDB-compatible JWS tokens and normalizing subjects
|
|
2
|
+
// Server-only: depends on Node's crypto for HMAC-SHA256
|
|
3
|
+
import { createHmac } from "crypto";
|
|
4
|
+
function base64url(input) {
|
|
5
|
+
const buf = Buffer.isBuffer(input) ? input : Buffer.from(input);
|
|
6
|
+
return buf
|
|
7
|
+
.toString("base64")
|
|
8
|
+
.replace(/=/g, "")
|
|
9
|
+
.replace(/\+/g, "-")
|
|
10
|
+
.replace(/\//g, "_");
|
|
11
|
+
}
|
|
12
|
+
function hmacSha256(data, secret) {
|
|
13
|
+
return createHmac("sha256", secret).update(data).digest();
|
|
14
|
+
}
|
|
15
|
+
function nowSeconds() {
|
|
16
|
+
return Math.floor(Date.now() / 1000);
|
|
17
|
+
}
|
|
18
|
+
export function signAnyDBToken(opts) {
|
|
19
|
+
const iat = opts.iat ?? nowSeconds();
|
|
20
|
+
const exp = iat + (opts.ttlSeconds ?? 15 * 60);
|
|
21
|
+
const header = { alg: "HS256", typ: "JWT" };
|
|
22
|
+
const payload = {
|
|
23
|
+
sub: opts.sub,
|
|
24
|
+
aud: opts.aud,
|
|
25
|
+
iss: opts.iss || "anydb-sdk",
|
|
26
|
+
iat,
|
|
27
|
+
exp,
|
|
28
|
+
};
|
|
29
|
+
const hB64 = base64url(JSON.stringify(header));
|
|
30
|
+
const pB64 = base64url(JSON.stringify(payload));
|
|
31
|
+
const signingInput = `${hB64}.${pB64}`;
|
|
32
|
+
const sig = base64url(hmacSha256(signingInput, opts.secret));
|
|
33
|
+
return `${signingInput}.${sig}`;
|
|
34
|
+
}
|
|
35
|
+
export function createServiceTokenProvider(opts) {
|
|
36
|
+
const iss = opts.iss || "anydb-sdk-service";
|
|
37
|
+
const ttl = opts.ttlSeconds ?? 60 * 60;
|
|
38
|
+
const aud = `${opts.storageAlias}/${opts.dbName}`;
|
|
39
|
+
const sub = opts.sub || "[:db/ident :anydb.system.v1/subject]";
|
|
40
|
+
return () => signAnyDBToken({ secret: opts.secret, sub, aud, iss, ttlSeconds: ttl });
|
|
41
|
+
}
|
|
42
|
+
export function signFromSessionClaims(opts) {
|
|
43
|
+
const iss = opts.iss || "anydb-sdk-auth";
|
|
44
|
+
const ttl = opts.ttlSeconds ?? 15 * 60;
|
|
45
|
+
const aud = `${opts.storageAlias}/${opts.dbName}`;
|
|
46
|
+
const rawSub = opts.claims?.sub;
|
|
47
|
+
if (typeof rawSub !== "string" || !rawSub.trim()) {
|
|
48
|
+
throw new Error("Invalid session: missing or invalid 'sub' in claims");
|
|
49
|
+
}
|
|
50
|
+
const sub = rawSub;
|
|
51
|
+
return signAnyDBToken({ secret: opts.secret, sub, aud, iss, ttlSeconds: ttl });
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anysoftinc/anydb-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "AnyDB TypeScript SDK for querying and transacting with Datomic databases",
|
|
5
5
|
"main": "dist/client.js",
|
|
6
6
|
"types": "dist/client.d.ts",
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
"require": "./dist/client.js",
|
|
16
16
|
"types": "./dist/client.d.ts"
|
|
17
17
|
},
|
|
18
|
+
"./auth": {
|
|
19
|
+
"import": "./dist/auth.js",
|
|
20
|
+
"require": "./dist/auth.js",
|
|
21
|
+
"types": "./dist/auth.d.ts"
|
|
22
|
+
},
|
|
18
23
|
"./nextauth-adapter": {
|
|
19
24
|
"import": "./dist/nextauth-adapter.js",
|
|
20
25
|
"require": "./dist/nextauth-adapter.js",
|