@azure/msal-common 14.2.0 → 14.3.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/dist/account/AuthToken.mjs +1 -1
- package/dist/account/CcsCredential.mjs +1 -1
- package/dist/account/ClientInfo.mjs +1 -1
- package/dist/authority/Authority.d.ts.map +1 -1
- package/dist/authority/Authority.mjs +3 -3
- package/dist/authority/AuthorityFactory.mjs +1 -1
- package/dist/authority/AuthorityMetadata.d.ts +29 -172
- package/dist/authority/AuthorityMetadata.d.ts.map +1 -1
- package/dist/authority/AuthorityMetadata.mjs +79 -413
- package/dist/authority/AuthorityMetadata.mjs.map +1 -1
- package/dist/authority/AuthorityOptions.d.ts +2 -2
- package/dist/authority/AuthorityOptions.d.ts.map +1 -1
- package/dist/authority/AuthorityOptions.mjs +1 -1
- package/dist/authority/AuthorityOptions.mjs.map +1 -1
- package/dist/authority/AuthorityType.mjs +1 -1
- package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
- package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
- package/dist/authority/OpenIdConfigResponse.mjs +1 -1
- package/dist/authority/ProtocolMode.mjs +1 -1
- package/dist/authority/RegionDiscovery.mjs +1 -1
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.mjs +16 -11
- package/dist/cache/CacheManager.mjs.map +1 -1
- package/dist/cache/entities/AccessTokenEntity.d.ts +12 -43
- package/dist/cache/entities/AccessTokenEntity.d.ts.map +1 -1
- package/dist/cache/entities/AccountEntity.mjs +1 -1
- package/dist/cache/entities/AppMetadataEntity.mjs +1 -1
- package/dist/cache/entities/AuthorityMetadataEntity.mjs +1 -1
- package/dist/cache/entities/CacheRecord.mjs +1 -1
- package/dist/cache/entities/CredentialEntity.d.ts +15 -73
- package/dist/cache/entities/CredentialEntity.d.ts.map +1 -1
- package/dist/cache/entities/IdTokenEntity.d.ts +4 -30
- package/dist/cache/entities/IdTokenEntity.d.ts.map +1 -1
- package/dist/cache/entities/RefreshTokenEntity.d.ts +2 -33
- package/dist/cache/entities/RefreshTokenEntity.d.ts.map +1 -1
- package/dist/cache/entities/ServerTelemetryEntity.mjs +1 -1
- package/dist/cache/entities/ThrottlingEntity.mjs +1 -1
- package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
- package/dist/cache/utils/CacheHelpers.d.ts +59 -0
- package/dist/cache/utils/CacheHelpers.d.ts.map +1 -0
- package/dist/cache/utils/CacheHelpers.mjs +226 -0
- package/dist/cache/utils/CacheHelpers.mjs.map +1 -0
- package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/client/AuthorizationCodeClient.mjs +2 -2
- package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
- package/dist/client/BaseClient.d.ts +1 -1
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.mjs +8 -8
- package/dist/client/BaseClient.mjs.map +1 -1
- package/dist/client/RefreshTokenClient.mjs +1 -1
- package/dist/client/SilentFlowClient.mjs +1 -1
- package/dist/config/ClientConfiguration.mjs +1 -1
- package/dist/crypto/ICrypto.mjs +1 -1
- package/dist/crypto/JoseHeader.mjs +1 -1
- package/dist/crypto/PopTokenGenerator.mjs +1 -1
- package/dist/error/AuthError.mjs +1 -1
- package/dist/error/AuthErrorCodes.mjs +1 -1
- package/dist/error/ClientAuthError.mjs +1 -1
- package/dist/error/ClientAuthErrorCodes.mjs +1 -1
- package/dist/error/ClientConfigurationError.mjs +1 -1
- package/dist/error/ClientConfigurationErrorCodes.mjs +1 -1
- package/dist/error/InteractionRequiredAuthError.mjs +1 -1
- package/dist/error/InteractionRequiredAuthErrorCodes.mjs +1 -1
- package/dist/error/JoseHeaderError.mjs +1 -1
- package/dist/error/JoseHeaderErrorCodes.mjs +1 -1
- package/dist/error/ServerError.mjs +1 -1
- package/dist/index.cjs +2632 -3105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +3 -5
- package/dist/index.mjs.map +1 -1
- package/dist/logger/Logger.mjs +1 -1
- package/dist/network/INetworkModule.mjs +1 -1
- package/dist/network/NetworkManager.mjs +1 -1
- package/dist/network/ThrottlingUtils.mjs +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.mjs +2 -2
- package/dist/request/AuthenticationHeaderParser.mjs +1 -1
- package/dist/request/RequestParameterBuilder.mjs +1 -1
- package/dist/request/RequestValidator.mjs +1 -1
- package/dist/request/ScopeSet.mjs +1 -1
- package/dist/response/ResponseHandler.d.ts +2 -2
- package/dist/response/ResponseHandler.d.ts.map +1 -1
- package/dist/response/ResponseHandler.mjs +23 -29
- package/dist/response/ResponseHandler.mjs.map +1 -1
- package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
- package/dist/telemetry/performance/PerformanceEvent.mjs +1 -1
- package/dist/telemetry/performance/StubPerformanceClient.mjs +1 -1
- package/dist/telemetry/server/ServerTelemetryManager.mjs +1 -1
- package/dist/url/UrlString.mjs +1 -1
- package/dist/utils/Constants.mjs +1 -1
- package/dist/utils/FunctionWrappers.mjs +1 -1
- package/dist/utils/ProtocolUtils.mjs +1 -1
- package/dist/utils/StringUtils.mjs +1 -1
- package/dist/utils/TimeUtils.mjs +1 -1
- package/package.json +1 -1
- package/src/authority/Authority.ts +3 -5
- package/src/authority/AuthorityMetadata.ts +109 -435
- package/src/authority/AuthorityOptions.ts +2 -2
- package/src/cache/CacheManager.ts +16 -20
- package/src/cache/entities/AccessTokenEntity.ts +13 -149
- package/src/cache/entities/CredentialEntity.ts +16 -200
- package/src/cache/entities/IdTokenEntity.ts +4 -64
- package/src/cache/entities/RefreshTokenEntity.ts +2 -69
- package/src/cache/utils/CacheHelpers.ts +306 -0
- package/src/client/AuthorizationCodeClient.ts +1 -2
- package/src/client/BaseClient.ts +21 -10
- package/src/index.ts +1 -0
- package/src/packageMetadata.ts +1 -1
- package/src/response/ResponseHandler.ts +36 -41
- package/dist/cache/entities/AccessTokenEntity.mjs +0 -121
- package/dist/cache/entities/AccessTokenEntity.mjs.map +0 -1
- package/dist/cache/entities/CredentialEntity.mjs +0 -145
- package/dist/cache/entities/CredentialEntity.mjs.map +0 -1
- package/dist/cache/entities/IdTokenEntity.mjs +0 -64
- package/dist/cache/entities/IdTokenEntity.mjs.map +0 -1
- package/dist/cache/entities/RefreshTokenEntity.mjs +0 -67
- package/dist/cache/entities/RefreshTokenEntity.mjs.map +0 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { extractTokenClaims } from "../../account/AuthToken";
|
|
7
|
+
import { TokenClaims } from "../../account/TokenClaims";
|
|
8
|
+
import {
|
|
9
|
+
ClientAuthErrorCodes,
|
|
10
|
+
createClientAuthError,
|
|
11
|
+
} from "../../error/ClientAuthError";
|
|
12
|
+
import {
|
|
13
|
+
AuthenticationScheme,
|
|
14
|
+
CredentialType,
|
|
15
|
+
Separators,
|
|
16
|
+
} from "../../utils/Constants";
|
|
17
|
+
import { TimeUtils } from "../../utils/TimeUtils";
|
|
18
|
+
import { AccessTokenEntity } from "../entities/AccessTokenEntity";
|
|
19
|
+
import { CredentialEntity } from "../entities/CredentialEntity";
|
|
20
|
+
import { IdTokenEntity } from "../entities/IdTokenEntity";
|
|
21
|
+
import { RefreshTokenEntity } from "../entities/RefreshTokenEntity";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Cache Key: <home_account_id>-<environment>-<credential_type>-<client_id or familyId>-<realm>-<scopes>-<claims hash>-<scheme>
|
|
25
|
+
* IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com
|
|
26
|
+
* AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop
|
|
27
|
+
* RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com
|
|
28
|
+
* @param credentialEntity
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
export function generateCredentialKey(
|
|
32
|
+
credentialEntity: CredentialEntity
|
|
33
|
+
): string {
|
|
34
|
+
const credentialKey = [
|
|
35
|
+
generateAccountId(credentialEntity),
|
|
36
|
+
generateCredentialId(credentialEntity),
|
|
37
|
+
generateTarget(credentialEntity),
|
|
38
|
+
generateClaimsHash(credentialEntity),
|
|
39
|
+
generateScheme(credentialEntity),
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create IdTokenEntity
|
|
47
|
+
* @param homeAccountId
|
|
48
|
+
* @param authenticationResult
|
|
49
|
+
* @param clientId
|
|
50
|
+
* @param authority
|
|
51
|
+
*/
|
|
52
|
+
export function createIdTokenEntity(
|
|
53
|
+
homeAccountId: string,
|
|
54
|
+
environment: string,
|
|
55
|
+
idToken: string,
|
|
56
|
+
clientId: string,
|
|
57
|
+
tenantId: string
|
|
58
|
+
): IdTokenEntity {
|
|
59
|
+
const idTokenEntity: IdTokenEntity = {
|
|
60
|
+
credentialType: CredentialType.ID_TOKEN,
|
|
61
|
+
homeAccountId: homeAccountId,
|
|
62
|
+
environment: environment,
|
|
63
|
+
clientId: clientId,
|
|
64
|
+
secret: idToken,
|
|
65
|
+
realm: tenantId,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return idTokenEntity;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create AccessTokenEntity
|
|
73
|
+
* @param homeAccountId
|
|
74
|
+
* @param environment
|
|
75
|
+
* @param accessToken
|
|
76
|
+
* @param clientId
|
|
77
|
+
* @param tenantId
|
|
78
|
+
* @param scopes
|
|
79
|
+
* @param expiresOn
|
|
80
|
+
* @param extExpiresOn
|
|
81
|
+
*/
|
|
82
|
+
export function createAccessTokenEntity(
|
|
83
|
+
homeAccountId: string,
|
|
84
|
+
environment: string,
|
|
85
|
+
accessToken: string,
|
|
86
|
+
clientId: string,
|
|
87
|
+
tenantId: string,
|
|
88
|
+
scopes: string,
|
|
89
|
+
expiresOn: number,
|
|
90
|
+
extExpiresOn: number,
|
|
91
|
+
base64Decode: (input: string) => string,
|
|
92
|
+
refreshOn?: number,
|
|
93
|
+
tokenType?: AuthenticationScheme,
|
|
94
|
+
userAssertionHash?: string,
|
|
95
|
+
keyId?: string,
|
|
96
|
+
requestedClaims?: string,
|
|
97
|
+
requestedClaimsHash?: string
|
|
98
|
+
): AccessTokenEntity {
|
|
99
|
+
const atEntity: AccessTokenEntity = {
|
|
100
|
+
homeAccountId: homeAccountId,
|
|
101
|
+
credentialType: CredentialType.ACCESS_TOKEN,
|
|
102
|
+
secret: accessToken,
|
|
103
|
+
cachedAt: TimeUtils.nowSeconds().toString(),
|
|
104
|
+
expiresOn: expiresOn.toString(),
|
|
105
|
+
extendedExpiresOn: extExpiresOn.toString(),
|
|
106
|
+
environment: environment,
|
|
107
|
+
clientId: clientId,
|
|
108
|
+
realm: tenantId,
|
|
109
|
+
target: scopes,
|
|
110
|
+
tokenType: tokenType || AuthenticationScheme.BEARER,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (userAssertionHash) {
|
|
114
|
+
atEntity.userAssertionHash = userAssertionHash;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (refreshOn) {
|
|
118
|
+
atEntity.refreshOn = refreshOn.toString();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (requestedClaims) {
|
|
122
|
+
atEntity.requestedClaims = requestedClaims;
|
|
123
|
+
atEntity.requestedClaimsHash = requestedClaimsHash;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
* Create Access Token With Auth Scheme instead of regular access token
|
|
128
|
+
* Cast to lower to handle "bearer" from ADFS
|
|
129
|
+
*/
|
|
130
|
+
if (
|
|
131
|
+
atEntity.tokenType?.toLowerCase() !==
|
|
132
|
+
AuthenticationScheme.BEARER.toLowerCase()
|
|
133
|
+
) {
|
|
134
|
+
atEntity.credentialType = CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
|
|
135
|
+
switch (atEntity.tokenType) {
|
|
136
|
+
case AuthenticationScheme.POP:
|
|
137
|
+
// Make sure keyId is present and add it to credential
|
|
138
|
+
const tokenClaims: TokenClaims | null = extractTokenClaims(
|
|
139
|
+
accessToken,
|
|
140
|
+
base64Decode
|
|
141
|
+
);
|
|
142
|
+
if (!tokenClaims?.cnf?.kid) {
|
|
143
|
+
throw createClientAuthError(
|
|
144
|
+
ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
atEntity.keyId = tokenClaims.cnf.kid;
|
|
148
|
+
break;
|
|
149
|
+
case AuthenticationScheme.SSH:
|
|
150
|
+
atEntity.keyId = keyId;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return atEntity;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Create RefreshTokenEntity
|
|
159
|
+
* @param homeAccountId
|
|
160
|
+
* @param authenticationResult
|
|
161
|
+
* @param clientId
|
|
162
|
+
* @param authority
|
|
163
|
+
*/
|
|
164
|
+
export function createRefreshTokenEntity(
|
|
165
|
+
homeAccountId: string,
|
|
166
|
+
environment: string,
|
|
167
|
+
refreshToken: string,
|
|
168
|
+
clientId: string,
|
|
169
|
+
familyId?: string,
|
|
170
|
+
userAssertionHash?: string
|
|
171
|
+
): RefreshTokenEntity {
|
|
172
|
+
const rtEntity: RefreshTokenEntity = {
|
|
173
|
+
credentialType: CredentialType.REFRESH_TOKEN,
|
|
174
|
+
homeAccountId: homeAccountId,
|
|
175
|
+
environment: environment,
|
|
176
|
+
clientId: clientId,
|
|
177
|
+
secret: refreshToken,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
if (userAssertionHash) {
|
|
181
|
+
rtEntity.userAssertionHash = userAssertionHash;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (familyId) {
|
|
185
|
+
rtEntity.familyId = familyId;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return rtEntity;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function isCredentialEntity(entity: object): boolean {
|
|
192
|
+
return (
|
|
193
|
+
entity.hasOwnProperty("homeAccountId") &&
|
|
194
|
+
entity.hasOwnProperty("environment") &&
|
|
195
|
+
entity.hasOwnProperty("credentialType") &&
|
|
196
|
+
entity.hasOwnProperty("clientId") &&
|
|
197
|
+
entity.hasOwnProperty("secret")
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Validates an entity: checks for all expected params
|
|
203
|
+
* @param entity
|
|
204
|
+
*/
|
|
205
|
+
export function isAccessTokenEntity(entity: object): boolean {
|
|
206
|
+
if (!entity) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
isCredentialEntity(entity) &&
|
|
212
|
+
entity.hasOwnProperty("realm") &&
|
|
213
|
+
entity.hasOwnProperty("target") &&
|
|
214
|
+
(entity["credentialType"] === CredentialType.ACCESS_TOKEN ||
|
|
215
|
+
entity["credentialType"] ===
|
|
216
|
+
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Validates an entity: checks for all expected params
|
|
222
|
+
* @param entity
|
|
223
|
+
*/
|
|
224
|
+
export function isIdTokenEntity(entity: object): boolean {
|
|
225
|
+
if (!entity) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
isCredentialEntity(entity) &&
|
|
231
|
+
entity.hasOwnProperty("realm") &&
|
|
232
|
+
entity["credentialType"] === CredentialType.ID_TOKEN
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Validates an entity: checks for all expected params
|
|
238
|
+
* @param entity
|
|
239
|
+
*/
|
|
240
|
+
export function isRefreshTokenEntity(entity: object): boolean {
|
|
241
|
+
if (!entity) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
isCredentialEntity(entity) &&
|
|
247
|
+
entity["credentialType"] === CredentialType.REFRESH_TOKEN
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
|
|
253
|
+
*/
|
|
254
|
+
function generateAccountId(credentialEntity: CredentialEntity): string {
|
|
255
|
+
const accountId: Array<string> = [
|
|
256
|
+
credentialEntity.homeAccountId,
|
|
257
|
+
credentialEntity.environment,
|
|
258
|
+
];
|
|
259
|
+
return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Generate Credential Id key component as per the schema: <credential_type>-<client_id>-<realm>
|
|
264
|
+
*/
|
|
265
|
+
function generateCredentialId(credentialEntity: CredentialEntity): string {
|
|
266
|
+
const clientOrFamilyId =
|
|
267
|
+
credentialEntity.credentialType === CredentialType.REFRESH_TOKEN
|
|
268
|
+
? credentialEntity.familyId || credentialEntity.clientId
|
|
269
|
+
: credentialEntity.clientId;
|
|
270
|
+
const credentialId: Array<string> = [
|
|
271
|
+
credentialEntity.credentialType,
|
|
272
|
+
clientOrFamilyId,
|
|
273
|
+
credentialEntity.realm || "",
|
|
274
|
+
];
|
|
275
|
+
|
|
276
|
+
return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Generate target key component as per schema: <target>
|
|
281
|
+
*/
|
|
282
|
+
function generateTarget(credentialEntity: CredentialEntity): string {
|
|
283
|
+
return (credentialEntity.target || "").toLowerCase();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Generate requested claims key component as per schema: <requestedClaims>
|
|
288
|
+
*/
|
|
289
|
+
function generateClaimsHash(credentialEntity: CredentialEntity): string {
|
|
290
|
+
return (credentialEntity.requestedClaimsHash || "").toLowerCase();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Generate scheme key componenet as per schema: <scheme>
|
|
295
|
+
*/
|
|
296
|
+
function generateScheme(credentialEntity: CredentialEntity): string {
|
|
297
|
+
/*
|
|
298
|
+
* PoP Tokens and SSH certs include scheme in cache key
|
|
299
|
+
* Cast to lowercase to handle "bearer" from ADFS
|
|
300
|
+
*/
|
|
301
|
+
return credentialEntity.tokenType &&
|
|
302
|
+
credentialEntity.tokenType.toLowerCase() !==
|
|
303
|
+
AuthenticationScheme.BEARER.toLowerCase()
|
|
304
|
+
? credentialEntity.tokenType.toLowerCase()
|
|
305
|
+
: "";
|
|
306
|
+
}
|
|
@@ -194,8 +194,7 @@ export class AuthorizationCodeClient extends BaseClient {
|
|
|
194
194
|
// Get code response
|
|
195
195
|
responseHandler.validateServerAuthorizationCodeResponse(
|
|
196
196
|
serverParams,
|
|
197
|
-
cachedState
|
|
198
|
-
this.cryptoUtils
|
|
197
|
+
cachedState
|
|
199
198
|
);
|
|
200
199
|
|
|
201
200
|
// throw when there is no auth code in the response
|
package/src/client/BaseClient.ts
CHANGED
|
@@ -19,15 +19,13 @@ import { CacheManager } from "../cache/CacheManager";
|
|
|
19
19
|
import { ServerTelemetryManager } from "../telemetry/server/ServerTelemetryManager";
|
|
20
20
|
import { RequestThumbprint } from "../network/RequestThumbprint";
|
|
21
21
|
import { version, name } from "../packageMetadata";
|
|
22
|
-
import {
|
|
23
|
-
createClientAuthError,
|
|
24
|
-
ClientAuthErrorCodes,
|
|
25
|
-
} from "../error/ClientAuthError";
|
|
26
22
|
import { CcsCredential, CcsCredentialType } from "../account/CcsCredential";
|
|
27
23
|
import { buildClientInfoFromHomeAccountId } from "../account/ClientInfo";
|
|
28
24
|
import { IPerformanceClient } from "../telemetry/performance/IPerformanceClient";
|
|
29
25
|
import { RequestParameterBuilder } from "../request/RequestParameterBuilder";
|
|
30
26
|
import { BaseAuthRequest } from "../request/BaseAuthRequest";
|
|
27
|
+
import { AuthorityFactory } from "../authority/AuthorityFactory";
|
|
28
|
+
import { PerformanceEvents } from "../telemetry/performance/PerformanceEvent";
|
|
31
29
|
|
|
32
30
|
/**
|
|
33
31
|
* Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.
|
|
@@ -184,13 +182,26 @@ export abstract class BaseClient {
|
|
|
184
182
|
* Updates the authority object of the client. Endpoint discovery must be completed.
|
|
185
183
|
* @param updatedAuthority
|
|
186
184
|
*/
|
|
187
|
-
updateAuthority(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
185
|
+
async updateAuthority(
|
|
186
|
+
cloudInstanceHostname: string,
|
|
187
|
+
correlationId: string
|
|
188
|
+
): Promise<void> {
|
|
189
|
+
this.performanceClient?.addQueueMeasurement(
|
|
190
|
+
PerformanceEvents.UpdateTokenEndpointAuthority,
|
|
191
|
+
correlationId
|
|
192
|
+
);
|
|
193
|
+
const cloudInstanceAuthorityUri = `https://${cloudInstanceHostname}/${this.authority.tenant}/`;
|
|
194
|
+
const cloudInstanceAuthority =
|
|
195
|
+
await AuthorityFactory.createDiscoveredInstance(
|
|
196
|
+
cloudInstanceAuthorityUri,
|
|
197
|
+
this.networkClient,
|
|
198
|
+
this.cacheManager,
|
|
199
|
+
this.authority.options,
|
|
200
|
+
this.logger,
|
|
201
|
+
this.performanceClient,
|
|
202
|
+
correlationId
|
|
191
203
|
);
|
|
192
|
-
|
|
193
|
-
this.authority = updatedAuthority;
|
|
204
|
+
this.authority = cloudInstanceAuthority;
|
|
194
205
|
}
|
|
195
206
|
|
|
196
207
|
/**
|
package/src/index.ts
CHANGED
|
@@ -71,6 +71,7 @@ export {
|
|
|
71
71
|
} from "./cache/utils/CacheTypes";
|
|
72
72
|
export { CacheRecord } from "./cache/entities/CacheRecord";
|
|
73
73
|
export { CredentialEntity } from "./cache/entities/CredentialEntity";
|
|
74
|
+
export * as CacheHelpers from "./cache/utils/CacheHelpers";
|
|
74
75
|
export { AppMetadataEntity } from "./cache/entities/AppMetadataEntity";
|
|
75
76
|
export { AccountEntity } from "./cache/entities/AccountEntity";
|
|
76
77
|
export { IdTokenEntity } from "./cache/entities/IdTokenEntity";
|
package/src/packageMetadata.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ServerAuthorizationTokenResponse } from "./ServerAuthorizationTokenResponse";
|
|
7
|
-
import { buildClientInfo } from "../account/ClientInfo";
|
|
8
7
|
import { ICrypto } from "../crypto/ICrypto";
|
|
9
8
|
import {
|
|
10
9
|
ClientAuthErrorCodes,
|
|
@@ -45,6 +44,7 @@ import { PerformanceEvents } from "../telemetry/performance/PerformanceEvent";
|
|
|
45
44
|
import { checkMaxAge, extractTokenClaims } from "../account/AuthToken";
|
|
46
45
|
import { TokenClaims } from "../account/TokenClaims";
|
|
47
46
|
import { AccountInfo } from "../account/AccountInfo";
|
|
47
|
+
import * as CacheHelpers from "../cache/utils/CacheHelpers";
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Class that handles response parsing.
|
|
@@ -81,16 +81,15 @@ export class ResponseHandler {
|
|
|
81
81
|
/**
|
|
82
82
|
* Function which validates server authorization code response.
|
|
83
83
|
* @param serverResponseHash
|
|
84
|
-
* @param
|
|
84
|
+
* @param requestState
|
|
85
85
|
* @param cryptoObj
|
|
86
86
|
*/
|
|
87
87
|
validateServerAuthorizationCodeResponse(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
cryptoObj: ICrypto
|
|
88
|
+
serverResponse: ServerAuthorizationCodeResponse,
|
|
89
|
+
requestState: string
|
|
91
90
|
): void {
|
|
92
|
-
if (!
|
|
93
|
-
throw
|
|
91
|
+
if (!serverResponse.state || !requestState) {
|
|
92
|
+
throw serverResponse.state
|
|
94
93
|
? createClientAuthError(
|
|
95
94
|
ClientAuthErrorCodes.stateNotFound,
|
|
96
95
|
"Cached State"
|
|
@@ -101,67 +100,63 @@ export class ResponseHandler {
|
|
|
101
100
|
);
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
let
|
|
105
|
-
let
|
|
103
|
+
let decodedServerResponseState: string;
|
|
104
|
+
let decodedRequestState: string;
|
|
106
105
|
|
|
107
106
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
decodedServerResponseState = decodeURIComponent(
|
|
108
|
+
serverResponse.state
|
|
110
109
|
);
|
|
111
110
|
} catch (e) {
|
|
112
111
|
throw createClientAuthError(
|
|
113
112
|
ClientAuthErrorCodes.invalidState,
|
|
114
|
-
|
|
113
|
+
serverResponse.state
|
|
115
114
|
);
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
try {
|
|
119
|
-
|
|
118
|
+
decodedRequestState = decodeURIComponent(requestState);
|
|
120
119
|
} catch (e) {
|
|
121
120
|
throw createClientAuthError(
|
|
122
121
|
ClientAuthErrorCodes.invalidState,
|
|
123
|
-
|
|
122
|
+
serverResponse.state
|
|
124
123
|
);
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
if (
|
|
126
|
+
if (decodedServerResponseState !== decodedRequestState) {
|
|
128
127
|
throw createClientAuthError(ClientAuthErrorCodes.stateMismatch);
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
// Check for error
|
|
132
131
|
if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
serverResponse.error ||
|
|
133
|
+
serverResponse.error_description ||
|
|
134
|
+
serverResponse.suberror
|
|
136
135
|
) {
|
|
137
136
|
if (
|
|
138
137
|
isInteractionRequiredError(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
serverResponse.error,
|
|
139
|
+
serverResponse.error_description,
|
|
140
|
+
serverResponse.suberror
|
|
142
141
|
)
|
|
143
142
|
) {
|
|
144
143
|
throw new InteractionRequiredAuthError(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
serverResponse.error || "",
|
|
145
|
+
serverResponse.error_description,
|
|
146
|
+
serverResponse.suberror,
|
|
147
|
+
serverResponse.timestamp || "",
|
|
148
|
+
serverResponse.trace_id || "",
|
|
149
|
+
serverResponse.correlation_id || "",
|
|
150
|
+
serverResponse.claims || ""
|
|
152
151
|
);
|
|
153
152
|
}
|
|
154
153
|
|
|
155
154
|
throw new ServerError(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
serverResponse.error || "",
|
|
156
|
+
serverResponse.error_description,
|
|
157
|
+
serverResponse.suberror
|
|
159
158
|
);
|
|
160
159
|
}
|
|
161
|
-
|
|
162
|
-
if (serverResponseHash.client_info) {
|
|
163
|
-
buildClientInfo(serverResponseHash.client_info, cryptoObj);
|
|
164
|
-
}
|
|
165
160
|
}
|
|
166
161
|
|
|
167
162
|
/**
|
|
@@ -415,7 +410,7 @@ export class ResponseHandler {
|
|
|
415
410
|
let cachedIdToken: IdTokenEntity | undefined;
|
|
416
411
|
let cachedAccount: AccountEntity | undefined;
|
|
417
412
|
if (serverTokenResponse.id_token && !!idTokenClaims) {
|
|
418
|
-
cachedIdToken =
|
|
413
|
+
cachedIdToken = CacheHelpers.createIdTokenEntity(
|
|
419
414
|
this.homeAccountIdentifier,
|
|
420
415
|
env,
|
|
421
416
|
serverTokenResponse.id_token,
|
|
@@ -468,16 +463,16 @@ export class ResponseHandler {
|
|
|
468
463
|
: undefined;
|
|
469
464
|
|
|
470
465
|
// non AAD scenarios can have empty realm
|
|
471
|
-
cachedAccessToken =
|
|
466
|
+
cachedAccessToken = CacheHelpers.createAccessTokenEntity(
|
|
472
467
|
this.homeAccountIdentifier,
|
|
473
468
|
env,
|
|
474
|
-
serverTokenResponse.access_token
|
|
469
|
+
serverTokenResponse.access_token,
|
|
475
470
|
this.clientId,
|
|
476
471
|
idTokenClaims?.tid || authority.tenant,
|
|
477
472
|
responseScopes.printScopes(),
|
|
478
473
|
tokenExpirationSeconds,
|
|
479
474
|
extendedTokenExpirationSeconds,
|
|
480
|
-
this.cryptoObj,
|
|
475
|
+
this.cryptoObj.base64Decode,
|
|
481
476
|
refreshOnSeconds,
|
|
482
477
|
serverTokenResponse.token_type,
|
|
483
478
|
userAssertionHash,
|
|
@@ -490,10 +485,10 @@ export class ResponseHandler {
|
|
|
490
485
|
// refreshToken
|
|
491
486
|
let cachedRefreshToken: RefreshTokenEntity | null = null;
|
|
492
487
|
if (serverTokenResponse.refresh_token) {
|
|
493
|
-
cachedRefreshToken =
|
|
488
|
+
cachedRefreshToken = CacheHelpers.createRefreshTokenEntity(
|
|
494
489
|
this.homeAccountIdentifier,
|
|
495
490
|
env,
|
|
496
|
-
serverTokenResponse.refresh_token
|
|
491
|
+
serverTokenResponse.refresh_token,
|
|
497
492
|
this.clientId,
|
|
498
493
|
serverTokenResponse.foci,
|
|
499
494
|
userAssertionHash
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/*! @azure/msal-common v14.2.0 2023-10-20 */
|
|
2
|
-
'use strict';
|
|
3
|
-
import { CredentialEntity } from './CredentialEntity.mjs';
|
|
4
|
-
import { CredentialType, AuthenticationScheme } from '../../utils/Constants.mjs';
|
|
5
|
-
import { TimeUtils } from '../../utils/TimeUtils.mjs';
|
|
6
|
-
import { createClientAuthError } from '../../error/ClientAuthError.mjs';
|
|
7
|
-
import { extractTokenClaims } from '../../account/AuthToken.mjs';
|
|
8
|
-
import { tokenClaimsCnfRequiredForSignedJwt } from '../../error/ClientAuthErrorCodes.mjs';
|
|
9
|
-
|
|
10
|
-
/*
|
|
11
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
12
|
-
* Licensed under the MIT License.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* ACCESS_TOKEN Credential Type
|
|
16
|
-
*
|
|
17
|
-
* Key:Value Schema:
|
|
18
|
-
*
|
|
19
|
-
* Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read
|
|
20
|
-
*
|
|
21
|
-
* Value Schema:
|
|
22
|
-
* {
|
|
23
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
24
|
-
* environment: entity that issued the token, represented as a full host
|
|
25
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
26
|
-
* clientId: client ID of the application
|
|
27
|
-
* secret: Actual credential as a string
|
|
28
|
-
* familyId: Family ID identifier, usually only used for refresh tokens
|
|
29
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
30
|
-
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
31
|
-
* cachedAt: Absolute device time when entry was created in the cache.
|
|
32
|
-
* expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string.
|
|
33
|
-
* extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds.
|
|
34
|
-
* keyId: used for POP and SSH tokenTypes
|
|
35
|
-
* tokenType: Type of the token issued. Usually "Bearer"
|
|
36
|
-
* }
|
|
37
|
-
*/
|
|
38
|
-
class AccessTokenEntity extends CredentialEntity {
|
|
39
|
-
/**
|
|
40
|
-
* Create AccessTokenEntity
|
|
41
|
-
* @param homeAccountId
|
|
42
|
-
* @param environment
|
|
43
|
-
* @param accessToken
|
|
44
|
-
* @param clientId
|
|
45
|
-
* @param tenantId
|
|
46
|
-
* @param scopes
|
|
47
|
-
* @param expiresOn
|
|
48
|
-
* @param extExpiresOn
|
|
49
|
-
*/
|
|
50
|
-
static createAccessTokenEntity(homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, cryptoUtils, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) {
|
|
51
|
-
const atEntity = new AccessTokenEntity();
|
|
52
|
-
atEntity.homeAccountId = homeAccountId;
|
|
53
|
-
atEntity.credentialType = CredentialType.ACCESS_TOKEN;
|
|
54
|
-
atEntity.secret = accessToken;
|
|
55
|
-
const currentTime = TimeUtils.nowSeconds();
|
|
56
|
-
atEntity.cachedAt = currentTime.toString();
|
|
57
|
-
/*
|
|
58
|
-
* Token expiry time.
|
|
59
|
-
* This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.
|
|
60
|
-
*/
|
|
61
|
-
atEntity.expiresOn = expiresOn.toString();
|
|
62
|
-
atEntity.extendedExpiresOn = extExpiresOn.toString();
|
|
63
|
-
if (refreshOn) {
|
|
64
|
-
atEntity.refreshOn = refreshOn.toString();
|
|
65
|
-
}
|
|
66
|
-
atEntity.environment = environment;
|
|
67
|
-
atEntity.clientId = clientId;
|
|
68
|
-
atEntity.realm = tenantId;
|
|
69
|
-
atEntity.target = scopes;
|
|
70
|
-
atEntity.userAssertionHash = userAssertionHash;
|
|
71
|
-
atEntity.tokenType = tokenType || AuthenticationScheme.BEARER;
|
|
72
|
-
if (requestedClaims) {
|
|
73
|
-
atEntity.requestedClaims = requestedClaims;
|
|
74
|
-
atEntity.requestedClaimsHash = requestedClaimsHash;
|
|
75
|
-
}
|
|
76
|
-
/*
|
|
77
|
-
* Create Access Token With Auth Scheme instead of regular access token
|
|
78
|
-
* Cast to lower to handle "bearer" from ADFS
|
|
79
|
-
*/
|
|
80
|
-
if (atEntity.tokenType?.toLowerCase() !==
|
|
81
|
-
AuthenticationScheme.BEARER.toLowerCase()) {
|
|
82
|
-
atEntity.credentialType =
|
|
83
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
|
|
84
|
-
switch (atEntity.tokenType) {
|
|
85
|
-
case AuthenticationScheme.POP:
|
|
86
|
-
// Make sure keyId is present and add it to credential
|
|
87
|
-
const tokenClaims = extractTokenClaims(accessToken, cryptoUtils.base64Decode);
|
|
88
|
-
if (!tokenClaims?.cnf?.kid) {
|
|
89
|
-
throw createClientAuthError(tokenClaimsCnfRequiredForSignedJwt);
|
|
90
|
-
}
|
|
91
|
-
atEntity.keyId = tokenClaims.cnf.kid;
|
|
92
|
-
break;
|
|
93
|
-
case AuthenticationScheme.SSH:
|
|
94
|
-
atEntity.keyId = keyId;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return atEntity;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Validates an entity: checks for all expected params
|
|
101
|
-
* @param entity
|
|
102
|
-
*/
|
|
103
|
-
static isAccessTokenEntity(entity) {
|
|
104
|
-
if (!entity) {
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
108
|
-
entity.hasOwnProperty("environment") &&
|
|
109
|
-
entity.hasOwnProperty("credentialType") &&
|
|
110
|
-
entity.hasOwnProperty("realm") &&
|
|
111
|
-
entity.hasOwnProperty("clientId") &&
|
|
112
|
-
entity.hasOwnProperty("secret") &&
|
|
113
|
-
entity.hasOwnProperty("target") &&
|
|
114
|
-
(entity["credentialType"] === CredentialType.ACCESS_TOKEN ||
|
|
115
|
-
entity["credentialType"] ===
|
|
116
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export { AccessTokenEntity };
|
|
121
|
-
//# sourceMappingURL=AccessTokenEntity.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AccessTokenEntity.mjs","sources":["../../../src/cache/entities/AccessTokenEntity.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;AAKA;AACA;AAEA;AAQA;;;;;;;;;;;;;;;;;;AAuBG;AACH;;;;;;AAMa,MAAA,iBAAU,SAAA,gBAAA,CAAA;;;;;AAMnB;;;;;;;;;;AAUG,QAAA,QAAA,CAAA,cAAA,GAAA,cAAA,CAAA,YAAA,CAAA;AACH,QAAA,QAAO,CAAA,MAAA,GAAA,WACH,CAAA;AAgFJ,QAAA,MAAA,WAAA,GAAA,SAAA,CAAA,UAAA,EAAA,CAAA;;;AAGG;AACH;AAkBH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|