@azure/keyvault-common 2.0.2-alpha.20260227.1 → 2.0.2-alpha.20260303.1

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.
Files changed (37) hide show
  1. package/dist/browser/index.d.ts +1 -1
  2. package/dist/browser/index.d.ts.map +1 -1
  3. package/dist/browser/index.js +0 -1
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/commonjs/extendedClientOptions.js +15 -5
  6. package/dist/commonjs/extendedClientOptions.js.map +7 -1
  7. package/dist/commonjs/index.d.ts +1 -1
  8. package/dist/commonjs/index.d.ts.map +1 -1
  9. package/dist/commonjs/index.js +18 -9
  10. package/dist/commonjs/index.js.map +7 -1
  11. package/dist/commonjs/keyVaultAuthenticationPolicy.js +146 -157
  12. package/dist/commonjs/keyVaultAuthenticationPolicy.js.map +7 -1
  13. package/dist/commonjs/logger.js +24 -8
  14. package/dist/commonjs/logger.js.map +7 -1
  15. package/dist/commonjs/parseKeyVaultIdentifier.js +53 -41
  16. package/dist/commonjs/parseKeyVaultIdentifier.js.map +7 -1
  17. package/dist/commonjs/parseWWWAuthenticate.js +49 -45
  18. package/dist/commonjs/parseWWWAuthenticate.js.map +7 -1
  19. package/dist/commonjs/tokenCycler.js +117 -155
  20. package/dist/commonjs/tokenCycler.js.map +7 -1
  21. package/dist/esm/extendedClientOptions.js +0 -4
  22. package/dist/esm/extendedClientOptions.js.map +7 -1
  23. package/dist/esm/index.d.ts +1 -1
  24. package/dist/esm/index.d.ts.map +1 -1
  25. package/dist/esm/index.js +0 -4
  26. package/dist/esm/index.js.map +7 -1
  27. package/dist/esm/keyVaultAuthenticationPolicy.js +125 -151
  28. package/dist/esm/keyVaultAuthenticationPolicy.js.map +7 -1
  29. package/dist/esm/logger.js +4 -4
  30. package/dist/esm/logger.js.map +7 -1
  31. package/dist/esm/parseKeyVaultIdentifier.js +35 -39
  32. package/dist/esm/parseKeyVaultIdentifier.js.map +7 -1
  33. package/dist/esm/parseWWWAuthenticate.js +31 -43
  34. package/dist/esm/parseWWWAuthenticate.js.map +7 -1
  35. package/dist/esm/tokenCycler.js +98 -151
  36. package/dist/esm/tokenCycler.js.map +7 -1
  37. package/package.json +2 -18
@@ -1,5 +1,5 @@
1
1
  export * from "./keyVaultAuthenticationPolicy.js";
2
2
  export * from "./parseKeyVaultIdentifier.js";
3
- export * from "./extendedClientOptions.js";
3
+ export type * from "./extendedClientOptions.js";
4
4
  export type { AdditionalPolicyConfig } from "@azure-rest/core-client";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,mBAAmB,4BAA4B,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -2,5 +2,4 @@
2
2
  // Licensed under the MIT License.
3
3
  export * from "./keyVaultAuthenticationPolicy.js";
4
4
  export * from "./parseKeyVaultIdentifier.js";
5
- export * from "./extendedClientOptions.js";
6
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nexport * from \"./keyVaultAuthenticationPolicy.js\";\nexport * from \"./parseKeyVaultIdentifier.js\";\nexport * from \"./extendedClientOptions.js\";\nexport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nexport * from \"./keyVaultAuthenticationPolicy.js\";\nexport * from \"./parseKeyVaultIdentifier.js\";\nexport type * from \"./extendedClientOptions.js\";\nexport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n"]}
@@ -1,5 +1,15 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- //# sourceMappingURL=extendedClientOptions.js.map
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
14
+ var extendedClientOptions_exports = {};
15
+ module.exports = __toCommonJS(extendedClientOptions_exports);
@@ -1 +1,7 @@
1
- {"version":3,"file":"extendedClientOptions.js","sourceRoot":"","sources":["../../src/extendedClientOptions.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { HttpClient, PipelineOptions } from \"@azure/core-rest-pipeline\";\nimport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n\n/**\n * The common set of options that high level clients are expected to expose.\n */\nexport interface CommonClientOptions extends PipelineOptions {\n /**\n * The HttpClient that will be used to send HTTP requests.\n */\n httpClient?: HttpClient;\n /**\n * Set to true if the request is sent over HTTP instead of HTTPS\n */\n allowInsecureConnection?: boolean;\n /**\n * Additional policies to include in the HTTP pipeline.\n */\n additionalPolicies?: AdditionalPolicyConfig[];\n}\n\n/**\n * Options for keep alive behavior of HTTP connections.\n */\nexport interface KeepAliveOptions {\n /**\n * When true, connections will be kept alive for multiple requests.\n * Defaults to true.\n */\n enable?: boolean;\n}\n\n/**\n * Options for how redirect responses are handled.\n */\nexport interface RedirectOptions {\n /**\n * When true, redirect responses are followed. Defaults to true.\n */\n handleRedirects?: boolean;\n\n /**\n * The maximum number of times the redirect URL will be tried before\n * failing. Defaults to 20.\n */\n maxRetries?: number;\n}\n\n/**\n * Extended common client options that include keep alive and redirect options.\n * This type combines the standard CommonClientOptions with additional options\n * for controlling HTTP connection keep-alive and redirect behavior.\n */\nexport type ExtendedCommonClientOptions = CommonClientOptions & {\n /**\n * Options to configure keep alive behavior for HTTP connections.\n */\n keepAliveOptions?: KeepAliveOptions;\n /**\n * Options to configure how redirect responses are handled.\n */\n redirectOptions?: RedirectOptions;\n};\n"]}
1
+ {
2
+ "version": 3,
3
+ "sources": ["/mnt/vss/_work/1/s/sdk/keyvault/keyvault-common/src/extendedClientOptions.ts"],
4
+ "sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { HttpClient, PipelineOptions } from \"@azure/core-rest-pipeline\";\nimport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n\n/**\n * The common set of options that high level clients are expected to expose.\n */\nexport interface CommonClientOptions extends PipelineOptions {\n /**\n * The HttpClient that will be used to send HTTP requests.\n */\n httpClient?: HttpClient;\n /**\n * Set to true if the request is sent over HTTP instead of HTTPS\n */\n allowInsecureConnection?: boolean;\n /**\n * Additional policies to include in the HTTP pipeline.\n */\n additionalPolicies?: AdditionalPolicyConfig[];\n}\n\n/**\n * Options for keep alive behavior of HTTP connections.\n */\nexport interface KeepAliveOptions {\n /**\n * When true, connections will be kept alive for multiple requests.\n * Defaults to true.\n */\n enable?: boolean;\n}\n\n/**\n * Options for how redirect responses are handled.\n */\nexport interface RedirectOptions {\n /**\n * When true, redirect responses are followed. Defaults to true.\n */\n handleRedirects?: boolean;\n\n /**\n * The maximum number of times the redirect URL will be tried before\n * failing. Defaults to 20.\n */\n maxRetries?: number;\n}\n\n/**\n * Extended common client options that include keep alive and redirect options.\n * This type combines the standard CommonClientOptions with additional options\n * for controlling HTTP connection keep-alive and redirect behavior.\n */\nexport type ExtendedCommonClientOptions = CommonClientOptions & {\n /**\n * Options to configure keep alive behavior for HTTP connections.\n */\n keepAliveOptions?: KeepAliveOptions;\n /**\n * Options to configure how redirect responses are handled.\n */\n redirectOptions?: RedirectOptions;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -1,5 +1,5 @@
1
1
  export * from "./keyVaultAuthenticationPolicy.js";
2
2
  export * from "./parseKeyVaultIdentifier.js";
3
- export * from "./extendedClientOptions.js";
3
+ export type * from "./extendedClientOptions.js";
4
4
  export type { AdditionalPolicyConfig } from "@azure-rest/core-client";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,mBAAmB,4BAA4B,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,9 +1,18 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- const tslib_1 = require("tslib");
6
- tslib_1.__exportStar(require("./keyVaultAuthenticationPolicy.js"), exports);
7
- tslib_1.__exportStar(require("./parseKeyVaultIdentifier.js"), exports);
8
- tslib_1.__exportStar(require("./extendedClientOptions.js"), exports);
9
- //# sourceMappingURL=index.js.map
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var src_exports = {};
16
+ module.exports = __toCommonJS(src_exports);
17
+ __reExport(src_exports, require("./keyVaultAuthenticationPolicy.js"), module.exports);
18
+ __reExport(src_exports, require("./parseKeyVaultIdentifier.js"), module.exports);
@@ -1 +1,7 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAElC,4EAAkD;AAClD,uEAA6C;AAC7C,qEAA2C","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nexport * from \"./keyVaultAuthenticationPolicy.js\";\nexport * from \"./parseKeyVaultIdentifier.js\";\nexport * from \"./extendedClientOptions.js\";\nexport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n"]}
1
+ {
2
+ "version": 3,
3
+ "sources": ["/mnt/vss/_work/1/s/sdk/keyvault/keyvault-common/src/index.ts"],
4
+ "sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nexport * from \"./keyVaultAuthenticationPolicy.js\";\nexport * from \"./parseKeyVaultIdentifier.js\";\nexport type * from \"./extendedClientOptions.js\";\nexport type { AdditionalPolicyConfig } from \"@azure-rest/core-client\";\n"],
5
+ "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAGA,wBAAc,8CAHd;AAIA,wBAAc,yCAJd;",
6
+ "names": []
7
+ }
@@ -1,168 +1,157 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.keyVaultAuthenticationPolicyName = void 0;
6
- exports.keyVaultAuthenticationPolicy = keyVaultAuthenticationPolicy;
7
- const parseWWWAuthenticate_js_1 = require("./parseWWWAuthenticate.js");
8
- const tokenCycler_js_1 = require("./tokenCycler.js");
9
- const logger_js_1 = require("./logger.js");
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var keyVaultAuthenticationPolicy_exports = {};
19
+ __export(keyVaultAuthenticationPolicy_exports, {
20
+ keyVaultAuthenticationPolicy: () => keyVaultAuthenticationPolicy,
21
+ keyVaultAuthenticationPolicyName: () => keyVaultAuthenticationPolicyName
22
+ });
23
+ module.exports = __toCommonJS(keyVaultAuthenticationPolicy_exports);
24
+ var import_parseWWWAuthenticate = require("./parseWWWAuthenticate.js");
25
+ var import_tokenCycler = require("./tokenCycler.js");
26
+ var import_logger = require("./logger.js");
10
27
  function verifyChallengeResource(scope, request) {
11
- let scopeAsUrl;
12
- try {
13
- scopeAsUrl = new URL(scope);
14
- }
15
- catch (e) {
16
- throw new Error(`The challenge contains invalid scope '${scope}'`);
17
- }
18
- const requestUrl = new URL(request.url);
19
- if (!requestUrl.hostname.endsWith(`.${scopeAsUrl.hostname}`)) {
20
- throw new Error(`The challenge resource '${scopeAsUrl.hostname}' does not match the requested domain. Set disableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information.`);
21
- }
28
+ let scopeAsUrl;
29
+ try {
30
+ scopeAsUrl = new URL(scope);
31
+ } catch (e) {
32
+ throw new Error(`The challenge contains invalid scope '${scope}'`);
33
+ }
34
+ const requestUrl = new URL(request.url);
35
+ if (!requestUrl.hostname.endsWith(`.${scopeAsUrl.hostname}`)) {
36
+ throw new Error(
37
+ `The challenge resource '${scopeAsUrl.hostname}' does not match the requested domain. Set disableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information.`
38
+ );
39
+ }
22
40
  }
23
- /**
24
- * Name of the Key Vault authentication policy.
25
- */
26
- exports.keyVaultAuthenticationPolicyName = "keyVaultAuthenticationPolicy";
27
- /**
28
- * A custom implementation of the bearer-token authentication policy that handles Key Vault and CAE challenges.
29
- *
30
- * Key Vault supports other authentication schemes, but we ensure challenge authentication
31
- * is used by first sending a copy of the request, without authorization or content.
32
- *
33
- * when the challenge is received, it will be authenticated and used to send the original
34
- * request with authorization.
35
- *
36
- * Following the first request of a client, follow-up requests will get the cached token
37
- * if possible.
38
- *
39
- */
41
+ const keyVaultAuthenticationPolicyName = "keyVaultAuthenticationPolicy";
40
42
  function keyVaultAuthenticationPolicy(credential, options = {}) {
41
- const { disableChallengeResourceVerification } = options;
42
- let challengeState = { status: "none" };
43
- const getAccessToken = (0, tokenCycler_js_1.createTokenCycler)(credential);
44
- function requestToOptions(request) {
45
- return {
46
- abortSignal: request.abortSignal,
47
- requestOptions: {
48
- timeout: request.timeout > 0 ? request.timeout : undefined,
49
- },
50
- tracingOptions: request.tracingOptions,
43
+ const { disableChallengeResourceVerification } = options;
44
+ let challengeState = { status: "none" };
45
+ const getAccessToken = (0, import_tokenCycler.createTokenCycler)(credential);
46
+ function requestToOptions(request) {
47
+ return {
48
+ abortSignal: request.abortSignal,
49
+ requestOptions: {
50
+ timeout: request.timeout > 0 ? request.timeout : void 0
51
+ },
52
+ tracingOptions: request.tracingOptions
53
+ };
54
+ }
55
+ async function authorizeRequest(request) {
56
+ const requestOptions = requestToOptions(request);
57
+ switch (challengeState.status) {
58
+ case "none":
59
+ challengeState = {
60
+ status: "started",
61
+ originalBody: request.body
51
62
  };
52
- }
53
- async function authorizeRequest(request) {
54
- const requestOptions = requestToOptions(request);
55
- switch (challengeState.status) {
56
- case "none":
57
- challengeState = {
58
- status: "started",
59
- originalBody: request.body,
60
- };
61
- request.body = null;
62
- break;
63
- case "started":
64
- break; // Retry, we should not overwrite the original body
65
- case "complete": {
66
- const token = await getAccessToken(challengeState.scopes, {
67
- ...requestOptions,
68
- enableCae: true,
69
- tenantId: challengeState.tenantId,
70
- });
71
- if (token) {
72
- request.headers.set("authorization", `Bearer ${token.token}`);
73
- }
74
- break;
75
- }
76
- }
77
- }
78
- async function handleChallenge(request, response, next) {
79
- // If status is not 401, this is a no-op
80
- if (response.status !== 401) {
81
- return response;
82
- }
83
- if (request.body === null && challengeState.status === "started") {
84
- // Reset the original body before doing anything else.
85
- // Note: If successful status will be "complete", otherwise "none" will
86
- // restart the process.
87
- request.body = challengeState.originalBody;
88
- }
89
- const getTokenOptions = requestToOptions(request);
90
- const challenge = response.headers.get("WWW-Authenticate");
91
- if (!challenge) {
92
- logger_js_1.logger.warning("keyVaultAuthentication policy encountered a 401 response without a corresponding WWW-Authenticate header. This is unexpected. Not handling the 401 response.");
93
- return response;
94
- }
95
- const parsedChallenge = (0, parseWWWAuthenticate_js_1.parseWWWAuthenticateHeader)(challenge);
96
- const scope = parsedChallenge.resource
97
- ? parsedChallenge.resource + "/.default"
98
- : parsedChallenge.scope;
99
- if (!scope) {
100
- // Cannot handle this kind of challenge here (if scope is not present, may be a CAE challenge)
101
- return response;
102
- }
103
- if (!disableChallengeResourceVerification) {
104
- verifyChallengeResource(scope, request);
105
- }
106
- const accessToken = await getAccessToken([scope], {
107
- ...getTokenOptions,
108
- enableCae: true,
109
- tenantId: parsedChallenge.tenantId,
63
+ request.body = null;
64
+ break;
65
+ case "started":
66
+ break;
67
+ // Retry, we should not overwrite the original body
68
+ case "complete": {
69
+ const token = await getAccessToken(challengeState.scopes, {
70
+ ...requestOptions,
71
+ enableCae: true,
72
+ tenantId: challengeState.tenantId
110
73
  });
111
- if (!accessToken) {
112
- // No access token provided, treat as no-op
113
- return response;
74
+ if (token) {
75
+ request.headers.set("authorization", `Bearer ${token.token}`);
114
76
  }
115
- request.headers.set("Authorization", `Bearer ${accessToken.token}`);
116
- challengeState = {
117
- status: "complete",
118
- scopes: [scope],
119
- tenantId: parsedChallenge.tenantId,
120
- };
121
- // We have a token now, so try send the request again
122
- return next(request);
77
+ break;
78
+ }
123
79
  }
124
- async function handleCaeChallenge(request, response, next) {
125
- // Cannot handle CAE challenge if a regular challenge has not been completed first
126
- if (challengeState.status !== "complete") {
127
- return response;
128
- }
129
- // If status is not 401, this is a no-op
130
- if (response.status !== 401) {
131
- return response;
132
- }
133
- const getTokenOptions = requestToOptions(request);
134
- const challenge = response.headers.get("WWW-Authenticate");
135
- if (!challenge) {
136
- return response;
137
- }
138
- const { claims: base64EncodedClaims, error } = (0, parseWWWAuthenticate_js_1.parseWWWAuthenticateHeader)(challenge);
139
- if (error !== "insufficient_claims" || base64EncodedClaims === undefined) {
140
- return response;
141
- }
142
- const claims = atob(base64EncodedClaims);
143
- const accessToken = await getAccessToken(challengeState.scopes, {
144
- ...getTokenOptions,
145
- enableCae: true,
146
- tenantId: challengeState.tenantId,
147
- claims,
148
- });
149
- request.headers.set("Authorization", `Bearer ${accessToken.token}`);
150
- return next(request);
80
+ }
81
+ async function handleChallenge(request, response, next) {
82
+ if (response.status !== 401) {
83
+ return response;
151
84
  }
152
- async function sendRequest(request, next) {
153
- // Add token if possible
154
- await authorizeRequest(request);
155
- // Try send request (first attempt)
156
- let response = await next(request);
157
- // Handle standard challenge if present
158
- response = await handleChallenge(request, response, next);
159
- // Handle CAE challenge if present
160
- response = await handleCaeChallenge(request, response, next);
161
- return response;
85
+ if (request.body === null && challengeState.status === "started") {
86
+ request.body = challengeState.originalBody;
162
87
  }
163
- return {
164
- name: exports.keyVaultAuthenticationPolicyName,
165
- sendRequest,
88
+ const getTokenOptions = requestToOptions(request);
89
+ const challenge = response.headers.get("WWW-Authenticate");
90
+ if (!challenge) {
91
+ import_logger.logger.warning(
92
+ "keyVaultAuthentication policy encountered a 401 response without a corresponding WWW-Authenticate header. This is unexpected. Not handling the 401 response."
93
+ );
94
+ return response;
95
+ }
96
+ const parsedChallenge = (0, import_parseWWWAuthenticate.parseWWWAuthenticateHeader)(challenge);
97
+ const scope = parsedChallenge.resource ? parsedChallenge.resource + "/.default" : parsedChallenge.scope;
98
+ if (!scope) {
99
+ return response;
100
+ }
101
+ if (!disableChallengeResourceVerification) {
102
+ verifyChallengeResource(scope, request);
103
+ }
104
+ const accessToken = await getAccessToken([scope], {
105
+ ...getTokenOptions,
106
+ enableCae: true,
107
+ tenantId: parsedChallenge.tenantId
108
+ });
109
+ if (!accessToken) {
110
+ return response;
111
+ }
112
+ request.headers.set("Authorization", `Bearer ${accessToken.token}`);
113
+ challengeState = {
114
+ status: "complete",
115
+ scopes: [scope],
116
+ tenantId: parsedChallenge.tenantId
166
117
  };
118
+ return next(request);
119
+ }
120
+ async function handleCaeChallenge(request, response, next) {
121
+ if (challengeState.status !== "complete") {
122
+ return response;
123
+ }
124
+ if (response.status !== 401) {
125
+ return response;
126
+ }
127
+ const getTokenOptions = requestToOptions(request);
128
+ const challenge = response.headers.get("WWW-Authenticate");
129
+ if (!challenge) {
130
+ return response;
131
+ }
132
+ const { claims: base64EncodedClaims, error } = (0, import_parseWWWAuthenticate.parseWWWAuthenticateHeader)(challenge);
133
+ if (error !== "insufficient_claims" || base64EncodedClaims === void 0) {
134
+ return response;
135
+ }
136
+ const claims = atob(base64EncodedClaims);
137
+ const accessToken = await getAccessToken(challengeState.scopes, {
138
+ ...getTokenOptions,
139
+ enableCae: true,
140
+ tenantId: challengeState.tenantId,
141
+ claims
142
+ });
143
+ request.headers.set("Authorization", `Bearer ${accessToken.token}`);
144
+ return next(request);
145
+ }
146
+ async function sendRequest(request, next) {
147
+ await authorizeRequest(request);
148
+ let response = await next(request);
149
+ response = await handleChallenge(request, response, next);
150
+ response = await handleCaeChallenge(request, response, next);
151
+ return response;
152
+ }
153
+ return {
154
+ name: keyVaultAuthenticationPolicyName,
155
+ sendRequest
156
+ };
167
157
  }
168
- //# sourceMappingURL=keyVaultAuthenticationPolicy.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"keyVaultAuthenticationPolicy.js","sourceRoot":"","sources":["../../src/keyVaultAuthenticationPolicy.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n PipelinePolicy,\n PipelineRequest,\n PipelineResponse,\n RequestBodyType,\n SendRequest,\n} from \"@azure/core-rest-pipeline\";\nimport type { WWWAuthenticate } from \"./parseWWWAuthenticate.js\";\nimport { parseWWWAuthenticateHeader } from \"./parseWWWAuthenticate.js\";\n\nimport type { GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { createTokenCycler } from \"./tokenCycler.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * @internal\n * Holds the state of Challenge Auth.\n * When making the first request we force Key Vault to begin a challenge\n * by clearing out the request body and storing it locally.\n *\n * Later on, the authorizeRequestOnChallenge callback will process the\n * challenge and, if ready to resend the original request, reset the body\n * so that it may be sent again.\n *\n * Once a client has succeeded once, we can start skipping CAE.\n */\ntype ChallengeState =\n | {\n status: \"none\";\n }\n | {\n status: \"started\";\n originalBody?: RequestBodyType;\n }\n | {\n status: \"complete\";\n scopes: string[];\n tenantId?: string;\n };\n\n/**\n * Additional options for the challenge based authentication policy.\n */\nexport interface KeyVaultAuthenticationPolicyOptions {\n /**\n * Whether to disable verification that the challenge resource matches the Key Vault or Managed HSM domain.\n *\n * Defaults to false.\n */\n disableChallengeResourceVerification?: boolean;\n}\n\nfunction verifyChallengeResource(scope: string, request: PipelineRequest): void {\n let scopeAsUrl: URL;\n try {\n scopeAsUrl = new URL(scope);\n } catch (e) {\n throw new Error(`The challenge contains invalid scope '${scope}'`);\n }\n\n const requestUrl = new URL(request.url);\n\n if (!requestUrl.hostname.endsWith(`.${scopeAsUrl.hostname}`)) {\n throw new Error(\n `The challenge resource '${scopeAsUrl.hostname}' does not match the requested domain. Set disableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information.`,\n );\n }\n}\n\n/**\n * Name of the Key Vault authentication policy.\n */\nexport const keyVaultAuthenticationPolicyName = \"keyVaultAuthenticationPolicy\";\n\n/**\n * A custom implementation of the bearer-token authentication policy that handles Key Vault and CAE challenges.\n *\n * Key Vault supports other authentication schemes, but we ensure challenge authentication\n * is used by first sending a copy of the request, without authorization or content.\n *\n * when the challenge is received, it will be authenticated and used to send the original\n * request with authorization.\n *\n * Following the first request of a client, follow-up requests will get the cached token\n * if possible.\n *\n */\nexport function keyVaultAuthenticationPolicy(\n credential: TokenCredential,\n options: KeyVaultAuthenticationPolicyOptions = {},\n): PipelinePolicy {\n const { disableChallengeResourceVerification } = options;\n let challengeState: ChallengeState = { status: \"none\" };\n const getAccessToken = createTokenCycler(credential);\n\n function requestToOptions(request: PipelineRequest): GetTokenOptions {\n return {\n abortSignal: request.abortSignal,\n requestOptions: {\n timeout: request.timeout > 0 ? request.timeout : undefined,\n },\n tracingOptions: request.tracingOptions,\n };\n }\n\n async function authorizeRequest(request: PipelineRequest): Promise<void> {\n const requestOptions: GetTokenOptions = requestToOptions(request);\n\n switch (challengeState.status) {\n case \"none\":\n challengeState = {\n status: \"started\",\n originalBody: request.body,\n };\n request.body = null;\n break;\n case \"started\":\n break; // Retry, we should not overwrite the original body\n case \"complete\": {\n const token = await getAccessToken(challengeState.scopes, {\n ...requestOptions,\n enableCae: true,\n tenantId: challengeState.tenantId,\n });\n if (token) {\n request.headers.set(\"authorization\", `Bearer ${token.token}`);\n }\n break;\n }\n }\n }\n\n async function handleChallenge(\n request: PipelineRequest,\n response: PipelineResponse,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // If status is not 401, this is a no-op\n if (response.status !== 401) {\n return response;\n }\n\n if (request.body === null && challengeState.status === \"started\") {\n // Reset the original body before doing anything else.\n // Note: If successful status will be \"complete\", otherwise \"none\" will\n // restart the process.\n request.body = challengeState.originalBody;\n }\n\n const getTokenOptions = requestToOptions(request);\n\n const challenge = response.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n logger.warning(\n \"keyVaultAuthentication policy encountered a 401 response without a corresponding WWW-Authenticate header. This is unexpected. Not handling the 401 response.\",\n );\n return response;\n }\n const parsedChallenge: WWWAuthenticate = parseWWWAuthenticateHeader(challenge);\n\n const scope = parsedChallenge.resource\n ? parsedChallenge.resource + \"/.default\"\n : parsedChallenge.scope;\n\n if (!scope) {\n // Cannot handle this kind of challenge here (if scope is not present, may be a CAE challenge)\n return response;\n }\n\n if (!disableChallengeResourceVerification) {\n verifyChallengeResource(scope, request);\n }\n\n const accessToken = await getAccessToken([scope], {\n ...getTokenOptions,\n enableCae: true,\n tenantId: parsedChallenge.tenantId,\n });\n\n if (!accessToken) {\n // No access token provided, treat as no-op\n return response;\n }\n\n request.headers.set(\"Authorization\", `Bearer ${accessToken.token}`);\n\n challengeState = {\n status: \"complete\",\n scopes: [scope],\n tenantId: parsedChallenge.tenantId,\n };\n\n // We have a token now, so try send the request again\n return next(request);\n }\n\n async function handleCaeChallenge(\n request: PipelineRequest,\n response: PipelineResponse,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // Cannot handle CAE challenge if a regular challenge has not been completed first\n if (challengeState.status !== \"complete\") {\n return response;\n }\n\n // If status is not 401, this is a no-op\n if (response.status !== 401) {\n return response;\n }\n\n const getTokenOptions = requestToOptions(request);\n\n const challenge = response.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n return response;\n }\n const { claims: base64EncodedClaims, error }: WWWAuthenticate =\n parseWWWAuthenticateHeader(challenge);\n\n if (error !== \"insufficient_claims\" || base64EncodedClaims === undefined) {\n return response;\n }\n\n const claims = atob(base64EncodedClaims);\n\n const accessToken = await getAccessToken(challengeState.scopes, {\n ...getTokenOptions,\n enableCae: true,\n tenantId: challengeState.tenantId,\n claims,\n });\n\n request.headers.set(\"Authorization\", `Bearer ${accessToken.token}`);\n\n return next(request);\n }\n\n async function sendRequest(\n request: PipelineRequest,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // Add token if possible\n await authorizeRequest(request);\n\n // Try send request (first attempt)\n let response = await next(request);\n\n // Handle standard challenge if present\n response = await handleChallenge(request, response, next);\n\n // Handle CAE challenge if present\n response = await handleCaeChallenge(request, response, next);\n\n return response;\n }\n\n return {\n name: keyVaultAuthenticationPolicyName,\n sendRequest,\n };\n}\n"]}
1
+ {
2
+ "version": 3,
3
+ "sources": ["/mnt/vss/_work/1/s/sdk/keyvault/keyvault-common/src/keyVaultAuthenticationPolicy.ts"],
4
+ "sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n PipelinePolicy,\n PipelineRequest,\n PipelineResponse,\n RequestBodyType,\n SendRequest,\n} from \"@azure/core-rest-pipeline\";\nimport type { WWWAuthenticate } from \"./parseWWWAuthenticate.js\";\nimport { parseWWWAuthenticateHeader } from \"./parseWWWAuthenticate.js\";\n\nimport type { GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { createTokenCycler } from \"./tokenCycler.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * @internal\n * Holds the state of Challenge Auth.\n * When making the first request we force Key Vault to begin a challenge\n * by clearing out the request body and storing it locally.\n *\n * Later on, the authorizeRequestOnChallenge callback will process the\n * challenge and, if ready to resend the original request, reset the body\n * so that it may be sent again.\n *\n * Once a client has succeeded once, we can start skipping CAE.\n */\ntype ChallengeState =\n | {\n status: \"none\";\n }\n | {\n status: \"started\";\n originalBody?: RequestBodyType;\n }\n | {\n status: \"complete\";\n scopes: string[];\n tenantId?: string;\n };\n\n/**\n * Additional options for the challenge based authentication policy.\n */\nexport interface KeyVaultAuthenticationPolicyOptions {\n /**\n * Whether to disable verification that the challenge resource matches the Key Vault or Managed HSM domain.\n *\n * Defaults to false.\n */\n disableChallengeResourceVerification?: boolean;\n}\n\nfunction verifyChallengeResource(scope: string, request: PipelineRequest): void {\n let scopeAsUrl: URL;\n try {\n scopeAsUrl = new URL(scope);\n } catch (e) {\n throw new Error(`The challenge contains invalid scope '${scope}'`);\n }\n\n const requestUrl = new URL(request.url);\n\n if (!requestUrl.hostname.endsWith(`.${scopeAsUrl.hostname}`)) {\n throw new Error(\n `The challenge resource '${scopeAsUrl.hostname}' does not match the requested domain. Set disableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information.`,\n );\n }\n}\n\n/**\n * Name of the Key Vault authentication policy.\n */\nexport const keyVaultAuthenticationPolicyName = \"keyVaultAuthenticationPolicy\";\n\n/**\n * A custom implementation of the bearer-token authentication policy that handles Key Vault and CAE challenges.\n *\n * Key Vault supports other authentication schemes, but we ensure challenge authentication\n * is used by first sending a copy of the request, without authorization or content.\n *\n * when the challenge is received, it will be authenticated and used to send the original\n * request with authorization.\n *\n * Following the first request of a client, follow-up requests will get the cached token\n * if possible.\n *\n */\nexport function keyVaultAuthenticationPolicy(\n credential: TokenCredential,\n options: KeyVaultAuthenticationPolicyOptions = {},\n): PipelinePolicy {\n const { disableChallengeResourceVerification } = options;\n let challengeState: ChallengeState = { status: \"none\" };\n const getAccessToken = createTokenCycler(credential);\n\n function requestToOptions(request: PipelineRequest): GetTokenOptions {\n return {\n abortSignal: request.abortSignal,\n requestOptions: {\n timeout: request.timeout > 0 ? request.timeout : undefined,\n },\n tracingOptions: request.tracingOptions,\n };\n }\n\n async function authorizeRequest(request: PipelineRequest): Promise<void> {\n const requestOptions: GetTokenOptions = requestToOptions(request);\n\n switch (challengeState.status) {\n case \"none\":\n challengeState = {\n status: \"started\",\n originalBody: request.body,\n };\n request.body = null;\n break;\n case \"started\":\n break; // Retry, we should not overwrite the original body\n case \"complete\": {\n const token = await getAccessToken(challengeState.scopes, {\n ...requestOptions,\n enableCae: true,\n tenantId: challengeState.tenantId,\n });\n if (token) {\n request.headers.set(\"authorization\", `Bearer ${token.token}`);\n }\n break;\n }\n }\n }\n\n async function handleChallenge(\n request: PipelineRequest,\n response: PipelineResponse,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // If status is not 401, this is a no-op\n if (response.status !== 401) {\n return response;\n }\n\n if (request.body === null && challengeState.status === \"started\") {\n // Reset the original body before doing anything else.\n // Note: If successful status will be \"complete\", otherwise \"none\" will\n // restart the process.\n request.body = challengeState.originalBody;\n }\n\n const getTokenOptions = requestToOptions(request);\n\n const challenge = response.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n logger.warning(\n \"keyVaultAuthentication policy encountered a 401 response without a corresponding WWW-Authenticate header. This is unexpected. Not handling the 401 response.\",\n );\n return response;\n }\n const parsedChallenge: WWWAuthenticate = parseWWWAuthenticateHeader(challenge);\n\n const scope = parsedChallenge.resource\n ? parsedChallenge.resource + \"/.default\"\n : parsedChallenge.scope;\n\n if (!scope) {\n // Cannot handle this kind of challenge here (if scope is not present, may be a CAE challenge)\n return response;\n }\n\n if (!disableChallengeResourceVerification) {\n verifyChallengeResource(scope, request);\n }\n\n const accessToken = await getAccessToken([scope], {\n ...getTokenOptions,\n enableCae: true,\n tenantId: parsedChallenge.tenantId,\n });\n\n if (!accessToken) {\n // No access token provided, treat as no-op\n return response;\n }\n\n request.headers.set(\"Authorization\", `Bearer ${accessToken.token}`);\n\n challengeState = {\n status: \"complete\",\n scopes: [scope],\n tenantId: parsedChallenge.tenantId,\n };\n\n // We have a token now, so try send the request again\n return next(request);\n }\n\n async function handleCaeChallenge(\n request: PipelineRequest,\n response: PipelineResponse,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // Cannot handle CAE challenge if a regular challenge has not been completed first\n if (challengeState.status !== \"complete\") {\n return response;\n }\n\n // If status is not 401, this is a no-op\n if (response.status !== 401) {\n return response;\n }\n\n const getTokenOptions = requestToOptions(request);\n\n const challenge = response.headers.get(\"WWW-Authenticate\");\n if (!challenge) {\n return response;\n }\n const { claims: base64EncodedClaims, error }: WWWAuthenticate =\n parseWWWAuthenticateHeader(challenge);\n\n if (error !== \"insufficient_claims\" || base64EncodedClaims === undefined) {\n return response;\n }\n\n const claims = atob(base64EncodedClaims);\n\n const accessToken = await getAccessToken(challengeState.scopes, {\n ...getTokenOptions,\n enableCae: true,\n tenantId: challengeState.tenantId,\n claims,\n });\n\n request.headers.set(\"Authorization\", `Bearer ${accessToken.token}`);\n\n return next(request);\n }\n\n async function sendRequest(\n request: PipelineRequest,\n next: SendRequest,\n ): Promise<PipelineResponse> {\n // Add token if possible\n await authorizeRequest(request);\n\n // Try send request (first attempt)\n let response = await next(request);\n\n // Handle standard challenge if present\n response = await handleChallenge(request, response, next);\n\n // Handle CAE challenge if present\n response = await handleCaeChallenge(request, response, next);\n\n return response;\n }\n\n return {\n name: keyVaultAuthenticationPolicyName,\n sendRequest,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,8 +1,24 @@
1
- "use strict";
2
- // Copyright (c) Microsoft Corporation.
3
- // Licensed under the MIT License.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.logger = void 0;
6
- const logger_1 = require("@azure/logger");
7
- exports.logger = (0, logger_1.createClientLogger)("keyvault-common");
8
- //# sourceMappingURL=logger.js.map
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var logger_exports = {};
19
+ __export(logger_exports, {
20
+ logger: () => logger
21
+ });
22
+ module.exports = __toCommonJS(logger_exports);
23
+ var import_logger = require("@azure/logger");
24
+ const logger = (0, import_logger.createClientLogger)("keyvault-common");
@@ -1 +1,7 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAElC,0CAAmD;AAEtC,QAAA,MAAM,GAAG,IAAA,2BAAkB,EAAC,iBAAiB,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { createClientLogger } from \"@azure/logger\";\n\nexport const logger = createClientLogger(\"keyvault-common\");\n"]}
1
+ {
2
+ "version": 3,
3
+ "sources": ["/mnt/vss/_work/1/s/sdk/keyvault/keyvault-common/src/logger.ts"],
4
+ "sourcesContent": ["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { createClientLogger } from \"@azure/logger\";\n\nexport const logger = createClientLogger(\"keyvault-common\");\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,oBAAmC;AAE5B,MAAM,aAAS,kCAAmB,iBAAiB;",
6
+ "names": []
7
+ }