@fluidframework/tool-utils 2.103.0 → 2.110.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/CHANGELOG.md +4 -0
- package/dist/odspTokenManager.d.ts +4 -9
- package/dist/odspTokenManager.d.ts.map +1 -1
- package/dist/odspTokenManager.js +12 -44
- package/dist/odspTokenManager.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/odspTokenManager.d.ts +4 -9
- package/lib/odspTokenManager.d.ts.map +1 -1
- package/lib/odspTokenManager.js +12 -44
- package/lib/odspTokenManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +13 -9
- package/src/odspTokenManager.ts +13 -83
- package/src/packageVersion.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,15 +11,11 @@ export declare const getMicrosoftConfiguration: () => IPublicClientConfig;
|
|
|
11
11
|
/**
|
|
12
12
|
* @internal
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
15
|
-
type: "password";
|
|
16
|
-
username: string;
|
|
17
|
-
password: string;
|
|
18
|
-
} | {
|
|
14
|
+
export interface LoginCredentials {
|
|
19
15
|
type: "fic";
|
|
20
16
|
username: string;
|
|
21
17
|
fetchToken(scopeEndpoint: "push" | "storage"): Promise<string>;
|
|
22
|
-
}
|
|
18
|
+
}
|
|
23
19
|
/**
|
|
24
20
|
* @internal
|
|
25
21
|
*/
|
|
@@ -38,13 +34,12 @@ export declare class OdspTokenManager {
|
|
|
38
34
|
constructor(tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> | undefined);
|
|
39
35
|
updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens): Promise<void>;
|
|
40
36
|
private updateTokensCacheWithoutLock;
|
|
41
|
-
getOdspTokens(
|
|
42
|
-
getPushTokens(
|
|
37
|
+
getOdspTokens(credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
|
|
38
|
+
getPushTokens(credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
|
|
43
39
|
private getTokenFromCache;
|
|
44
40
|
private static getCacheKey;
|
|
45
41
|
private getTokens;
|
|
46
42
|
private getTokensCore;
|
|
47
|
-
private acquireTokensWithPassword;
|
|
48
43
|
private ficTokenToIOdspTokens;
|
|
49
44
|
private jwtToIOdspTokens;
|
|
50
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,mBAAmB,EACnB,WAAW,EACX,MAAM,4CAA4C,CAAC;AAIpD,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAKhE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,mBAQ3C,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAsBD;;GAEG;AACH,qBAAa,gBAAgB;IAK3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAJ7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;gBAExB,UAAU,CAAC,iEAAqD;IAGrE,iBAAiB,CAC7B,GAAG,EAAE,yBAAyB,EAC9B,KAAK,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;YAMF,4BAA4B;IAU7B,aAAa,CACzB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAKV,aAAa,CACzB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;YAKT,iBAAiB;IAiB/B,OAAO,CAAC,MAAM,CAAC,WAAW;YAUZ,SAAS;YAgCT,aAAa;IA6C3B,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,gBAAgB;CA4BxB;AAaD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA8B/E,CAAC"}
|
package/dist/odspTokenManager.js
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.odspTokensCache = exports.OdspTokenManager = exports.getMicrosoftConfiguration = void 0;
|
|
8
|
-
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
9
|
-
const internal_2 = require("@fluidframework/odsp-doclib-utils/internal");
|
|
10
8
|
const async_mutex_1 = require("async-mutex");
|
|
11
9
|
const debug_js_1 = require("./debug.js");
|
|
12
10
|
const fluidToolRc_js_1 = require("./fluidToolRc.js");
|
|
@@ -62,13 +60,13 @@ class OdspTokenManager {
|
|
|
62
60
|
memoryCache.set(key.user, value);
|
|
63
61
|
await this.tokenCache?.save(key, value);
|
|
64
62
|
}
|
|
65
|
-
async getOdspTokens(
|
|
63
|
+
async getOdspTokens(credentials, forceRefresh = false, forceReauth = false) {
|
|
66
64
|
(0, debug_js_1.debug)("Getting odsp tokens");
|
|
67
|
-
return this.getTokens(false,
|
|
65
|
+
return this.getTokens(false, credentials, forceRefresh, forceReauth);
|
|
68
66
|
}
|
|
69
|
-
async getPushTokens(
|
|
67
|
+
async getPushTokens(credentials, forceRefresh = false, forceReauth = false) {
|
|
70
68
|
(0, debug_js_1.debug)("Getting push tokens");
|
|
71
|
-
return this.getTokens(true,
|
|
69
|
+
return this.getTokens(true, credentials, forceRefresh, forceReauth);
|
|
72
70
|
}
|
|
73
71
|
async getTokenFromCache(cacheKey) {
|
|
74
72
|
const memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;
|
|
@@ -90,12 +88,12 @@ class OdspTokenManager {
|
|
|
90
88
|
user: credentials.username,
|
|
91
89
|
};
|
|
92
90
|
}
|
|
93
|
-
async getTokens(isPush,
|
|
91
|
+
async getTokens(isPush, credentials, forceRefresh, forceReauth) {
|
|
94
92
|
const invokeGetTokensCore = async () => {
|
|
95
93
|
// Don't solely rely on tokenCache lock, ensure serialized execution of
|
|
96
94
|
// cache update to avoid multiple fetch.
|
|
97
95
|
return this.cacheMutex.runExclusive(async () => {
|
|
98
|
-
return this.getTokensCore(isPush,
|
|
96
|
+
return this.getTokensCore(isPush, credentials, forceRefresh, forceReauth);
|
|
99
97
|
});
|
|
100
98
|
};
|
|
101
99
|
if (!forceReauth && !forceRefresh) {
|
|
@@ -116,8 +114,7 @@ class OdspTokenManager {
|
|
|
116
114
|
}
|
|
117
115
|
return invokeGetTokensCore();
|
|
118
116
|
}
|
|
119
|
-
async getTokensCore(isPush,
|
|
120
|
-
const scope = isPush ? internal_2.pushScope : (0, internal_2.getOdspScope)(server);
|
|
117
|
+
async getTokensCore(isPush, credentials, forceRefresh, forceReauth) {
|
|
121
118
|
const cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);
|
|
122
119
|
let tokens;
|
|
123
120
|
if (!forceReauth) {
|
|
@@ -126,18 +123,9 @@ class OdspTokenManager {
|
|
|
126
123
|
if (tokensFromCache) {
|
|
127
124
|
if (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {
|
|
128
125
|
try {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
133
|
-
}
|
|
134
|
-
else if (credentials.type === "password") {
|
|
135
|
-
// For OAuth flows, use refresh token
|
|
136
|
-
tokens = await (0, internal_2.refreshTokens)(server, scope, clientConfig, tokensFromCache);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
(0, internal_1.unreachableCase)(credentials);
|
|
140
|
-
}
|
|
126
|
+
const scopeEndpoint = isPush ? "push" : "storage";
|
|
127
|
+
const newTokenData = await credentials.fetchToken(scopeEndpoint);
|
|
128
|
+
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
141
129
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
142
130
|
}
|
|
143
131
|
catch (error) {
|
|
@@ -153,20 +141,8 @@ class OdspTokenManager {
|
|
|
153
141
|
return tokens;
|
|
154
142
|
}
|
|
155
143
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
tokens = await this.acquireTokensWithPassword(server, scope, clientConfig, credentials.username, credentials.password);
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
case "fic": {
|
|
162
|
-
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
163
|
-
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
default: {
|
|
167
|
-
(0, internal_1.unreachableCase)(credentials);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
144
|
+
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
145
|
+
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
170
146
|
if (!isValidAndNotExpiredToken(tokens)) {
|
|
171
147
|
throw new Error(`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +
|
|
172
148
|
`Acquired token JSON: ${JSON.stringify(tokens)}`);
|
|
@@ -174,14 +150,6 @@ class OdspTokenManager {
|
|
|
174
150
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
175
151
|
return tokens;
|
|
176
152
|
}
|
|
177
|
-
async acquireTokensWithPassword(server, scope, clientConfig, username, password) {
|
|
178
|
-
const credentials = {
|
|
179
|
-
grant_type: "password",
|
|
180
|
-
username,
|
|
181
|
-
password,
|
|
182
|
-
};
|
|
183
|
-
return (0, internal_2.fetchTokens)(server, scope, clientConfig, credentials);
|
|
184
|
-
}
|
|
185
153
|
ficTokenToIOdspTokens(token, isPush) {
|
|
186
154
|
// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity
|
|
187
155
|
if (isPush) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIPublicClientConfig,\n\tIOdspTokens,\n\tTokenRequestCredentials,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport {\n\tfetchTokens,\n\tgetOdspScope,\n\tpushScope,\n\trefreshTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\n\nimport { debug } from \"./debug.js\";\nimport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nimport { loadRC, lockRC, saveRC } from \"./fluidToolRc.js\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IPublicClientConfig => ({\n\tget clientId(): string {\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n});\n\n/**\n * @internal\n */\nexport type LoginCredentials =\n\t| {\n\t\t\ttype: \"password\";\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t }\n\t| {\n\t\t\ttype: \"fic\";\n\t\t\tusername: string;\n\t\t\tfetchToken(scopeEndpoint: \"push\" | \"storage\"): Promise<string>;\n\t };\n\n/**\n * @internal\n */\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly user: string;\n}\n\nconst isValidAndNotExpiredToken = (tokens: IOdspTokens): boolean => {\n\t// Return false for undefined or empty tokens.\n\tif (!tokens.accessToken || tokens.accessToken.length === 0) {\n\t\treturn false;\n\t}\n\n\tif (tokens.receivedAt === undefined || tokens.expiresIn === undefined) {\n\t\t// If we don't have receivedAt or expiresIn, we treat the token as expired.\n\t\treturn false;\n\t}\n\n\tconst expiresAt = tokens.receivedAt + tokens.expiresIn;\n\t// Give it a 60s buffer\n\treturn expiresAt - 60 >= Date.now() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey): string => {\n\treturn `${key.user}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\n/**\n * @internal\n */\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tpublic constructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.user, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\n\t\treturn this.getTokens(false, server, clientConfig, credentials, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\n\t\treturn this.getTokens(true, server, clientConfig, credentials, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(\n\t\tcacheKey: IOdspTokenManagerCacheKey,\n\t): Promise<IOdspTokens | undefined> {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.user);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.user, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t): IOdspTokenManagerCacheKey {\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuser: credentials.username,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async (): Promise<IOdspTokens> => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(\n\t\t\t\t\tisPush,\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tcredentials,\n\t\t\t\t\tforceRefresh,\n\t\t\t\t\tforceReauth,\n\t\t\t\t);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst scope = isPush ? pushScope : getOdspScope(server);\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (credentials.type === \"fic\") {\n\t\t\t\t\t\t\tconst scopeEndpoint = isPush ? \"push\" : \"storage\";\n\t\t\t\t\t\t\tconst newTokenData = await credentials.fetchToken(scopeEndpoint);\n\t\t\t\t\t\t\ttokens = this.ficTokenToIOdspTokens(newTokenData, isPush);\n\t\t\t\t\t\t} else if (credentials.type === \"password\") {\n\t\t\t\t\t\t\t// For OAuth flows, use refresh token\n\t\t\t\t\t\t\ttokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tunreachableCase(credentials);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tokens) {\n\t\t\t\treturn tokens;\n\t\t\t}\n\t\t}\n\n\t\tswitch (credentials.type) {\n\t\t\tcase \"password\": {\n\t\t\t\ttokens = await this.acquireTokensWithPassword(\n\t\t\t\t\tserver,\n\t\t\t\t\tscope,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tcredentials.username,\n\t\t\t\t\tcredentials.password,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"fic\": {\n\t\t\t\tconst tokenData = await credentials.fetchToken(isPush ? \"push\" : \"storage\");\n\t\t\t\ttokens = this.ficTokenToIOdspTokens(tokenData, isPush);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(credentials);\n\t\t\t}\n\t\t}\n\n\t\tif (!isValidAndNotExpiredToken(tokens)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +\n\t\t\t\t\t`Acquired token JSON: ${JSON.stringify(tokens)}`,\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate async acquireTokensWithPassword(\n\t\tserver: string,\n\t\tscope: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tusername: string,\n\t\tpassword: string,\n\t): Promise<IOdspTokens> {\n\t\tconst credentials: TokenRequestCredentials = {\n\t\t\tgrant_type: \"password\",\n\t\t\tusername,\n\t\t\tpassword,\n\t\t};\n\t\treturn fetchTokens(server, scope, clientConfig, credentials);\n\t}\n\n\tprivate ficTokenToIOdspTokens(token: string, isPush: boolean): IOdspTokens {\n\t\t// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity\n\t\tif (isPush) {\n\t\t\t// Push tokens are not standard JWTs. With direct token exchange, the second leg includes information about expiry.\n\t\t\t// This is not available in the FIC flow, but in direct token exchange we request tokens with 1 hour expiry so default to that.\n\t\t\t// At worst this should result in some higher latency when a token is returned from the cache when it should really be\n\t\t\t// refreshed immediately (as attempting to use such a token will trigger a token refresh flow indirectly).\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\treceivedAt: Math.floor(Date.now() / 1000),\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\n\t\t} else {\n\t\t\treturn this.jwtToIOdspTokens(token);\n\t\t}\n\t}\n\n\tprivate jwtToIOdspTokens(token: string): IOdspTokens {\n\t\tlet receivedAt: number;\n\t\tlet expiresIn: number;\n\t\tconst payloadSegment = token.split(\".\")[1];\n\t\tif (payloadSegment === undefined) {\n\t\t\tthrow new Error(\"Invalid JWT format\");\n\t\t}\n\t\tconst payload = JSON.parse(Buffer.from(payloadSegment, \"base64url\").toString(\"utf8\")) as {\n\t\t\tiat?: number;\n\t\t\texp?: number;\n\t\t};\n\t\tif (typeof payload.iat === \"number\") {\n\t\t\treceivedAt = payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid iat claim.\");\n\t\t}\n\t\tif (typeof payload.exp === \"number\" && typeof payload.iat === \"number\") {\n\t\t\texpiresIn = payload.exp - payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid exp claim.\");\n\t\t}\n\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\treceivedAt,\n\t\t\texpiresIn,\n\t\t};\n\t}\n}\n\nasync function loadAndPatchRC(): Promise<IResources> {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete rc.tokens;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\n/**\n * @internal\n */\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.user]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- using ??= could change behavior if value is falsy\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.user];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.user] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIPublicClientConfig,\n\tIOdspTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\n\nimport { debug } from \"./debug.js\";\nimport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nimport { loadRC, lockRC, saveRC } from \"./fluidToolRc.js\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IPublicClientConfig => ({\n\tget clientId(): string {\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n});\n\n/**\n * @internal\n */\nexport interface LoginCredentials {\n\ttype: \"fic\";\n\tusername: string;\n\tfetchToken(scopeEndpoint: \"push\" | \"storage\"): Promise<string>;\n}\n\n/**\n * @internal\n */\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly user: string;\n}\n\nconst isValidAndNotExpiredToken = (tokens: IOdspTokens): boolean => {\n\t// Return false for undefined or empty tokens.\n\tif (!tokens.accessToken || tokens.accessToken.length === 0) {\n\t\treturn false;\n\t}\n\n\tif (tokens.receivedAt === undefined || tokens.expiresIn === undefined) {\n\t\t// If we don't have receivedAt or expiresIn, we treat the token as expired.\n\t\treturn false;\n\t}\n\n\tconst expiresAt = tokens.receivedAt + tokens.expiresIn;\n\t// Give it a 60s buffer\n\treturn expiresAt - 60 >= Date.now() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey): string => {\n\treturn `${key.user}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\n/**\n * @internal\n */\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tpublic constructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.user, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\n\t\treturn this.getTokens(false, credentials, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\n\t\treturn this.getTokens(true, credentials, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(\n\t\tcacheKey: IOdspTokenManagerCacheKey,\n\t): Promise<IOdspTokens | undefined> {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.user);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.user, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t): IOdspTokenManagerCacheKey {\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuser: credentials.username,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async (): Promise<IOdspTokens> => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(isPush, credentials, forceRefresh, forceReauth);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst scopeEndpoint = isPush ? \"push\" : \"storage\";\n\t\t\t\t\t\tconst newTokenData = await credentials.fetchToken(scopeEndpoint);\n\t\t\t\t\t\ttokens = this.ficTokenToIOdspTokens(newTokenData, isPush);\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tokens) {\n\t\t\t\treturn tokens;\n\t\t\t}\n\t\t}\n\n\t\tconst tokenData = await credentials.fetchToken(isPush ? \"push\" : \"storage\");\n\t\ttokens = this.ficTokenToIOdspTokens(tokenData, isPush);\n\n\t\tif (!isValidAndNotExpiredToken(tokens)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +\n\t\t\t\t\t`Acquired token JSON: ${JSON.stringify(tokens)}`,\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate ficTokenToIOdspTokens(token: string, isPush: boolean): IOdspTokens {\n\t\t// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity\n\t\tif (isPush) {\n\t\t\t// Push tokens are not standard JWTs. With direct token exchange, the second leg includes information about expiry.\n\t\t\t// This is not available in the FIC flow, but in direct token exchange we request tokens with 1 hour expiry so default to that.\n\t\t\t// At worst this should result in some higher latency when a token is returned from the cache when it should really be\n\t\t\t// refreshed immediately (as attempting to use such a token will trigger a token refresh flow indirectly).\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\treceivedAt: Math.floor(Date.now() / 1000),\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\n\t\t} else {\n\t\t\treturn this.jwtToIOdspTokens(token);\n\t\t}\n\t}\n\n\tprivate jwtToIOdspTokens(token: string): IOdspTokens {\n\t\tlet receivedAt: number;\n\t\tlet expiresIn: number;\n\t\tconst payloadSegment = token.split(\".\")[1];\n\t\tif (payloadSegment === undefined) {\n\t\t\tthrow new Error(\"Invalid JWT format\");\n\t\t}\n\t\tconst payload = JSON.parse(Buffer.from(payloadSegment, \"base64url\").toString(\"utf8\")) as {\n\t\t\tiat?: number;\n\t\t\texp?: number;\n\t\t};\n\t\tif (typeof payload.iat === \"number\") {\n\t\t\treceivedAt = payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid iat claim.\");\n\t\t}\n\t\tif (typeof payload.exp === \"number\" && typeof payload.iat === \"number\") {\n\t\t\texpiresIn = payload.exp - payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid exp claim.\");\n\t\t}\n\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\treceivedAt,\n\t\t\texpiresIn,\n\t\t};\n\t}\n}\n\nasync function loadAndPatchRC(): Promise<IResources> {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete rc.tokens;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\n/**\n * @internal\n */\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.user]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- using ??= could change behavior if value is falsy\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.user];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.user] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/tool-utils";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.110.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/tool-utils";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.110.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.110.0\";\n"]}
|
|
@@ -11,15 +11,11 @@ export declare const getMicrosoftConfiguration: () => IPublicClientConfig;
|
|
|
11
11
|
/**
|
|
12
12
|
* @internal
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
15
|
-
type: "password";
|
|
16
|
-
username: string;
|
|
17
|
-
password: string;
|
|
18
|
-
} | {
|
|
14
|
+
export interface LoginCredentials {
|
|
19
15
|
type: "fic";
|
|
20
16
|
username: string;
|
|
21
17
|
fetchToken(scopeEndpoint: "push" | "storage"): Promise<string>;
|
|
22
|
-
}
|
|
18
|
+
}
|
|
23
19
|
/**
|
|
24
20
|
* @internal
|
|
25
21
|
*/
|
|
@@ -38,13 +34,12 @@ export declare class OdspTokenManager {
|
|
|
38
34
|
constructor(tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> | undefined);
|
|
39
35
|
updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens): Promise<void>;
|
|
40
36
|
private updateTokensCacheWithoutLock;
|
|
41
|
-
getOdspTokens(
|
|
42
|
-
getPushTokens(
|
|
37
|
+
getOdspTokens(credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
|
|
38
|
+
getPushTokens(credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
|
|
43
39
|
private getTokenFromCache;
|
|
44
40
|
private static getCacheKey;
|
|
45
41
|
private getTokens;
|
|
46
42
|
private getTokensCore;
|
|
47
|
-
private acquireTokensWithPassword;
|
|
48
43
|
private ficTokenToIOdspTokens;
|
|
49
44
|
private jwtToIOdspTokens;
|
|
50
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,mBAAmB,EACnB,WAAW,EACX,MAAM,4CAA4C,CAAC;AAIpD,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAKhE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,mBAQ3C,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAsBD;;GAEG;AACH,qBAAa,gBAAgB;IAK3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAJ7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;gBAExB,UAAU,CAAC,iEAAqD;IAGrE,iBAAiB,CAC7B,GAAG,EAAE,yBAAyB,EAC9B,KAAK,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;YAMF,4BAA4B;IAU7B,aAAa,CACzB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAKV,aAAa,CACzB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;YAKT,iBAAiB;IAiB/B,OAAO,CAAC,MAAM,CAAC,WAAW;YAUZ,SAAS;YAgCT,aAAa;IA6C3B,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,gBAAgB;CA4BxB;AAaD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA8B/E,CAAC"}
|
package/lib/odspTokenManager.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { unreachableCase } from "@fluidframework/core-utils/internal";
|
|
6
|
-
import { fetchTokens, getOdspScope, pushScope, refreshTokens, } from "@fluidframework/odsp-doclib-utils/internal";
|
|
7
5
|
import { Mutex } from "async-mutex";
|
|
8
6
|
import { debug } from "./debug.js";
|
|
9
7
|
import { loadRC, lockRC, saveRC } from "./fluidToolRc.js";
|
|
@@ -58,13 +56,13 @@ export class OdspTokenManager {
|
|
|
58
56
|
memoryCache.set(key.user, value);
|
|
59
57
|
await this.tokenCache?.save(key, value);
|
|
60
58
|
}
|
|
61
|
-
async getOdspTokens(
|
|
59
|
+
async getOdspTokens(credentials, forceRefresh = false, forceReauth = false) {
|
|
62
60
|
debug("Getting odsp tokens");
|
|
63
|
-
return this.getTokens(false,
|
|
61
|
+
return this.getTokens(false, credentials, forceRefresh, forceReauth);
|
|
64
62
|
}
|
|
65
|
-
async getPushTokens(
|
|
63
|
+
async getPushTokens(credentials, forceRefresh = false, forceReauth = false) {
|
|
66
64
|
debug("Getting push tokens");
|
|
67
|
-
return this.getTokens(true,
|
|
65
|
+
return this.getTokens(true, credentials, forceRefresh, forceReauth);
|
|
68
66
|
}
|
|
69
67
|
async getTokenFromCache(cacheKey) {
|
|
70
68
|
const memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;
|
|
@@ -86,12 +84,12 @@ export class OdspTokenManager {
|
|
|
86
84
|
user: credentials.username,
|
|
87
85
|
};
|
|
88
86
|
}
|
|
89
|
-
async getTokens(isPush,
|
|
87
|
+
async getTokens(isPush, credentials, forceRefresh, forceReauth) {
|
|
90
88
|
const invokeGetTokensCore = async () => {
|
|
91
89
|
// Don't solely rely on tokenCache lock, ensure serialized execution of
|
|
92
90
|
// cache update to avoid multiple fetch.
|
|
93
91
|
return this.cacheMutex.runExclusive(async () => {
|
|
94
|
-
return this.getTokensCore(isPush,
|
|
92
|
+
return this.getTokensCore(isPush, credentials, forceRefresh, forceReauth);
|
|
95
93
|
});
|
|
96
94
|
};
|
|
97
95
|
if (!forceReauth && !forceRefresh) {
|
|
@@ -112,8 +110,7 @@ export class OdspTokenManager {
|
|
|
112
110
|
}
|
|
113
111
|
return invokeGetTokensCore();
|
|
114
112
|
}
|
|
115
|
-
async getTokensCore(isPush,
|
|
116
|
-
const scope = isPush ? pushScope : getOdspScope(server);
|
|
113
|
+
async getTokensCore(isPush, credentials, forceRefresh, forceReauth) {
|
|
117
114
|
const cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);
|
|
118
115
|
let tokens;
|
|
119
116
|
if (!forceReauth) {
|
|
@@ -122,18 +119,9 @@ export class OdspTokenManager {
|
|
|
122
119
|
if (tokensFromCache) {
|
|
123
120
|
if (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {
|
|
124
121
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
129
|
-
}
|
|
130
|
-
else if (credentials.type === "password") {
|
|
131
|
-
// For OAuth flows, use refresh token
|
|
132
|
-
tokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
unreachableCase(credentials);
|
|
136
|
-
}
|
|
122
|
+
const scopeEndpoint = isPush ? "push" : "storage";
|
|
123
|
+
const newTokenData = await credentials.fetchToken(scopeEndpoint);
|
|
124
|
+
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
137
125
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
138
126
|
}
|
|
139
127
|
catch (error) {
|
|
@@ -149,20 +137,8 @@ export class OdspTokenManager {
|
|
|
149
137
|
return tokens;
|
|
150
138
|
}
|
|
151
139
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
tokens = await this.acquireTokensWithPassword(server, scope, clientConfig, credentials.username, credentials.password);
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
-
case "fic": {
|
|
158
|
-
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
159
|
-
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
default: {
|
|
163
|
-
unreachableCase(credentials);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
140
|
+
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
141
|
+
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
166
142
|
if (!isValidAndNotExpiredToken(tokens)) {
|
|
167
143
|
throw new Error(`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +
|
|
168
144
|
`Acquired token JSON: ${JSON.stringify(tokens)}`);
|
|
@@ -170,14 +146,6 @@ export class OdspTokenManager {
|
|
|
170
146
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
171
147
|
return tokens;
|
|
172
148
|
}
|
|
173
|
-
async acquireTokensWithPassword(server, scope, clientConfig, username, password) {
|
|
174
|
-
const credentials = {
|
|
175
|
-
grant_type: "password",
|
|
176
|
-
username,
|
|
177
|
-
password,
|
|
178
|
-
};
|
|
179
|
-
return fetchTokens(server, scope, clientConfig, credentials);
|
|
180
|
-
}
|
|
181
149
|
ficTokenToIOdspTokens(token, isPush) {
|
|
182
150
|
// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity
|
|
183
151
|
if (isPush) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport type {\n\tIPublicClientConfig,\n\tIOdspTokens,\n\tTokenRequestCredentials,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport {\n\tfetchTokens,\n\tgetOdspScope,\n\tpushScope,\n\trefreshTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\n\nimport { debug } from \"./debug.js\";\nimport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nimport { loadRC, lockRC, saveRC } from \"./fluidToolRc.js\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IPublicClientConfig => ({\n\tget clientId(): string {\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n});\n\n/**\n * @internal\n */\nexport type LoginCredentials =\n\t| {\n\t\t\ttype: \"password\";\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t }\n\t| {\n\t\t\ttype: \"fic\";\n\t\t\tusername: string;\n\t\t\tfetchToken(scopeEndpoint: \"push\" | \"storage\"): Promise<string>;\n\t };\n\n/**\n * @internal\n */\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly user: string;\n}\n\nconst isValidAndNotExpiredToken = (tokens: IOdspTokens): boolean => {\n\t// Return false for undefined or empty tokens.\n\tif (!tokens.accessToken || tokens.accessToken.length === 0) {\n\t\treturn false;\n\t}\n\n\tif (tokens.receivedAt === undefined || tokens.expiresIn === undefined) {\n\t\t// If we don't have receivedAt or expiresIn, we treat the token as expired.\n\t\treturn false;\n\t}\n\n\tconst expiresAt = tokens.receivedAt + tokens.expiresIn;\n\t// Give it a 60s buffer\n\treturn expiresAt - 60 >= Date.now() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey): string => {\n\treturn `${key.user}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\n/**\n * @internal\n */\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tpublic constructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.user, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\n\t\treturn this.getTokens(false, server, clientConfig, credentials, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\n\t\treturn this.getTokens(true, server, clientConfig, credentials, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(\n\t\tcacheKey: IOdspTokenManagerCacheKey,\n\t): Promise<IOdspTokens | undefined> {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.user);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.user, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t): IOdspTokenManagerCacheKey {\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuser: credentials.username,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async (): Promise<IOdspTokens> => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(\n\t\t\t\t\tisPush,\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tcredentials,\n\t\t\t\t\tforceRefresh,\n\t\t\t\t\tforceReauth,\n\t\t\t\t);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst scope = isPush ? pushScope : getOdspScope(server);\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (credentials.type === \"fic\") {\n\t\t\t\t\t\t\tconst scopeEndpoint = isPush ? \"push\" : \"storage\";\n\t\t\t\t\t\t\tconst newTokenData = await credentials.fetchToken(scopeEndpoint);\n\t\t\t\t\t\t\ttokens = this.ficTokenToIOdspTokens(newTokenData, isPush);\n\t\t\t\t\t\t} else if (credentials.type === \"password\") {\n\t\t\t\t\t\t\t// For OAuth flows, use refresh token\n\t\t\t\t\t\t\ttokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tunreachableCase(credentials);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tokens) {\n\t\t\t\treturn tokens;\n\t\t\t}\n\t\t}\n\n\t\tswitch (credentials.type) {\n\t\t\tcase \"password\": {\n\t\t\t\ttokens = await this.acquireTokensWithPassword(\n\t\t\t\t\tserver,\n\t\t\t\t\tscope,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tcredentials.username,\n\t\t\t\t\tcredentials.password,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"fic\": {\n\t\t\t\tconst tokenData = await credentials.fetchToken(isPush ? \"push\" : \"storage\");\n\t\t\t\ttokens = this.ficTokenToIOdspTokens(tokenData, isPush);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(credentials);\n\t\t\t}\n\t\t}\n\n\t\tif (!isValidAndNotExpiredToken(tokens)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +\n\t\t\t\t\t`Acquired token JSON: ${JSON.stringify(tokens)}`,\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate async acquireTokensWithPassword(\n\t\tserver: string,\n\t\tscope: string,\n\t\tclientConfig: IPublicClientConfig,\n\t\tusername: string,\n\t\tpassword: string,\n\t): Promise<IOdspTokens> {\n\t\tconst credentials: TokenRequestCredentials = {\n\t\t\tgrant_type: \"password\",\n\t\t\tusername,\n\t\t\tpassword,\n\t\t};\n\t\treturn fetchTokens(server, scope, clientConfig, credentials);\n\t}\n\n\tprivate ficTokenToIOdspTokens(token: string, isPush: boolean): IOdspTokens {\n\t\t// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity\n\t\tif (isPush) {\n\t\t\t// Push tokens are not standard JWTs. With direct token exchange, the second leg includes information about expiry.\n\t\t\t// This is not available in the FIC flow, but in direct token exchange we request tokens with 1 hour expiry so default to that.\n\t\t\t// At worst this should result in some higher latency when a token is returned from the cache when it should really be\n\t\t\t// refreshed immediately (as attempting to use such a token will trigger a token refresh flow indirectly).\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\treceivedAt: Math.floor(Date.now() / 1000),\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\n\t\t} else {\n\t\t\treturn this.jwtToIOdspTokens(token);\n\t\t}\n\t}\n\n\tprivate jwtToIOdspTokens(token: string): IOdspTokens {\n\t\tlet receivedAt: number;\n\t\tlet expiresIn: number;\n\t\tconst payloadSegment = token.split(\".\")[1];\n\t\tif (payloadSegment === undefined) {\n\t\t\tthrow new Error(\"Invalid JWT format\");\n\t\t}\n\t\tconst payload = JSON.parse(Buffer.from(payloadSegment, \"base64url\").toString(\"utf8\")) as {\n\t\t\tiat?: number;\n\t\t\texp?: number;\n\t\t};\n\t\tif (typeof payload.iat === \"number\") {\n\t\t\treceivedAt = payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid iat claim.\");\n\t\t}\n\t\tif (typeof payload.exp === \"number\" && typeof payload.iat === \"number\") {\n\t\t\texpiresIn = payload.exp - payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid exp claim.\");\n\t\t}\n\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\treceivedAt,\n\t\t\texpiresIn,\n\t\t};\n\t}\n}\n\nasync function loadAndPatchRC(): Promise<IResources> {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete rc.tokens;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\n/**\n * @internal\n */\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.user]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- using ??= could change behavior if value is falsy\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.user];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.user] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIPublicClientConfig,\n\tIOdspTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\n\nimport { debug } from \"./debug.js\";\nimport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nimport { loadRC, lockRC, saveRC } from \"./fluidToolRc.js\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IPublicClientConfig => ({\n\tget clientId(): string {\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n});\n\n/**\n * @internal\n */\nexport interface LoginCredentials {\n\ttype: \"fic\";\n\tusername: string;\n\tfetchToken(scopeEndpoint: \"push\" | \"storage\"): Promise<string>;\n}\n\n/**\n * @internal\n */\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly user: string;\n}\n\nconst isValidAndNotExpiredToken = (tokens: IOdspTokens): boolean => {\n\t// Return false for undefined or empty tokens.\n\tif (!tokens.accessToken || tokens.accessToken.length === 0) {\n\t\treturn false;\n\t}\n\n\tif (tokens.receivedAt === undefined || tokens.expiresIn === undefined) {\n\t\t// If we don't have receivedAt or expiresIn, we treat the token as expired.\n\t\treturn false;\n\t}\n\n\tconst expiresAt = tokens.receivedAt + tokens.expiresIn;\n\t// Give it a 60s buffer\n\treturn expiresAt - 60 >= Date.now() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey): string => {\n\treturn `${key.user}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\n/**\n * @internal\n */\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tpublic constructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.user, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\n\t\treturn this.getTokens(false, credentials, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\n\t\treturn this.getTokens(true, credentials, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(\n\t\tcacheKey: IOdspTokenManagerCacheKey,\n\t): Promise<IOdspTokens | undefined> {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.user);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.user, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t): IOdspTokenManagerCacheKey {\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuser: credentials.username,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async (): Promise<IOdspTokens> => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(isPush, credentials, forceRefresh, forceReauth);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tcredentials: LoginCredentials,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst scopeEndpoint = isPush ? \"push\" : \"storage\";\n\t\t\t\t\t\tconst newTokenData = await credentials.fetchToken(scopeEndpoint);\n\t\t\t\t\t\ttokens = this.ficTokenToIOdspTokens(newTokenData, isPush);\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tokens) {\n\t\t\t\treturn tokens;\n\t\t\t}\n\t\t}\n\n\t\tconst tokenData = await credentials.fetchToken(isPush ? \"push\" : \"storage\");\n\t\ttokens = this.ficTokenToIOdspTokens(tokenData, isPush);\n\n\t\tif (!isValidAndNotExpiredToken(tokens)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Acquired invalid tokens for ${cacheKeyToString(cacheKey)}. ` +\n\t\t\t\t\t`Acquired token JSON: ${JSON.stringify(tokens)}`,\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate ficTokenToIOdspTokens(token: string, isPush: boolean): IOdspTokens {\n\t\t// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity\n\t\tif (isPush) {\n\t\t\t// Push tokens are not standard JWTs. With direct token exchange, the second leg includes information about expiry.\n\t\t\t// This is not available in the FIC flow, but in direct token exchange we request tokens with 1 hour expiry so default to that.\n\t\t\t// At worst this should result in some higher latency when a token is returned from the cache when it should really be\n\t\t\t// refreshed immediately (as attempting to use such a token will trigger a token refresh flow indirectly).\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\treceivedAt: Math.floor(Date.now() / 1000),\n\t\t\t\texpiresIn: 3600,\n\t\t\t};\n\t\t} else {\n\t\t\treturn this.jwtToIOdspTokens(token);\n\t\t}\n\t}\n\n\tprivate jwtToIOdspTokens(token: string): IOdspTokens {\n\t\tlet receivedAt: number;\n\t\tlet expiresIn: number;\n\t\tconst payloadSegment = token.split(\".\")[1];\n\t\tif (payloadSegment === undefined) {\n\t\t\tthrow new Error(\"Invalid JWT format\");\n\t\t}\n\t\tconst payload = JSON.parse(Buffer.from(payloadSegment, \"base64url\").toString(\"utf8\")) as {\n\t\t\tiat?: number;\n\t\t\texp?: number;\n\t\t};\n\t\tif (typeof payload.iat === \"number\") {\n\t\t\treceivedAt = payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid iat claim.\");\n\t\t}\n\t\tif (typeof payload.exp === \"number\" && typeof payload.iat === \"number\") {\n\t\t\texpiresIn = payload.exp - payload.iat;\n\t\t} else {\n\t\t\tthrow new TypeError(\"JWT payload lacks valid exp claim.\");\n\t\t}\n\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\treceivedAt,\n\t\t\texpiresIn,\n\t\t};\n\t}\n}\n\nasync function loadAndPatchRC(): Promise<IResources> {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete rc.tokens;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\n/**\n * @internal\n */\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.user]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- using ??= could change behavior if value is falsy\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.user];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.user] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/tool-utils";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.110.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.110.0\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/tool-utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.110.0",
|
|
4
4
|
"description": "Common utilities for Fluid tools",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"temp-directory": "nyc/.nyc_output"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@fluidframework/core-utils": "~2.
|
|
63
|
-
"@fluidframework/driver-definitions": "~2.
|
|
64
|
-
"@fluidframework/driver-utils": "~2.
|
|
65
|
-
"@fluidframework/odsp-doclib-utils": "~2.
|
|
62
|
+
"@fluidframework/core-utils": "~2.110.0",
|
|
63
|
+
"@fluidframework/driver-definitions": "~2.110.0",
|
|
64
|
+
"@fluidframework/driver-utils": "~2.110.0",
|
|
65
|
+
"@fluidframework/odsp-doclib-utils": "~2.110.0",
|
|
66
66
|
"async-mutex": "^0.3.1",
|
|
67
67
|
"debug": "^4.3.4",
|
|
68
68
|
"proper-lockfile": "^4.1.2"
|
|
@@ -70,12 +70,12 @@
|
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
72
72
|
"@biomejs/biome": "~2.4.5",
|
|
73
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
73
|
+
"@fluid-internal/mocha-test-setup": "~2.110.0",
|
|
74
74
|
"@fluid-tools/build-cli": "^0.65.0",
|
|
75
75
|
"@fluidframework/build-common": "^2.0.3",
|
|
76
76
|
"@fluidframework/build-tools": "^0.65.0",
|
|
77
|
-
"@fluidframework/eslint-config-fluid": "^
|
|
78
|
-
"@fluidframework/tool-utils-previous": "npm:@fluidframework/tool-utils@2.
|
|
77
|
+
"@fluidframework/eslint-config-fluid": "^13.0.0",
|
|
78
|
+
"@fluidframework/tool-utils-previous": "npm:@fluidframework/tool-utils@2.103.0",
|
|
79
79
|
"@microsoft/api-extractor": "7.58.1",
|
|
80
80
|
"@types/debug": "^4.1.5",
|
|
81
81
|
"@types/mocha": "^10.0.10",
|
|
@@ -93,7 +93,11 @@
|
|
|
93
93
|
"typescript": "~5.4.5"
|
|
94
94
|
},
|
|
95
95
|
"typeValidation": {
|
|
96
|
-
"broken": {
|
|
96
|
+
"broken": {
|
|
97
|
+
"TypeAlias_LoginCredentials": {
|
|
98
|
+
"forwardCompat": false
|
|
99
|
+
}
|
|
100
|
+
},
|
|
97
101
|
"entrypoint": "internal"
|
|
98
102
|
},
|
|
99
103
|
"scripts": {
|
package/src/odspTokenManager.ts
CHANGED
|
@@ -3,17 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
6
|
import type {
|
|
8
7
|
IPublicClientConfig,
|
|
9
8
|
IOdspTokens,
|
|
10
|
-
TokenRequestCredentials,
|
|
11
|
-
} from "@fluidframework/odsp-doclib-utils/internal";
|
|
12
|
-
import {
|
|
13
|
-
fetchTokens,
|
|
14
|
-
getOdspScope,
|
|
15
|
-
pushScope,
|
|
16
|
-
refreshTokens,
|
|
17
9
|
} from "@fluidframework/odsp-doclib-utils/internal";
|
|
18
10
|
import { Mutex } from "async-mutex";
|
|
19
11
|
|
|
@@ -39,17 +31,11 @@ export const getMicrosoftConfiguration = (): IPublicClientConfig => ({
|
|
|
39
31
|
/**
|
|
40
32
|
* @internal
|
|
41
33
|
*/
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
| {
|
|
49
|
-
type: "fic";
|
|
50
|
-
username: string;
|
|
51
|
-
fetchToken(scopeEndpoint: "push" | "storage"): Promise<string>;
|
|
52
|
-
};
|
|
34
|
+
export interface LoginCredentials {
|
|
35
|
+
type: "fic";
|
|
36
|
+
username: string;
|
|
37
|
+
fetchToken(scopeEndpoint: "push" | "storage"): Promise<string>;
|
|
38
|
+
}
|
|
53
39
|
|
|
54
40
|
/**
|
|
55
41
|
* @internal
|
|
@@ -110,25 +96,21 @@ export class OdspTokenManager {
|
|
|
110
96
|
}
|
|
111
97
|
|
|
112
98
|
public async getOdspTokens(
|
|
113
|
-
server: string,
|
|
114
|
-
clientConfig: IPublicClientConfig,
|
|
115
99
|
credentials: LoginCredentials,
|
|
116
100
|
forceRefresh = false,
|
|
117
101
|
forceReauth = false,
|
|
118
102
|
): Promise<IOdspTokens> {
|
|
119
103
|
debug("Getting odsp tokens");
|
|
120
|
-
return this.getTokens(false,
|
|
104
|
+
return this.getTokens(false, credentials, forceRefresh, forceReauth);
|
|
121
105
|
}
|
|
122
106
|
|
|
123
107
|
public async getPushTokens(
|
|
124
|
-
server: string,
|
|
125
|
-
clientConfig: IPublicClientConfig,
|
|
126
108
|
credentials: LoginCredentials,
|
|
127
109
|
forceRefresh = false,
|
|
128
110
|
forceReauth = false,
|
|
129
111
|
): Promise<IOdspTokens> {
|
|
130
112
|
debug("Getting push tokens");
|
|
131
|
-
return this.getTokens(true,
|
|
113
|
+
return this.getTokens(true, credentials, forceRefresh, forceReauth);
|
|
132
114
|
}
|
|
133
115
|
|
|
134
116
|
private async getTokenFromCache(
|
|
@@ -160,8 +142,6 @@ export class OdspTokenManager {
|
|
|
160
142
|
|
|
161
143
|
private async getTokens(
|
|
162
144
|
isPush: boolean,
|
|
163
|
-
server: string,
|
|
164
|
-
clientConfig: IPublicClientConfig,
|
|
165
145
|
credentials: LoginCredentials,
|
|
166
146
|
forceRefresh: boolean,
|
|
167
147
|
forceReauth: boolean,
|
|
@@ -170,14 +150,7 @@ export class OdspTokenManager {
|
|
|
170
150
|
// Don't solely rely on tokenCache lock, ensure serialized execution of
|
|
171
151
|
// cache update to avoid multiple fetch.
|
|
172
152
|
return this.cacheMutex.runExclusive(async () => {
|
|
173
|
-
return this.getTokensCore(
|
|
174
|
-
isPush,
|
|
175
|
-
server,
|
|
176
|
-
clientConfig,
|
|
177
|
-
credentials,
|
|
178
|
-
forceRefresh,
|
|
179
|
-
forceReauth,
|
|
180
|
-
);
|
|
153
|
+
return this.getTokensCore(isPush, credentials, forceRefresh, forceReauth);
|
|
181
154
|
});
|
|
182
155
|
};
|
|
183
156
|
if (!forceReauth && !forceRefresh) {
|
|
@@ -201,13 +174,10 @@ export class OdspTokenManager {
|
|
|
201
174
|
|
|
202
175
|
private async getTokensCore(
|
|
203
176
|
isPush: boolean,
|
|
204
|
-
server: string,
|
|
205
|
-
clientConfig: IPublicClientConfig,
|
|
206
177
|
credentials: LoginCredentials,
|
|
207
178
|
forceRefresh: boolean,
|
|
208
179
|
forceReauth: boolean,
|
|
209
180
|
): Promise<IOdspTokens> {
|
|
210
|
-
const scope = isPush ? pushScope : getOdspScope(server);
|
|
211
181
|
const cacheKey = OdspTokenManager.getCacheKey(isPush, credentials);
|
|
212
182
|
let tokens: IOdspTokens | undefined;
|
|
213
183
|
if (!forceReauth) {
|
|
@@ -216,16 +186,9 @@ export class OdspTokenManager {
|
|
|
216
186
|
if (tokensFromCache) {
|
|
217
187
|
if (forceRefresh || !isValidAndNotExpiredToken(tokensFromCache)) {
|
|
218
188
|
try {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
223
|
-
} else if (credentials.type === "password") {
|
|
224
|
-
// For OAuth flows, use refresh token
|
|
225
|
-
tokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);
|
|
226
|
-
} else {
|
|
227
|
-
unreachableCase(credentials);
|
|
228
|
-
}
|
|
189
|
+
const scopeEndpoint = isPush ? "push" : "storage";
|
|
190
|
+
const newTokenData = await credentials.fetchToken(scopeEndpoint);
|
|
191
|
+
tokens = this.ficTokenToIOdspTokens(newTokenData, isPush);
|
|
229
192
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
230
193
|
} catch (error) {
|
|
231
194
|
debug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);
|
|
@@ -240,26 +203,8 @@ export class OdspTokenManager {
|
|
|
240
203
|
}
|
|
241
204
|
}
|
|
242
205
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
tokens = await this.acquireTokensWithPassword(
|
|
246
|
-
server,
|
|
247
|
-
scope,
|
|
248
|
-
clientConfig,
|
|
249
|
-
credentials.username,
|
|
250
|
-
credentials.password,
|
|
251
|
-
);
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
case "fic": {
|
|
255
|
-
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
256
|
-
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
default: {
|
|
260
|
-
unreachableCase(credentials);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
206
|
+
const tokenData = await credentials.fetchToken(isPush ? "push" : "storage");
|
|
207
|
+
tokens = this.ficTokenToIOdspTokens(tokenData, isPush);
|
|
263
208
|
|
|
264
209
|
if (!isValidAndNotExpiredToken(tokens)) {
|
|
265
210
|
throw new Error(
|
|
@@ -272,21 +217,6 @@ export class OdspTokenManager {
|
|
|
272
217
|
return tokens;
|
|
273
218
|
}
|
|
274
219
|
|
|
275
|
-
private async acquireTokensWithPassword(
|
|
276
|
-
server: string,
|
|
277
|
-
scope: string,
|
|
278
|
-
clientConfig: IPublicClientConfig,
|
|
279
|
-
username: string,
|
|
280
|
-
password: string,
|
|
281
|
-
): Promise<IOdspTokens> {
|
|
282
|
-
const credentials: TokenRequestCredentials = {
|
|
283
|
-
grant_type: "password",
|
|
284
|
-
username,
|
|
285
|
-
password,
|
|
286
|
-
};
|
|
287
|
-
return fetchTokens(server, scope, clientConfig, credentials);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
220
|
private ficTokenToIOdspTokens(token: string, isPush: boolean): IOdspTokens {
|
|
291
221
|
// eslint-disable-next-line unicorn/prefer-ternary -- using if statement for clarity
|
|
292
222
|
if (isPush) {
|
package/src/packageVersion.ts
CHANGED