@forestadmin/agent-bff 1.0.0 → 1.2.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.
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createSid = createSid;
7
+ exports.default = createInMemorySessionStore;
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const DEFAULT_AUTH_CODE_TTL_SECONDS = 5 * 60;
10
+ const DEFAULT_MAX_PENDING_CODES = 10000;
11
+ function createSid() {
12
+ return crypto_1.default.randomBytes(32).toString('base64url');
13
+ }
14
+ function createOpaqueToken() {
15
+ return crypto_1.default.randomBytes(32).toString('base64url');
16
+ }
17
+ function hashToken(token) {
18
+ return crypto_1.default.createHash('sha256').update(token).digest('base64url');
19
+ }
20
+ function createInMemorySessionStore({ cipher, now, sessionTtlSeconds, authCodeTtlSeconds = DEFAULT_AUTH_CODE_TTL_SECONDS, maxPendingCodes = DEFAULT_MAX_PENDING_CODES, }) {
21
+ const sessions = new Map();
22
+ const usedCodes = new Map();
23
+ const activeRefreshHashToSid = new Map();
24
+ const rotatedRefreshHashToSid = new Map();
25
+ const lastRotationBySid = new Map();
26
+ function forgetRefreshHashes(sid) {
27
+ for (const [hash, owner] of activeRefreshHashToSid) {
28
+ if (owner === sid)
29
+ activeRefreshHashToSid.delete(hash);
30
+ }
31
+ for (const [hash, owner] of rotatedRefreshHashToSid) {
32
+ if (owner === sid)
33
+ rotatedRefreshHashToSid.delete(hash);
34
+ }
35
+ lastRotationBySid.delete(sid);
36
+ }
37
+ function dropSession(sid) {
38
+ sessions.delete(sid);
39
+ forgetRefreshHashes(sid);
40
+ }
41
+ function purgeExpiredCodes() {
42
+ const current = now();
43
+ for (const [code, expiresAt] of usedCodes) {
44
+ if (current >= expiresAt)
45
+ usedCodes.delete(code);
46
+ }
47
+ }
48
+ function purgeExpiredSessions() {
49
+ const current = now();
50
+ for (const [sid, session] of sessions) {
51
+ if (current >= session.expiresAt)
52
+ dropSession(sid);
53
+ }
54
+ }
55
+ function liveSession(sid) {
56
+ const session = sessions.get(sid);
57
+ if (!session)
58
+ return undefined;
59
+ if (now() >= session.expiresAt) {
60
+ dropSession(sid);
61
+ return undefined;
62
+ }
63
+ return session;
64
+ }
65
+ return {
66
+ create(input) {
67
+ purgeExpiredSessions();
68
+ const sid = createSid();
69
+ const refreshToken = createOpaqueToken();
70
+ const refreshTokenHash = hashToken(refreshToken);
71
+ sessions.set(sid, {
72
+ saasAccessToken: input.saasAccessToken,
73
+ saasRefreshTokenBlob: cipher.encrypt(input.saasRefreshToken),
74
+ refreshTokenHash,
75
+ renderingId: input.renderingId,
76
+ userId: input.userId,
77
+ expiresAt: now() + sessionTtlSeconds * 1000,
78
+ });
79
+ activeRefreshHashToSid.set(refreshTokenHash, sid);
80
+ return { sid, refreshToken };
81
+ },
82
+ get(sid) {
83
+ const session = liveSession(sid);
84
+ return session ? { ...session } : undefined;
85
+ },
86
+ getSaasRefreshToken(sid) {
87
+ const session = liveSession(sid);
88
+ return session ? cipher.decrypt(session.saasRefreshTokenBlob) : undefined;
89
+ },
90
+ updateSaasTokens(sid, tokens) {
91
+ const session = liveSession(sid);
92
+ if (!session)
93
+ return;
94
+ session.saasAccessToken = tokens.saasAccessToken;
95
+ session.saasRefreshTokenBlob = cipher.encrypt(tokens.saasRefreshToken);
96
+ },
97
+ prepareRotation(presentedToken) {
98
+ const hash = hashToken(presentedToken);
99
+ const reusedSid = rotatedRefreshHashToSid.get(hash);
100
+ if (reusedSid !== undefined) {
101
+ const session = liveSession(reusedSid);
102
+ if (!session)
103
+ return { outcome: 'unknown' };
104
+ const lastRotation = lastRotationBySid.get(reusedSid);
105
+ if (lastRotation?.rotatedHash === hash) {
106
+ return {
107
+ outcome: 'replay',
108
+ sid: reusedSid,
109
+ renderingId: session.renderingId,
110
+ lastIssuedRefreshToken: cipher.decrypt(lastRotation.issuedRefreshBlob),
111
+ };
112
+ }
113
+ return { outcome: 'reuse', sid: reusedSid };
114
+ }
115
+ const sid = activeRefreshHashToSid.get(hash);
116
+ if (sid === undefined)
117
+ return { outcome: 'unknown' };
118
+ const session = liveSession(sid);
119
+ if (!session)
120
+ return { outcome: 'unknown' };
121
+ return {
122
+ outcome: 'ready',
123
+ sid,
124
+ renderingId: session.renderingId,
125
+ newRefreshToken: createOpaqueToken(),
126
+ };
127
+ },
128
+ commitRotation(presentedToken, newRefreshToken) {
129
+ const hash = hashToken(presentedToken);
130
+ const sid = activeRefreshHashToSid.get(hash);
131
+ if (sid === undefined)
132
+ return false;
133
+ const session = liveSession(sid);
134
+ if (!session)
135
+ return false;
136
+ const newHash = hashToken(newRefreshToken);
137
+ activeRefreshHashToSid.delete(hash);
138
+ rotatedRefreshHashToSid.set(hash, sid);
139
+ lastRotationBySid.set(sid, {
140
+ rotatedHash: hash,
141
+ issuedRefreshBlob: cipher.encrypt(newRefreshToken),
142
+ });
143
+ activeRefreshHashToSid.set(newHash, sid);
144
+ session.refreshTokenHash = newHash;
145
+ return true;
146
+ },
147
+ destroy(sid) {
148
+ dropSession(sid);
149
+ },
150
+ claimAuthorizationCode(code) {
151
+ purgeExpiredCodes();
152
+ if (usedCodes.has(code))
153
+ return false;
154
+ if (usedCodes.size >= maxPendingCodes)
155
+ return false;
156
+ usedCodes.set(code, now() + authCodeTtlSeconds * 1000);
157
+ return true;
158
+ },
159
+ releaseAuthorizationCode(code) {
160
+ usedCodes.delete(code);
161
+ },
162
+ pendingClaimCount() {
163
+ purgeExpiredCodes();
164
+ return usedCodes.size;
165
+ },
166
+ };
167
+ }
168
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbi1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vYXV0aC9zZXNzaW9uLXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBNERBLDhCQUVDO0FBVUQsNkNBMExDO0FBaFFELG9EQUE0QjtBQXVENUIsTUFBTSw2QkFBNkIsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQzdDLE1BQU0seUJBQXlCLEdBQUcsS0FBTSxDQUFDO0FBRXpDLFNBQWdCLFNBQVM7SUFDdkIsT0FBTyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDdEQsQ0FBQztBQUVELFNBQVMsaUJBQWlCO0lBQ3hCLE9BQU8sZ0JBQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFhO0lBQzlCLE9BQU8sZ0JBQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUN2RSxDQUFDO0FBRUQsU0FBd0IsMEJBQTBCLENBQUMsRUFDakQsTUFBTSxFQUNOLEdBQUcsRUFDSCxpQkFBaUIsRUFDakIsa0JBQWtCLEdBQUcsNkJBQTZCLEVBQ2xELGVBQWUsR0FBRyx5QkFBeUIsR0FDdkI7SUFDcEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQXlCLENBQUM7SUFDbEQsTUFBTSxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDNUMsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUN6RCxNQUFNLHVCQUF1QixHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQzFELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBRzlCLENB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
@@ -0,0 +1,11 @@
1
+ export interface EncryptedBlob {
2
+ iv: string;
3
+ authTag: string;
4
+ ciphertext: string;
5
+ }
6
+ export interface TokenCipher {
7
+ encrypt(plaintext: string): EncryptedBlob;
8
+ decrypt(blob: EncryptedBlob): string;
9
+ }
10
+ export default function createTokenCipher(base64Key: string): TokenCipher;
11
+ //# sourceMappingURL=token-cipher.d.ts.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createTokenCipher;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const ALGORITHM = 'aes-256-gcm';
9
+ const IV_BYTES = 12;
10
+ function bytes(value) {
11
+ return new Uint8Array(typeof value === 'string' ? Buffer.from(value, 'base64') : value);
12
+ }
13
+ function toBase64(value) {
14
+ return Buffer.from(value).toString('base64');
15
+ }
16
+ function createTokenCipher(base64Key) {
17
+ const key = bytes(base64Key);
18
+ return {
19
+ encrypt(plaintext) {
20
+ const iv = new Uint8Array(crypto_1.default.randomBytes(IV_BYTES));
21
+ const cipher = crypto_1.default.createCipheriv(ALGORITHM, key, iv);
22
+ const ciphertext = new Uint8Array(Buffer.concat([
23
+ new Uint8Array(cipher.update(plaintext, 'utf8')),
24
+ new Uint8Array(cipher.final()),
25
+ ]));
26
+ return {
27
+ iv: toBase64(iv),
28
+ authTag: toBase64(new Uint8Array(cipher.getAuthTag())),
29
+ ciphertext: toBase64(ciphertext),
30
+ };
31
+ },
32
+ decrypt({ iv, authTag, ciphertext }) {
33
+ const decipher = crypto_1.default.createDecipheriv(ALGORITHM, key, bytes(iv));
34
+ decipher.setAuthTag(bytes(authTag));
35
+ return Buffer.concat([
36
+ new Uint8Array(decipher.update(bytes(ciphertext))),
37
+ new Uint8Array(decipher.final()),
38
+ ]).toString('utf8');
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tY2lwaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29hdXRoL3Rva2VuLWNpcGhlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQXdCQSxvQ0E4QkM7QUF0REQsb0RBQTRCO0FBRTVCLE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQztBQUNoQyxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7QUFhcEIsU0FBUyxLQUFLLENBQUMsS0FBMEI7SUFDdkMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMxRixDQUFDO0FBRUQsU0FBUyxRQUFRLENBQUMsS0FBaUI7SUFDakMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUMvQyxDQUFDO0FBRUQsU0FBd0IsaUJBQWlCLENBQUMsU0FBaUI7SUFDekQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTdCLE9BQU87UUFDTCxPQUFPLENBQUMsU0FBUztZQUNmLE1BQU0sRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDLGdCQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDeEQsTUFBTSxNQUFNLEdBQUcsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN6RCxNQUFNLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FDL0IsTUFBTSxDQUFDLE1BQU0sQ0FBQztnQkFDWixJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDaEQsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQy9CLENBQUMsQ0FDSCxDQUFDO1lBRUYsT0FBTztnQkFDTCxFQUFFLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDaEIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztnQkFDdEQsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUM7YUFDakMsQ0FBQztRQUNKLENBQUM7UUFDRCxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRTtZQUNqQyxNQUFNLFFBQVEsR0FBRyxnQkFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDcEUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUVwQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ25CLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xELElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNqQyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestadmin/agent-bff",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "forest-bff": "dist/cli.js"
@@ -31,10 +31,14 @@
31
31
  "test": "jest"
32
32
  },
33
33
  "dependencies": {
34
+ "@forestadmin/forestadmin-client": "1.40.3",
35
+ "@koa/bodyparser": "^6.1.0",
36
+ "jsonwebtoken": "^9.0.3",
34
37
  "koa": "^3.0.1",
35
38
  "zod": "4.3.6"
36
39
  },
37
40
  "devDependencies": {
41
+ "@types/jsonwebtoken": "^9.0.1",
38
42
  "@types/koa": "^2.13.5",
39
43
  "@types/supertest": "^6.0.2",
40
44
  "supertest": "^7.1.3"