@azure/core-client 1.3.2-alpha.20211001.1 → 1.4.0-alpha.20211123.3
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 +10 -1
- package/README.md +1 -1
- package/dist/index.js +93 -6
- package/dist/index.js.map +1 -1
- package/dist-esm/src/authorizeRequestOnClaimChallenge.js +69 -0
- package/dist-esm/src/authorizeRequestOnClaimChallenge.js.map +1 -0
- package/dist-esm/src/base64.browser.js +7 -0
- package/dist-esm/src/base64.browser.js.map +1 -1
- package/dist-esm/src/base64.js +7 -0
- package/dist-esm/src/base64.js.map +1 -1
- package/dist-esm/src/index.js +1 -0
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/urlHelpers.js +18 -6
- package/dist-esm/src/urlHelpers.js.map +1 -1
- package/package.json +2 -1
- package/types/3.1/core-client.d.ts +28 -0
- package/types/latest/core-client.d.ts +29 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.4.0 (Unreleased)
|
|
4
4
|
|
|
5
5
|
### Features Added
|
|
6
6
|
|
|
7
|
+
- Added a new function `authorizeRequestOnClaimChallenge`, that can be used with the `@azure/core-rest-pipeline`'s `bearerTokenAuthenticationPolicy` to support [Continuous Access Evaluation (CAE) challenges](https://docs.microsoft.com/azure/active-directory/conditional-access/concept-continuous-access-evaluation).
|
|
8
|
+
- Call the `bearerTokenAuthenticationPolicy` with the following options: `bearerTokenAuthenticationPolicy({ authorizeRequestOnChallenge: authorizeRequestOnClaimChallenge })`. Once provided, the `bearerTokenAuthenticationPolicy` policy will internally handle Continuous Access Evaluation (CAE) challenges. When it can't complete a challenge it will return the 401 (unauthorized) response from ARM.
|
|
9
|
+
|
|
7
10
|
### Breaking Changes
|
|
8
11
|
|
|
9
12
|
### Bugs Fixed
|
|
10
13
|
|
|
11
14
|
### Other Changes
|
|
12
15
|
|
|
16
|
+
## 1.3.2 (2021-10-25)
|
|
17
|
+
|
|
18
|
+
### Bugs Fixed
|
|
19
|
+
|
|
20
|
+
- Skip query parameter replacement for absolute URLs. [PR #18310](https://github.com/Azure/azure-sdk-for-js/pull/18310)
|
|
21
|
+
|
|
13
22
|
## 1.3.1 (2021-09-30)
|
|
14
23
|
|
|
15
24
|
### Other Changes
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Azure Core Service client library for JavaScript
|
|
1
|
+
# Azure Core Service client library for JavaScript
|
|
2
2
|
|
|
3
3
|
This library is primarily intended to be used in code generated by [AutoRest](https://github.com/Azure/Autorest) and [`autorest.typescript`](https://github.com/Azure/autorest.typescript).
|
|
4
4
|
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var coreRestPipeline = require('@azure/core-rest-pipeline');
|
|
6
|
+
var logger$1 = require('@azure/logger');
|
|
6
7
|
require('@azure/core-asynciterator-polyfill');
|
|
7
8
|
|
|
8
9
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -140,6 +141,13 @@ function encodeByteArray(value) {
|
|
|
140
141
|
function decodeString(value) {
|
|
141
142
|
return Buffer.from(value, "base64");
|
|
142
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Decodes a base64 string into a string.
|
|
146
|
+
* @param value - the base64 string to decode
|
|
147
|
+
*/
|
|
148
|
+
function decodeStringToString(value) {
|
|
149
|
+
return Buffer.from(value, "base64").toString();
|
|
150
|
+
}
|
|
143
151
|
|
|
144
152
|
// Copyright (c) Microsoft Corporation.
|
|
145
153
|
// Licensed under the MIT license.
|
|
@@ -1145,6 +1153,7 @@ const CollectionFormatToDelimiterMap = {
|
|
|
1145
1153
|
};
|
|
1146
1154
|
function getRequestUrl(baseUri, operationSpec, operationArguments, fallbackObject) {
|
|
1147
1155
|
const urlReplacements = calculateUrlReplacements(operationSpec, operationArguments, fallbackObject);
|
|
1156
|
+
let isAbsolutePath = false;
|
|
1148
1157
|
let requestUrl = replaceAll(baseUri, urlReplacements);
|
|
1149
1158
|
if (operationSpec.path) {
|
|
1150
1159
|
const path = replaceAll(operationSpec.path, urlReplacements);
|
|
@@ -1153,13 +1162,20 @@ function getRequestUrl(baseUri, operationSpec, operationArguments, fallbackObjec
|
|
|
1153
1162
|
// ignore the baseUri.
|
|
1154
1163
|
if (isAbsoluteUrl(path)) {
|
|
1155
1164
|
requestUrl = path;
|
|
1165
|
+
isAbsolutePath = true;
|
|
1156
1166
|
}
|
|
1157
1167
|
else {
|
|
1158
1168
|
requestUrl = appendPath(requestUrl, path);
|
|
1159
1169
|
}
|
|
1160
1170
|
}
|
|
1161
1171
|
const { queryParams, sequenceParams } = calculateQueryParameters(operationSpec, operationArguments, fallbackObject);
|
|
1162
|
-
|
|
1172
|
+
/**
|
|
1173
|
+
* Notice that this call sets the `noOverwrite` parameter to true if the `requestUrl`
|
|
1174
|
+
* is an absolute path. This ensures that existing query parameter values in `requestUrl`
|
|
1175
|
+
* do not get overwritten. On the other hand when `requestUrl` is not absolute path, it
|
|
1176
|
+
* is still being built so there is nothing to overwrite.
|
|
1177
|
+
*/
|
|
1178
|
+
requestUrl = appendQueryParams(requestUrl, queryParams, sequenceParams, isAbsolutePath);
|
|
1163
1179
|
return requestUrl;
|
|
1164
1180
|
}
|
|
1165
1181
|
function replaceAll(input, replacements) {
|
|
@@ -1297,7 +1313,7 @@ function simpleParseQueryParams(queryString) {
|
|
|
1297
1313
|
return result;
|
|
1298
1314
|
}
|
|
1299
1315
|
/** @internal */
|
|
1300
|
-
function appendQueryParams(url, queryParams, sequenceParams) {
|
|
1316
|
+
function appendQueryParams(url, queryParams, sequenceParams, noOverwrite = false) {
|
|
1301
1317
|
if (queryParams.size === 0) {
|
|
1302
1318
|
return url;
|
|
1303
1319
|
}
|
|
@@ -1319,14 +1335,15 @@ function appendQueryParams(url, queryParams, sequenceParams) {
|
|
|
1319
1335
|
}
|
|
1320
1336
|
}
|
|
1321
1337
|
else if (existingValue) {
|
|
1322
|
-
let newValue = value;
|
|
1323
1338
|
if (Array.isArray(value)) {
|
|
1324
1339
|
value.unshift(existingValue);
|
|
1325
1340
|
}
|
|
1326
1341
|
else if (sequenceParams.has(name)) {
|
|
1327
|
-
|
|
1342
|
+
combinedParams.set(name, [existingValue, value]);
|
|
1343
|
+
}
|
|
1344
|
+
if (!noOverwrite) {
|
|
1345
|
+
combinedParams.set(name, value);
|
|
1328
1346
|
}
|
|
1329
|
-
combinedParams.set(name, newValue);
|
|
1330
1347
|
}
|
|
1331
1348
|
else {
|
|
1332
1349
|
combinedParams.set(name, value);
|
|
@@ -1337,12 +1354,15 @@ function appendQueryParams(url, queryParams, sequenceParams) {
|
|
|
1337
1354
|
if (typeof value === "string") {
|
|
1338
1355
|
searchPieces.push(`${name}=${value}`);
|
|
1339
1356
|
}
|
|
1340
|
-
else {
|
|
1357
|
+
else if (Array.isArray(value)) {
|
|
1341
1358
|
// QUIRK: If we get an array of values, include multiple key/value pairs
|
|
1342
1359
|
for (const subValue of value) {
|
|
1343
1360
|
searchPieces.push(`${name}=${subValue}`);
|
|
1344
1361
|
}
|
|
1345
1362
|
}
|
|
1363
|
+
else {
|
|
1364
|
+
searchPieces.push(`${name}=${value}`);
|
|
1365
|
+
}
|
|
1346
1366
|
}
|
|
1347
1367
|
// QUIRK: we have to set search manually as searchParams will encode comma when it shouldn't.
|
|
1348
1368
|
parsedUrl.search = searchPieces.length ? `?${searchPieces.join("&")}` : "";
|
|
@@ -1874,10 +1894,77 @@ function getCredentialScopes(options) {
|
|
|
1874
1894
|
return undefined;
|
|
1875
1895
|
}
|
|
1876
1896
|
|
|
1897
|
+
// Copyright (c) Microsoft Corporation.
|
|
1898
|
+
const logger = logger$1.createClientLogger("authorizeRequestOnClaimChallenge");
|
|
1899
|
+
/**
|
|
1900
|
+
* Converts: `Bearer a="b", c="d", Bearer d="e", f="g"`.
|
|
1901
|
+
* Into: `[ { a: 'b', c: 'd' }, { d: 'e', f: 'g' } ]`.
|
|
1902
|
+
*
|
|
1903
|
+
* @internal
|
|
1904
|
+
*/
|
|
1905
|
+
function parseCAEChallenge(challenges) {
|
|
1906
|
+
const bearerChallenges = `, ${challenges.trim()}`.split(", Bearer ").filter((x) => x);
|
|
1907
|
+
return bearerChallenges.map((challenge) => {
|
|
1908
|
+
const challengeParts = `${challenge.trim()}, `.split('", ').filter((x) => x);
|
|
1909
|
+
const keyValuePairs = challengeParts.map((keyValue) => (([key, value]) => ({ [key]: value }))(keyValue.trim().split('="')));
|
|
1910
|
+
// Key-value pairs to plain object:
|
|
1911
|
+
return keyValuePairs.reduce((a, b) => (Object.assign(Object.assign({}, a), b)), {});
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
/**
|
|
1915
|
+
* This function can be used as a callback for the `bearerTokenAuthenticationPolicy` of `@azure/core-rest-pipeline`, to support CAE challenges:
|
|
1916
|
+
* [Continuous Access Evaluation](https://docs.microsoft.com/azure/active-directory/conditional-access/concept-continuous-access-evaluation).
|
|
1917
|
+
*
|
|
1918
|
+
* Call the `bearerTokenAuthenticationPolicy` with the following options:
|
|
1919
|
+
*
|
|
1920
|
+
* ```ts
|
|
1921
|
+
* import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline";
|
|
1922
|
+
* import { authorizeRequestOnClaimChallenge } from "@azure/core-client";
|
|
1923
|
+
*
|
|
1924
|
+
* const bearerTokenAuthenticationPolicy = bearerTokenAuthenticationPolicy({
|
|
1925
|
+
* authorizeRequestOnChallenge: authorizeRequestOnClaimChallenge
|
|
1926
|
+
* });
|
|
1927
|
+
* ```
|
|
1928
|
+
*
|
|
1929
|
+
* Once provided, the `bearerTokenAuthenticationPolicy` policy will internally handle Continuous Access Evaluation (CAE) challenges.
|
|
1930
|
+
* When it can't complete a challenge it will return the 401 (unauthorized) response from ARM.
|
|
1931
|
+
*
|
|
1932
|
+
* Example challenge with claims:
|
|
1933
|
+
*
|
|
1934
|
+
* ```
|
|
1935
|
+
* Bearer authorization_uri="https://login.windows-ppe.net/", error="invalid_token",
|
|
1936
|
+
* error_description="User session has been revoked",
|
|
1937
|
+
* claims="eyJhY2Nlc3NfdG9rZW4iOnsibmJmIjp7ImVzc2VudGlhbCI6dHJ1ZSwgInZhbHVlIjoiMTYwMzc0MjgwMCJ9fX0="
|
|
1938
|
+
* ```
|
|
1939
|
+
*/
|
|
1940
|
+
async function authorizeRequestOnClaimChallenge(onChallengeOptions) {
|
|
1941
|
+
const { scopes, response } = onChallengeOptions;
|
|
1942
|
+
const challenge = response.headers.get("WWW-Authenticate");
|
|
1943
|
+
if (!challenge) {
|
|
1944
|
+
logger.info(`The WWW-Authenticate header was missing. Failed to perform the Continuous Access Evaluation authentication flow.`);
|
|
1945
|
+
return false;
|
|
1946
|
+
}
|
|
1947
|
+
const challenges = parseCAEChallenge(challenge) || [];
|
|
1948
|
+
const parsedChallenge = challenges.find((x) => x.claims);
|
|
1949
|
+
if (!parsedChallenge) {
|
|
1950
|
+
logger.info(`The WWW-Authenticate header was missing the necessary "claims" to perform the Continuous Access Evaluation authentication flow.`);
|
|
1951
|
+
return false;
|
|
1952
|
+
}
|
|
1953
|
+
const accessToken = await onChallengeOptions.getAccessToken(parsedChallenge.scope ? [parsedChallenge.scope] : scopes, {
|
|
1954
|
+
claims: decodeStringToString(parsedChallenge.claims)
|
|
1955
|
+
});
|
|
1956
|
+
if (!accessToken) {
|
|
1957
|
+
return false;
|
|
1958
|
+
}
|
|
1959
|
+
onChallengeOptions.request.headers.set("Authorization", `Bearer ${accessToken.token}`);
|
|
1960
|
+
return true;
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1877
1963
|
exports.MapperTypeNames = MapperTypeNames;
|
|
1878
1964
|
exports.ServiceClient = ServiceClient;
|
|
1879
1965
|
exports.XML_ATTRKEY = XML_ATTRKEY;
|
|
1880
1966
|
exports.XML_CHARKEY = XML_CHARKEY;
|
|
1967
|
+
exports.authorizeRequestOnClaimChallenge = authorizeRequestOnClaimChallenge;
|
|
1881
1968
|
exports.createClientPipeline = createClientPipeline;
|
|
1882
1969
|
exports.createSerializer = createSerializer;
|
|
1883
1970
|
exports.deserializationPolicy = deserializationPolicy;
|