@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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluidframework/tool-utils
2
2
 
3
+ ## 2.110.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.103.0
4
8
 
5
9
  Dependency updates only.
@@ -11,15 +11,11 @@ export declare const getMicrosoftConfiguration: () => IPublicClientConfig;
11
11
  /**
12
12
  * @internal
13
13
  */
14
- export type LoginCredentials = {
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(server: string, clientConfig: IPublicClientConfig, credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
42
- getPushTokens(server: string, clientConfig: IPublicClientConfig, credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
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;AAGH,OAAO,KAAK,EACX,mBAAmB,EACnB,WAAW,EAEX,MAAM,4CAA4C,CAAC;AAUpD,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAKhE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,mBAQ3C,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACzB;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D,CAAC;AAEL;;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,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAKV,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,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;YAyCT,aAAa;YAyEb,yBAAyB;IAevC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,gBAAgB;CA4BxB;AAaD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA8B/E,CAAC"}
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"}
@@ -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(server, clientConfig, credentials, forceRefresh = false, forceReauth = false) {
63
+ async getOdspTokens(credentials, forceRefresh = false, forceReauth = false) {
66
64
  (0, debug_js_1.debug)("Getting odsp tokens");
67
- return this.getTokens(false, server, clientConfig, credentials, forceRefresh, forceReauth);
65
+ return this.getTokens(false, credentials, forceRefresh, forceReauth);
68
66
  }
69
- async getPushTokens(server, clientConfig, credentials, forceRefresh = false, forceReauth = false) {
67
+ async getPushTokens(credentials, forceRefresh = false, forceReauth = false) {
70
68
  (0, debug_js_1.debug)("Getting push tokens");
71
- return this.getTokens(true, server, clientConfig, credentials, forceRefresh, forceReauth);
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, server, clientConfig, credentials, forceRefresh, forceReauth) {
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, server, clientConfig, credentials, forceRefresh, forceReauth);
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, server, clientConfig, credentials, forceRefresh, forceReauth) {
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
- if (credentials.type === "fic") {
130
- const scopeEndpoint = isPush ? "push" : "storage";
131
- const newTokenData = await credentials.fetchToken(scopeEndpoint);
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
- switch (credentials.type) {
157
- case "password": {
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"]}
@@ -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.103.0";
8
+ export declare const pkgVersion = "2.110.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -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.103.0";
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.103.0\";\n"]}
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 type LoginCredentials = {
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(server: string, clientConfig: IPublicClientConfig, credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
42
- getPushTokens(server: string, clientConfig: IPublicClientConfig, credentials: LoginCredentials, forceRefresh?: boolean, forceReauth?: boolean): Promise<IOdspTokens>;
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;AAGH,OAAO,KAAK,EACX,mBAAmB,EACnB,WAAW,EAEX,MAAM,4CAA4C,CAAC;AAUpD,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAKhE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,mBAQ3C,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACzB;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D,CAAC;AAEL;;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,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,gBAAgB,EAC7B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAKV,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,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;YAyCT,aAAa;YAyEb,yBAAyB;IAevC,OAAO,CAAC,qBAAqB;IAiB7B,OAAO,CAAC,gBAAgB;CA4BxB;AAaD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA8B/E,CAAC"}
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"}
@@ -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(server, clientConfig, credentials, forceRefresh = false, forceReauth = false) {
59
+ async getOdspTokens(credentials, forceRefresh = false, forceReauth = false) {
62
60
  debug("Getting odsp tokens");
63
- return this.getTokens(false, server, clientConfig, credentials, forceRefresh, forceReauth);
61
+ return this.getTokens(false, credentials, forceRefresh, forceReauth);
64
62
  }
65
- async getPushTokens(server, clientConfig, credentials, forceRefresh = false, forceReauth = false) {
63
+ async getPushTokens(credentials, forceRefresh = false, forceReauth = false) {
66
64
  debug("Getting push tokens");
67
- return this.getTokens(true, server, clientConfig, credentials, forceRefresh, forceReauth);
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, server, clientConfig, credentials, forceRefresh, forceReauth) {
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, server, clientConfig, credentials, forceRefresh, forceReauth);
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, server, clientConfig, credentials, forceRefresh, forceReauth) {
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
- if (credentials.type === "fic") {
126
- const scopeEndpoint = isPush ? "push" : "storage";
127
- const newTokenData = await credentials.fetchToken(scopeEndpoint);
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
- switch (credentials.type) {
153
- case "password": {
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"]}
@@ -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.103.0";
8
+ export declare const pkgVersion = "2.110.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/tool-utils";
8
- export const pkgVersion = "2.103.0";
8
+ export const pkgVersion = "2.110.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -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.103.0\";\n"]}
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.103.0",
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.103.0",
63
- "@fluidframework/driver-definitions": "~2.103.0",
64
- "@fluidframework/driver-utils": "~2.103.0",
65
- "@fluidframework/odsp-doclib-utils": "~2.103.0",
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.103.0",
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": "^9.0.0",
78
- "@fluidframework/tool-utils-previous": "npm:@fluidframework/tool-utils@2.101.0",
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": {
@@ -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 type LoginCredentials =
43
- | {
44
- type: "password";
45
- username: string;
46
- password: string;
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, server, clientConfig, credentials, forceRefresh, forceReauth);
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, server, clientConfig, credentials, forceRefresh, forceReauth);
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
- if (credentials.type === "fic") {
220
- const scopeEndpoint = isPush ? "push" : "storage";
221
- const newTokenData = await credentials.fetchToken(scopeEndpoint);
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
- switch (credentials.type) {
244
- case "password": {
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) {
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/tool-utils";
9
- export const pkgVersion = "2.103.0";
9
+ export const pkgVersion = "2.110.0";