@leanmcp/auth 0.4.3 → 0.4.4-alpha.8.f4673cd
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/LICENSE +21 -21
- package/README.md +410 -396
- package/dist/{auth0-UTD4QBG6.mjs → auth0-DWCHZ7IN.mjs} +1 -1
- package/dist/{chunk-RGCCBQWG.mjs → chunk-MXTUNMHA.mjs} +4 -4
- package/dist/{chunk-P4HFKA5R.mjs → chunk-ZJYMG6ZM.mjs} +4 -4
- package/dist/{clerk-3SDKGD6C.mjs → clerk-YVTZMRLF.mjs} +1 -1
- package/dist/client/index.js +56 -56
- package/dist/client/index.mjs +53 -53
- package/dist/{cognito-QQT7LK2Y.mjs → cognito-XKPEG6UH.mjs} +1 -1
- package/dist/index.js +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{leanmcp-Y7TXNSTD.mjs → leanmcp-73RUGZ2B.mjs} +9 -9
- package/dist/proxy/index.js +36 -36
- package/dist/proxy/index.mjs +36 -36
- package/dist/server/index.js +69 -69
- package/dist/server/index.mjs +69 -69
- package/dist/storage/index.js +24 -24
- package/dist/storage/index.mjs +21 -21
- package/package.json +121 -121
package/dist/server/index.mjs
CHANGED
|
@@ -114,11 +114,11 @@ var DynamicClientRegistration = class {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
* Register a new OAuth client (stateless)
|
|
118
|
+
*
|
|
119
|
+
* @param request - Client registration request per RFC 7591
|
|
120
|
+
* @returns Client registration response with JWT credentials
|
|
121
|
+
*/
|
|
122
122
|
register(request) {
|
|
123
123
|
const now = Date.now();
|
|
124
124
|
const nowSeconds = Math.floor(now / 1e3);
|
|
@@ -160,12 +160,12 @@ var DynamicClientRegistration = class {
|
|
|
160
160
|
return response;
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
163
|
+
* Validate client credentials (stateless)
|
|
164
|
+
*
|
|
165
|
+
* @param clientId - Client ID (JWT with prefix)
|
|
166
|
+
* @param clientSecret - Client secret (optional for public clients)
|
|
167
|
+
* @returns Whether credentials are valid
|
|
168
|
+
*/
|
|
169
169
|
validate(clientId, clientSecret) {
|
|
170
170
|
try {
|
|
171
171
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -182,8 +182,8 @@ var DynamicClientRegistration = class {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
* Get a registered client by ID (stateless)
|
|
186
|
+
*/
|
|
187
187
|
getClient(clientId) {
|
|
188
188
|
try {
|
|
189
189
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -205,8 +205,8 @@ var DynamicClientRegistration = class {
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
* Validate redirect URI for a client
|
|
209
|
+
*/
|
|
210
210
|
validateRedirectUri(clientId, redirectUri) {
|
|
211
211
|
const client = this.getClient(clientId);
|
|
212
212
|
if (!client) return false;
|
|
@@ -214,29 +214,29 @@ var DynamicClientRegistration = class {
|
|
|
214
214
|
return client.redirect_uris.includes(redirectUri);
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
* Delete a client (no-op in stateless mode)
|
|
218
|
+
*
|
|
219
|
+
* In stateless mode, clients cannot be truly "deleted" because
|
|
220
|
+
* their credentials are self-contained. They will expire naturally
|
|
221
|
+
* or when the signing secret is rotated.
|
|
222
|
+
*/
|
|
223
223
|
delete(clientId) {
|
|
224
224
|
return this.getClient(clientId) !== void 0;
|
|
225
225
|
}
|
|
226
226
|
/**
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
* List all registered clients (not supported in stateless mode)
|
|
228
|
+
*/
|
|
229
229
|
listClients() {
|
|
230
230
|
throw new Error("listClients() is not supported in stateless DCR mode");
|
|
231
231
|
}
|
|
232
232
|
/**
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
* Clear all clients (no-op in stateless mode)
|
|
234
|
+
*/
|
|
235
235
|
clearAll() {
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
* Extract JWT from prefixed client_id
|
|
239
|
+
*/
|
|
240
240
|
extractJWT(clientId) {
|
|
241
241
|
if (!clientId.startsWith(this.options.clientIdPrefix)) {
|
|
242
242
|
return null;
|
|
@@ -244,11 +244,11 @@ var DynamicClientRegistration = class {
|
|
|
244
244
|
return clientId.slice(this.options.clientIdPrefix.length);
|
|
245
245
|
}
|
|
246
246
|
/**
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
247
|
+
* Derive client secret from client_id JWT
|
|
248
|
+
*
|
|
249
|
+
* Uses HMAC to create a deterministic secret that can be
|
|
250
|
+
* validated without storage.
|
|
251
|
+
*/
|
|
252
252
|
deriveClientSecret(clientIdJWT) {
|
|
253
253
|
const { createHmac: createHmac3 } = __require("crypto");
|
|
254
254
|
return createHmac3("sha256", this.options.signingSecret).update(clientIdJWT).digest("hex");
|
|
@@ -297,16 +297,16 @@ var OAuthAuthorizationServer = class {
|
|
|
297
297
|
});
|
|
298
298
|
}
|
|
299
299
|
/**
|
|
300
|
-
|
|
301
|
-
|
|
300
|
+
* Generate state parameter with HMAC signature
|
|
301
|
+
*/
|
|
302
302
|
generateState() {
|
|
303
303
|
const nonce = randomUUID2();
|
|
304
304
|
const signature = createHmac2("sha256", this.options.sessionSecret).update(nonce).digest("hex").substring(0, 8);
|
|
305
305
|
return `${nonce}.${signature}`;
|
|
306
306
|
}
|
|
307
307
|
/**
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
* Verify state parameter signature
|
|
309
|
+
*/
|
|
310
310
|
verifyState(state) {
|
|
311
311
|
const [nonce, signature] = state.split(".");
|
|
312
312
|
if (!nonce || !signature) return false;
|
|
@@ -314,14 +314,14 @@ var OAuthAuthorizationServer = class {
|
|
|
314
314
|
return signature === expectedSignature;
|
|
315
315
|
}
|
|
316
316
|
/**
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
* Generate an authorization code
|
|
318
|
+
*/
|
|
319
319
|
generateAuthCode() {
|
|
320
320
|
return randomBytes2(32).toString("hex");
|
|
321
321
|
}
|
|
322
322
|
/**
|
|
323
|
-
|
|
324
|
-
|
|
323
|
+
* Generate JWT access token with encrypted upstream credentials
|
|
324
|
+
*/
|
|
325
325
|
generateAccessToken(claims, upstreamToken) {
|
|
326
326
|
const now = Math.floor(Date.now() / 1e3);
|
|
327
327
|
const jwtSigningSecret = this.options.jwtSigningSecret || this.options.sessionSecret;
|
|
@@ -348,8 +348,8 @@ var OAuthAuthorizationServer = class {
|
|
|
348
348
|
return signJWT(payload, jwtSigningSecret);
|
|
349
349
|
}
|
|
350
350
|
/**
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
* Get authorization server metadata (RFC 8414)
|
|
352
|
+
*/
|
|
353
353
|
getMetadata() {
|
|
354
354
|
const issuer = this.options.issuer;
|
|
355
355
|
return {
|
|
@@ -376,8 +376,8 @@ var OAuthAuthorizationServer = class {
|
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
378
|
/**
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
* Get Express router with all OAuth endpoints
|
|
380
|
+
*/
|
|
381
381
|
getRouter() {
|
|
382
382
|
const router = express.Router();
|
|
383
383
|
router.get("/.well-known/oauth-authorization-server", (_req, res) => {
|
|
@@ -410,8 +410,8 @@ var OAuthAuthorizationServer = class {
|
|
|
410
410
|
return router;
|
|
411
411
|
}
|
|
412
412
|
/**
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
* Handle authorization request
|
|
414
|
+
*/
|
|
415
415
|
handleAuthorize(req, res) {
|
|
416
416
|
const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method, resource } = req.query;
|
|
417
417
|
if (response_type !== "code") {
|
|
@@ -480,8 +480,8 @@ var OAuthAuthorizationServer = class {
|
|
|
480
480
|
res.redirect(authUrl.toString());
|
|
481
481
|
}
|
|
482
482
|
/**
|
|
483
|
-
|
|
484
|
-
|
|
483
|
+
* Handle callback from upstream provider
|
|
484
|
+
*/
|
|
485
485
|
async handleCallback(req, res) {
|
|
486
486
|
const { code, state, error, error_description } = req.query;
|
|
487
487
|
if (error) {
|
|
@@ -533,7 +533,7 @@ var OAuthAuthorizationServer = class {
|
|
|
533
533
|
const tokenResponse = await fetch(upstream.tokenEndpoint, {
|
|
534
534
|
method: "POST",
|
|
535
535
|
headers: {
|
|
536
|
-
|
|
536
|
+
Accept: "application/json",
|
|
537
537
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
538
538
|
},
|
|
539
539
|
body: new URLSearchParams({
|
|
@@ -553,8 +553,8 @@ var OAuthAuthorizationServer = class {
|
|
|
553
553
|
if (upstream.userInfoEndpoint && upstreamTokens.access_token) {
|
|
554
554
|
const userInfoResponse = await fetch(upstream.userInfoEndpoint, {
|
|
555
555
|
headers: {
|
|
556
|
-
|
|
557
|
-
|
|
556
|
+
Authorization: `Bearer ${upstreamTokens.access_token}`,
|
|
557
|
+
Accept: "application/json"
|
|
558
558
|
}
|
|
559
559
|
});
|
|
560
560
|
if (userInfoResponse.ok) {
|
|
@@ -591,8 +591,8 @@ var OAuthAuthorizationServer = class {
|
|
|
591
591
|
}
|
|
592
592
|
}
|
|
593
593
|
/**
|
|
594
|
-
|
|
595
|
-
|
|
594
|
+
* Handle token request
|
|
595
|
+
*/
|
|
596
596
|
async handleToken(req, res) {
|
|
597
597
|
const { grant_type, code, redirect_uri, client_id, client_secret, code_verifier } = req.body;
|
|
598
598
|
let clientId = client_id;
|
|
@@ -638,8 +638,8 @@ var OAuthAuthorizationServer = class {
|
|
|
638
638
|
}
|
|
639
639
|
}
|
|
640
640
|
/**
|
|
641
|
-
|
|
642
|
-
|
|
641
|
+
* Handle authorization code grant
|
|
642
|
+
*/
|
|
643
643
|
async handleAuthCodeGrant(res, clientId, code, redirectUri, codeVerifier) {
|
|
644
644
|
if (!code) {
|
|
645
645
|
res.status(400).json({
|
|
@@ -742,11 +742,11 @@ var TokenVerifier = class {
|
|
|
742
742
|
};
|
|
743
743
|
}
|
|
744
744
|
/**
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
745
|
+
* Verify a JWT access token
|
|
746
|
+
*
|
|
747
|
+
* @param token - The JWT access token to verify
|
|
748
|
+
* @returns Verification result with claims and decrypted upstream token if valid
|
|
749
|
+
*/
|
|
750
750
|
async verify(token) {
|
|
751
751
|
if (!token) {
|
|
752
752
|
return {
|
|
@@ -809,13 +809,13 @@ var TokenVerifier = class {
|
|
|
809
809
|
}
|
|
810
810
|
}
|
|
811
811
|
/**
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
812
|
+
* Generate WWW-Authenticate header for 401 responses
|
|
813
|
+
*
|
|
814
|
+
* Per RFC 9728, this should include the resource_metadata URL
|
|
815
|
+
*
|
|
816
|
+
* @param options - Header options
|
|
817
|
+
* @returns WWW-Authenticate header value
|
|
818
|
+
*/
|
|
819
819
|
static getWWWAuthenticateHeader(options) {
|
|
820
820
|
const parts = [
|
|
821
821
|
`Bearer resource_metadata="${options.resourceMetadataUrl}"`
|
|
@@ -832,8 +832,8 @@ var TokenVerifier = class {
|
|
|
832
832
|
return parts.join(", ");
|
|
833
833
|
}
|
|
834
834
|
/**
|
|
835
|
-
|
|
836
|
-
|
|
835
|
+
* Check if token has required scopes
|
|
836
|
+
*/
|
|
837
837
|
hasScopes(claims, requiredScopes) {
|
|
838
838
|
if (requiredScopes.length === 0) return true;
|
|
839
839
|
const tokenScopes = typeof claims.scope === "string" ? claims.scope.split(" ") : claims.scope || [];
|
package/dist/storage/index.js
CHANGED
|
@@ -59,14 +59,14 @@ var MemoryStorage = class {
|
|
|
59
59
|
tokens = /* @__PURE__ */ new Map();
|
|
60
60
|
clients = /* @__PURE__ */ new Map();
|
|
61
61
|
/**
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
* Normalize server URL for consistent key lookup
|
|
63
|
+
*/
|
|
64
64
|
normalizeUrl(serverUrl) {
|
|
65
65
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
* Check if an entry is expired
|
|
69
|
+
*/
|
|
70
70
|
isExpired(entry) {
|
|
71
71
|
if (!entry) return true;
|
|
72
72
|
if (!entry.expiresAt) return false;
|
|
@@ -162,8 +162,8 @@ var FileStorage = class {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
* Expand ~ to home directory
|
|
166
|
+
*/
|
|
167
167
|
expandPath(filePath) {
|
|
168
168
|
if (filePath.startsWith("~")) {
|
|
169
169
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -172,14 +172,14 @@ var FileStorage = class {
|
|
|
172
172
|
return filePath;
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
* Normalize server URL for consistent key lookup
|
|
176
|
+
*/
|
|
177
177
|
normalizeUrl(serverUrl) {
|
|
178
178
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
* Encrypt data
|
|
182
|
+
*/
|
|
183
183
|
encrypt(data) {
|
|
184
184
|
if (!this.encryptionKey) return data;
|
|
185
185
|
const iv = (0, import_crypto.randomBytes)(16);
|
|
@@ -190,8 +190,8 @@ var FileStorage = class {
|
|
|
190
190
|
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`;
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
* Decrypt data
|
|
194
|
+
*/
|
|
195
195
|
decrypt(data) {
|
|
196
196
|
if (!this.encryptionKey) return data;
|
|
197
197
|
const [ivHex, authTagHex, encrypted] = data.split(":");
|
|
@@ -204,8 +204,8 @@ var FileStorage = class {
|
|
|
204
204
|
return decrypted;
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
* Read data from file
|
|
208
|
+
*/
|
|
209
209
|
async readFile() {
|
|
210
210
|
if (this.cache) return this.cache;
|
|
211
211
|
try {
|
|
@@ -225,8 +225,8 @@ var FileStorage = class {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
/**
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
229
|
+
*/
|
|
230
230
|
async writeFile(data) {
|
|
231
231
|
this.cache = data;
|
|
232
232
|
if (this.writePromise) {
|
|
@@ -361,8 +361,8 @@ var KeychainStorage = class {
|
|
|
361
361
|
this.serviceName = options.serviceName ?? SERVICE_NAME;
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
* Initialize keytar (lazy load)
|
|
365
|
+
*/
|
|
366
366
|
async init() {
|
|
367
367
|
if (this.keytar) return;
|
|
368
368
|
if (this.initPromise) {
|
|
@@ -379,20 +379,20 @@ var KeychainStorage = class {
|
|
|
379
379
|
await this.initPromise;
|
|
380
380
|
}
|
|
381
381
|
/**
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
* Normalize server URL for consistent key lookup
|
|
383
|
+
*/
|
|
384
384
|
normalizeUrl(serverUrl) {
|
|
385
385
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
386
386
|
}
|
|
387
387
|
/**
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
* Get account key for tokens
|
|
389
|
+
*/
|
|
390
390
|
getTokensAccount(serverUrl) {
|
|
391
391
|
return `tokens:${this.normalizeUrl(serverUrl)}`;
|
|
392
392
|
}
|
|
393
393
|
/**
|
|
394
|
-
|
|
395
|
-
|
|
394
|
+
* Get account key for client info
|
|
395
|
+
*/
|
|
396
396
|
getClientAccount(serverUrl) {
|
|
397
397
|
return `client:${this.normalizeUrl(serverUrl)}`;
|
|
398
398
|
}
|
package/dist/storage/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
MemoryStorage,
|
|
3
3
|
isTokenExpired,
|
|
4
4
|
withExpiresAt
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-MXTUNMHA.mjs";
|
|
6
6
|
import {
|
|
7
7
|
__name,
|
|
8
8
|
__require
|
|
@@ -36,8 +36,8 @@ var FileStorage = class {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
* Expand ~ to home directory
|
|
40
|
+
*/
|
|
41
41
|
expandPath(filePath) {
|
|
42
42
|
if (filePath.startsWith("~")) {
|
|
43
43
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -46,14 +46,14 @@ var FileStorage = class {
|
|
|
46
46
|
return filePath;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
* Normalize server URL for consistent key lookup
|
|
50
|
+
*/
|
|
51
51
|
normalizeUrl(serverUrl) {
|
|
52
52
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
* Encrypt data
|
|
56
|
+
*/
|
|
57
57
|
encrypt(data) {
|
|
58
58
|
if (!this.encryptionKey) return data;
|
|
59
59
|
const iv = randomBytes(16);
|
|
@@ -64,8 +64,8 @@ var FileStorage = class {
|
|
|
64
64
|
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
* Decrypt data
|
|
68
|
+
*/
|
|
69
69
|
decrypt(data) {
|
|
70
70
|
if (!this.encryptionKey) return data;
|
|
71
71
|
const [ivHex, authTagHex, encrypted] = data.split(":");
|
|
@@ -78,8 +78,8 @@ var FileStorage = class {
|
|
|
78
78
|
return decrypted;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
* Read data from file
|
|
82
|
+
*/
|
|
83
83
|
async readFile() {
|
|
84
84
|
if (this.cache) return this.cache;
|
|
85
85
|
try {
|
|
@@ -99,8 +99,8 @@ var FileStorage = class {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
103
|
+
*/
|
|
104
104
|
async writeFile(data) {
|
|
105
105
|
this.cache = data;
|
|
106
106
|
if (this.writePromise) {
|
|
@@ -235,8 +235,8 @@ var KeychainStorage = class {
|
|
|
235
235
|
this.serviceName = options.serviceName ?? SERVICE_NAME;
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
* Initialize keytar (lazy load)
|
|
239
|
+
*/
|
|
240
240
|
async init() {
|
|
241
241
|
if (this.keytar) return;
|
|
242
242
|
if (this.initPromise) {
|
|
@@ -253,20 +253,20 @@ var KeychainStorage = class {
|
|
|
253
253
|
await this.initPromise;
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
* Normalize server URL for consistent key lookup
|
|
257
|
+
*/
|
|
258
258
|
normalizeUrl(serverUrl) {
|
|
259
259
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
* Get account key for tokens
|
|
263
|
+
*/
|
|
264
264
|
getTokensAccount(serverUrl) {
|
|
265
265
|
return `tokens:${this.normalizeUrl(serverUrl)}`;
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
* Get account key for client info
|
|
269
|
+
*/
|
|
270
270
|
getClientAccount(serverUrl) {
|
|
271
271
|
return `client:${this.normalizeUrl(serverUrl)}`;
|
|
272
272
|
}
|