@azure/identity 4.1.1-alpha.20240416.1 → 4.1.1-alpha.20240418.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.
Potentially problematic release.
This version of @azure/identity might be problematic. Click here for more details.
- package/dist/index.js +796 -648
- package/dist/index.js.map +1 -1
- package/dist-esm/src/credentials/clientAssertionCredential.js +5 -4
- package/dist-esm/src/credentials/clientAssertionCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +63 -11
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +4 -6
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClient.js +34 -11
- package/dist-esm/src/msal/nodeFlows/msalClient.js.map +1 -1
- package/dist-esm/src/msal/types.js.map +1 -1
- package/package.json +1 -1
- package/types/identity.d.ts +9 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
|
3
4
|
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
4
|
-
import { MsalClientAssertion } from "../msal/nodeFlows/msalClientAssertion";
|
|
5
5
|
import { credentialLogger } from "../util/logging";
|
|
6
6
|
import { tracingClient } from "../util/tracing";
|
|
7
7
|
const logger = credentialLogger("ClientAssertionCredential");
|
|
@@ -25,9 +25,9 @@ export class ClientAssertionCredential {
|
|
|
25
25
|
}
|
|
26
26
|
this.tenantId = tenantId;
|
|
27
27
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
28
|
-
this.clientId = clientId;
|
|
29
28
|
this.options = options;
|
|
30
|
-
this.
|
|
29
|
+
this.getAssertion = getAssertion;
|
|
30
|
+
this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger, tokenCredentialOptions: this.options }));
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -40,8 +40,9 @@ export class ClientAssertionCredential {
|
|
|
40
40
|
async getToken(scopes, options = {}) {
|
|
41
41
|
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
|
|
42
42
|
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
|
|
43
|
+
const clientAssertion = await this.getAssertion();
|
|
43
44
|
const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
44
|
-
return this.
|
|
45
|
+
return this.msalClient.getTokenByClientAssertion(arrayScopes, clientAssertion, newOptions);
|
|
45
46
|
});
|
|
46
47
|
}
|
|
47
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientAssertionCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientAssertionCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"clientAssertionCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientAssertionCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAc,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,OAAO,yBAAyB;IAOpC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAmC,EACnC,UAA4C,EAAE;QAE9C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,kCAChD,OAAO,KACV,MAAM,EACN,sBAAsB,EAAE,IAAI,CAAC,OAAO,IACpC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,aAAa,CAAC,QAAQ,CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EACnC,OAAO,EACP,KAAK,EAAE,UAAU,EAAE,EAAE;YACnB,UAAU,CAAC,QAAQ,GAAG,yBAAyB,CAC7C,IAAI,CAAC,QAAQ,EACb,UAAU,EACV,IAAI,CAAC,4BAA4B,EACjC,MAAM,CACP,CAAC;YAEF,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,WAAW,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAC7F,CAAC,CACF,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { ClientAssertionCredentialOptions } from \"./clientAssertionCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"ClientAssertionCredential\");\n\n/**\n * Authenticates a service principal with a JWT assertion.\n */\nexport class ClientAssertionCredential implements TokenCredential {\n private msalClient: MsalClient;\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private getAssertion: () => Promise<string>;\n private options: ClientAssertionCredentialOptions;\n\n /**\n * Creates an instance of the ClientAssertionCredential with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * assertion provided by the developer through the `getAssertion` function parameter.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param getAssertion - A function that retrieves the assertion for the credential to use.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n getAssertion: () => Promise<string>,\n options: ClientAssertionCredentialOptions = {},\n ) {\n if (!tenantId || !clientId || !getAssertion) {\n throw new Error(\n \"ClientAssertionCredential: tenantId, clientId, and clientAssertion are required parameters.\",\n );\n }\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.options = options;\n this.getAssertion = getAssertion;\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: this.options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(\n `${this.constructor.name}.getToken`,\n options,\n async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const clientAssertion = await this.getAssertion();\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalClient.getTokenByClientAssertion(arrayScopes, clientAssertion, newOptions);\n },\n );\n }\n}\n"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
|
4
|
+
import { createHash, createPrivateKey } from "crypto";
|
|
3
5
|
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
4
|
-
import { MsalClientCertificate } from "../msal/nodeFlows/msalClientCertificate";
|
|
5
6
|
import { credentialLogger } from "../util/logging";
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
6
8
|
import { tracingClient } from "../util/tracing";
|
|
7
9
|
const credentialName = "ClientCertificateCredential";
|
|
8
10
|
const logger = credentialLogger(credentialName);
|
|
@@ -21,24 +23,21 @@ export class ClientCertificateCredential {
|
|
|
21
23
|
}
|
|
22
24
|
this.tenantId = tenantId;
|
|
23
25
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
24
|
-
|
|
26
|
+
this.sendCertificateChain = options.sendCertificateChain;
|
|
27
|
+
this.certificateConfiguration = Object.assign({}, (typeof certificatePathOrConfiguration === "string"
|
|
25
28
|
? {
|
|
26
29
|
certificatePath: certificatePathOrConfiguration,
|
|
27
30
|
}
|
|
28
31
|
: certificatePathOrConfiguration));
|
|
29
|
-
const certificate =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!configuration || !(certificate || certificatePath)) {
|
|
32
|
+
const certificate = this.certificateConfiguration.certificate;
|
|
33
|
+
const certificatePath = this.certificateConfiguration.certificatePath;
|
|
34
|
+
if (!this.certificateConfiguration || !(certificate || certificatePath)) {
|
|
33
35
|
throw new Error(`${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
|
34
36
|
}
|
|
35
37
|
if (certificate && certificatePath) {
|
|
36
38
|
throw new Error(`${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`);
|
|
37
39
|
}
|
|
38
|
-
this.
|
|
39
|
-
logger,
|
|
40
|
-
clientId,
|
|
41
|
-
tenantId, sendCertificateChain: options.sendCertificateChain, tokenCredentialOptions: options }));
|
|
40
|
+
this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger, tokenCredentialOptions: options }));
|
|
42
41
|
}
|
|
43
42
|
/**
|
|
44
43
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -52,8 +51,61 @@ export class ClientCertificateCredential {
|
|
|
52
51
|
return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {
|
|
53
52
|
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
|
|
54
53
|
const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
55
|
-
|
|
54
|
+
const certificate = await this.buildClientCertificate();
|
|
55
|
+
return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
+
async buildClientCertificate() {
|
|
59
|
+
const parts = await this.parseCertificate();
|
|
60
|
+
let privateKey;
|
|
61
|
+
if (this.certificateConfiguration.certificatePassword !== undefined) {
|
|
62
|
+
privateKey = createPrivateKey({
|
|
63
|
+
key: parts.certificateContents,
|
|
64
|
+
passphrase: this.certificateConfiguration.certificatePassword,
|
|
65
|
+
format: "pem",
|
|
66
|
+
})
|
|
67
|
+
.export({
|
|
68
|
+
format: "pem",
|
|
69
|
+
type: "pkcs8",
|
|
70
|
+
})
|
|
71
|
+
.toString();
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
privateKey = parts.certificateContents;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
thumbprint: parts.thumbprint,
|
|
78
|
+
privateKey,
|
|
79
|
+
x5c: parts.x5c,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async parseCertificate() {
|
|
83
|
+
const certificate = this.certificateConfiguration.certificate;
|
|
84
|
+
const certificatePath = this.certificateConfiguration.certificatePath;
|
|
85
|
+
const certificateContents = certificate || (await readFile(certificatePath, "utf8"));
|
|
86
|
+
const x5c = this.sendCertificateChain ? certificateContents : undefined;
|
|
87
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/g;
|
|
88
|
+
const publicKeys = [];
|
|
89
|
+
// Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c
|
|
90
|
+
let match;
|
|
91
|
+
do {
|
|
92
|
+
match = certificatePattern.exec(certificateContents);
|
|
93
|
+
if (match) {
|
|
94
|
+
publicKeys.push(match[3]);
|
|
95
|
+
}
|
|
96
|
+
} while (match);
|
|
97
|
+
if (publicKeys.length === 0) {
|
|
98
|
+
throw new Error("The file at the specified path does not contain a PEM-encoded certificate.");
|
|
99
|
+
}
|
|
100
|
+
const thumbprint = createHash("sha1")
|
|
101
|
+
.update(Buffer.from(publicKeys[0], "base64"))
|
|
102
|
+
.digest("hex")
|
|
103
|
+
.toUpperCase();
|
|
104
|
+
return {
|
|
105
|
+
certificateContents,
|
|
106
|
+
thumbprint,
|
|
107
|
+
x5c,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
58
110
|
}
|
|
59
111
|
//# sourceMappingURL=clientCertificateCredential.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAEhF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,cAAc,GAAG,6BAA6B,CAAC;AACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAqChD;;;;;;;GAOG;AACH,MAAM,OAAO,2BAA2B;IAoDtC,YACE,QAAgB,EAChB,QAAgB,EAChB,8BAAoF,EACpF,UAA8C,EAAE;QAEhD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,cAAc,kDAAkD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QAEF,MAAM,aAAa,qBACd,CAAC,OAAO,8BAA8B,KAAK,QAAQ;YACpD,CAAC,CAAC;gBACE,eAAe,EAAE,8BAA8B;aAChD;YACH,CAAC,CAAC,8BAA8B,CAAC,CACpC,CAAC;QACF,MAAM,WAAW,GAAwB,aAAiD;aACvF,WAAW,CAAC;QACf,MAAM,eAAe,GACnB,aACD,CAAC,eAAe,CAAC;QAClB,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,WAAW,IAAI,eAAe,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,4MAA4M,CAC9N,CAAC;QACJ,CAAC;QACD,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,GAAG,cAAc,wOAAwO,CAC1P,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,qBAAqB,iCACpC,OAAO,KACV,aAAa;YACb,MAAM;YACN,QAAQ;YACR,QAAQ,EACR,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,EAClD,sBAAsB,EAAE,OAAO,IAC/B,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,aAAa,CAAC,QAAQ,CAAC,GAAG,cAAc,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;YACxF,UAAU,CAAC,QAAQ,GAAG,yBAAyB,CAC7C,IAAI,CAAC,QAAQ,EACb,UAAU,EACV,IAAI,CAAC,4BAA4B,EACjC,MAAM,CACP,CAAC;YAEF,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\nimport { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions\";\nimport { MsalClientCertificate } from \"../msal/nodeFlows/msalClientCertificate\";\nimport { MsalFlow } from \"../msal/flows\";\nimport { credentialLogger } from \"../util/logging\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the string contents of a PEM certificate\n */\nexport interface ClientCertificatePEMCertificate {\n /**\n * The PEM-encoded public/private key certificate on the filesystem.\n */\n certificate: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the path to a PEM certificate.\n */\nexport interface ClientCertificatePEMCertificatePath {\n /**\n * The path to the PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with either the string contents of a PEM certificate, or the path to a PEM certificate.\n */\nexport type ClientCertificateCredentialPEMConfiguration =\n | ClientCertificatePEMCertificate\n | ClientCertificatePEMCertificatePath;\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalFlow: MsalFlow;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n const configuration: ClientCertificateCredentialPEMConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate: string | undefined = (configuration as ClientCertificatePEMCertificate)\n .certificate;\n const certificatePath: string | undefined = (\n configuration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n if (!configuration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalFlow = new MsalClientCertificate({\n ...options,\n configuration,\n logger,\n clientId,\n tenantId,\n sendCertificateChain: options.sendCertificateChain,\n tokenCredentialOptions: options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n return this.msalFlow.getToken(arrayScopes, newOptions);\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"clientCertificateCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientCertificateCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport { createHash, createPrivateKey } from \"crypto\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { CertificateParts } from \"../msal/types\";\nimport { ClientCertificateCredentialOptions } from \"./clientCertificateCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { readFile } from \"fs/promises\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst credentialName = \"ClientCertificateCredential\";\nconst logger = credentialLogger(credentialName);\n\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the string contents of a PEM certificate\n */\nexport interface ClientCertificatePEMCertificate {\n /**\n * The PEM-encoded public/private key certificate on the filesystem.\n */\n certificate: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with the path to a PEM certificate.\n */\nexport interface ClientCertificatePEMCertificatePath {\n /**\n * The path to the PEM-encoded public/private key certificate on the filesystem.\n */\n certificatePath: string;\n\n /**\n * The password for the certificate file.\n */\n certificatePassword?: string;\n}\n/**\n * Required configuration options for the {@link ClientCertificateCredential}, with either the string contents of a PEM certificate, or the path to a PEM certificate.\n */\nexport type ClientCertificateCredentialPEMConfiguration =\n | ClientCertificatePEMCertificate\n | ClientCertificatePEMCertificatePath;\n\n/**\n * Enables authentication to Microsoft Entra ID using a PEM-encoded\n * certificate that is assigned to an App Registration. More information\n * on how to configure certificate authentication can be found here:\n *\n * https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#register-your-certificate-with-azure-ad\n *\n */\nexport class ClientCertificateCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private certificateConfiguration: ClientCertificateCredentialPEMConfiguration;\n private sendCertificateChain?: boolean;\n private msalClient: MsalClient;\n\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param certificatePath - The path to a PEM-encoded public/private key certificate on the filesystem.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n certificatePath: string,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the path of the certificate on the filesystem.\n * If the type is ignored, we will throw the value of the path to a PEM certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificatePath,\n options?: ClientCertificateCredentialOptions,\n );\n /**\n * Creates an instance of the ClientCertificateCredential with the details\n * needed to authenticate against Microsoft Entra ID with a certificate.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param configuration - Other parameters required, including the PEM-encoded certificate as a string.\n * If the type is ignored, we will throw the value of the PEM-encoded certificate.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n configuration: ClientCertificatePEMCertificate,\n options?: ClientCertificateCredentialOptions,\n );\n constructor(\n tenantId: string,\n clientId: string,\n certificatePathOrConfiguration: string | ClientCertificateCredentialPEMConfiguration,\n options: ClientCertificateCredentialOptions = {},\n ) {\n if (!tenantId || !clientId) {\n throw new Error(`${credentialName}: tenantId and clientId are required parameters.`);\n }\n\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.sendCertificateChain = options.sendCertificateChain;\n\n this.certificateConfiguration = {\n ...(typeof certificatePathOrConfiguration === \"string\"\n ? {\n certificatePath: certificatePathOrConfiguration,\n }\n : certificatePathOrConfiguration),\n };\n const certificate: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n if (!this.certificateConfiguration || !(certificate || certificatePath)) {\n throw new Error(\n `${credentialName}: Provide either a PEM certificate in string form, or the path to that certificate in the filesystem. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n if (certificate && certificatePath) {\n throw new Error(\n `${credentialName}: To avoid unexpected behaviors, providing both the contents of a PEM certificate and the path to a PEM certificate is forbidden. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.`,\n );\n }\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(`${credentialName}.getToken`, options, async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];\n const certificate = await this.buildClientCertificate();\n return this.msalClient.getTokenByClientCertificate(arrayScopes, certificate, newOptions);\n });\n }\n\n private async buildClientCertificate(): Promise<CertificateParts> {\n const parts = await this.parseCertificate();\n\n let privateKey: string;\n if (this.certificateConfiguration.certificatePassword !== undefined) {\n privateKey = createPrivateKey({\n key: parts.certificateContents,\n passphrase: this.certificateConfiguration.certificatePassword,\n format: \"pem\",\n })\n .export({\n format: \"pem\",\n type: \"pkcs8\",\n })\n .toString();\n } else {\n privateKey = parts.certificateContents;\n }\n\n return {\n thumbprint: parts.thumbprint,\n privateKey,\n x5c: parts.x5c,\n };\n }\n\n private async parseCertificate(): Promise<\n Omit<CertificateParts, \"privateKey\"> & { certificateContents: string }\n > {\n const certificate: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificate\n ).certificate;\n const certificatePath: string | undefined = (\n this.certificateConfiguration as ClientCertificatePEMCertificatePath\n ).certificatePath;\n const certificateContents = certificate || (await readFile(certificatePath!, \"utf8\"));\n const x5c = this.sendCertificateChain ? certificateContents : undefined;\n\n const certificatePattern =\n /(-+BEGIN CERTIFICATE-+)(\\n\\r?|\\r\\n?)([A-Za-z0-9+/\\n\\r]+=*)(\\n\\r?|\\r\\n?)(-+END CERTIFICATE-+)/g;\n const publicKeys: string[] = [];\n\n // Match all possible certificates, in the order they are in the file. These will form the chain that is used for x5c\n let match;\n do {\n match = certificatePattern.exec(certificateContents);\n if (match) {\n publicKeys.push(match[3]);\n }\n } while (match);\n\n if (publicKeys.length === 0) {\n throw new Error(\"The file at the specified path does not contain a PEM-encoded certificate.\");\n }\n\n const thumbprint = createHash(\"sha1\")\n .update(Buffer.from(publicKeys[0], \"base64\"))\n .digest(\"hex\")\n .toUpperCase();\n\n return {\n certificateContents,\n thumbprint,\n x5c,\n };\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
+
import { createMsalClient } from "../msal/nodeFlows/msalClient";
|
|
3
4
|
import { processMultiTenantRequest, resolveAdditionallyAllowedTenantIds, } from "../util/tenantIdUtils";
|
|
4
|
-
import { MsalClientSecret } from "../msal/nodeFlows/msalClientSecret";
|
|
5
5
|
import { credentialLogger } from "../util/logging";
|
|
6
6
|
import { ensureScopes } from "../util/scopeUtils";
|
|
7
7
|
import { tracingClient } from "../util/tracing";
|
|
@@ -29,12 +29,10 @@ export class ClientSecretCredential {
|
|
|
29
29
|
if (!tenantId || !clientId || !clientSecret) {
|
|
30
30
|
throw new Error("ClientSecretCredential: tenantId, clientId, and clientSecret are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.");
|
|
31
31
|
}
|
|
32
|
+
this.clientSecret = clientSecret;
|
|
32
33
|
this.tenantId = tenantId;
|
|
33
34
|
this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
|
|
34
|
-
this.
|
|
35
|
-
clientId,
|
|
36
|
-
tenantId,
|
|
37
|
-
clientSecret, tokenCredentialOptions: options }));
|
|
35
|
+
this.msalClient = createMsalClient(clientId, tenantId, Object.assign(Object.assign({}, options), { logger, tokenCredentialOptions: options }));
|
|
38
36
|
}
|
|
39
37
|
/**
|
|
40
38
|
* Authenticates with Microsoft Entra ID and returns an access token if successful.
|
|
@@ -48,7 +46,7 @@ export class ClientSecretCredential {
|
|
|
48
46
|
return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
|
|
49
47
|
newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger);
|
|
50
48
|
const arrayScopes = ensureScopes(scopes);
|
|
51
|
-
return this.
|
|
49
|
+
return this.msalClient.getTokenByClientSecret(arrayScopes, this.clientSecret, newOptions);
|
|
52
50
|
});
|
|
53
51
|
}
|
|
54
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clientSecretCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientSecretCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"clientSecretCredential.js","sourceRoot":"","sources":["../../../src/credentials/clientSecretCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAGlC,OAAO,EAAc,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EACL,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,MAAM,GAAG,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAsB;IAMjC;;;;;;;;;OASG;IACH,YACE,QAAgB,EAChB,QAAgB,EAChB,YAAoB,EACpB,UAAyC,EAAE;QAE3C,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,4LAA4L,CAC7L,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,4BAA4B,GAAG,mCAAmC,CACrE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,0BAA0B,CACpC,CAAC;QAEF,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,kCAChD,OAAO,KACV,MAAM,EACN,sBAAsB,EAAE,OAAO,IAC/B,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAyB,EAAE,UAA2B,EAAE;QACrE,OAAO,aAAa,CAAC,QAAQ,CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,WAAW,EACnC,OAAO,EACP,KAAK,EAAE,UAAU,EAAE,EAAE;YACnB,UAAU,CAAC,QAAQ,GAAG,yBAAyB,CAC7C,IAAI,CAAC,QAAQ,EACb,UAAU,EACV,IAAI,CAAC,4BAA4B,EACjC,MAAM,CACP,CAAC;YAEF,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAC5F,CAAC,CACF,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, TokenCredential } from \"@azure/core-auth\";\nimport { MsalClient, createMsalClient } from \"../msal/nodeFlows/msalClient\";\nimport {\n processMultiTenantRequest,\n resolveAdditionallyAllowedTenantIds,\n} from \"../util/tenantIdUtils\";\n\nimport { ClientSecretCredentialOptions } from \"./clientSecretCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { ensureScopes } from \"../util/scopeUtils\";\nimport { tracingClient } from \"../util/tracing\";\n\nconst logger = credentialLogger(\"ClientSecretCredential\");\n\n/**\n * Enables authentication to Microsoft Entra ID using a client secret\n * that was generated for an App Registration. More information on how\n * to configure a client secret can be found here:\n *\n * https://learn.microsoft.com/entra/identity-platform/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application\n *\n */\nexport class ClientSecretCredential implements TokenCredential {\n private tenantId: string;\n private additionallyAllowedTenantIds: string[];\n private msalClient: MsalClient;\n private clientSecret: string;\n\n /**\n * Creates an instance of the ClientSecretCredential with the details\n * needed to authenticate against Microsoft Entra ID with a client\n * secret.\n *\n * @param tenantId - The Microsoft Entra tenant (directory) ID.\n * @param clientId - The client (application) ID of an App Registration in the tenant.\n * @param clientSecret - A client secret that was generated for the App Registration.\n * @param options - Options for configuring the client which makes the authentication request.\n */\n constructor(\n tenantId: string,\n clientId: string,\n clientSecret: string,\n options: ClientSecretCredentialOptions = {},\n ) {\n if (!tenantId || !clientId || !clientSecret) {\n throw new Error(\n \"ClientSecretCredential: tenantId, clientId, and clientSecret are required parameters. To troubleshoot, visit https://aka.ms/azsdk/js/identity/serviceprincipalauthentication/troubleshoot.\",\n );\n }\n\n this.clientSecret = clientSecret;\n this.tenantId = tenantId;\n this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(\n options?.additionallyAllowedTenants,\n );\n\n this.msalClient = createMsalClient(clientId, tenantId, {\n ...options,\n logger,\n tokenCredentialOptions: options,\n });\n }\n\n /**\n * Authenticates with Microsoft Entra ID and returns an access token if successful.\n * If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.\n *\n * @param scopes - The list of scopes for which the token will have access.\n * @param options - The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n async getToken(scopes: string | string[], options: GetTokenOptions = {}): Promise<AccessToken> {\n return tracingClient.withSpan(\n `${this.constructor.name}.getToken`,\n options,\n async (newOptions) => {\n newOptions.tenantId = processMultiTenantRequest(\n this.tenantId,\n newOptions,\n this.additionallyAllowedTenantIds,\n logger,\n );\n\n const arrayScopes = ensureScopes(scopes);\n return this.msalClient.getTokenByClientSecret(arrayScopes, this.clientSecret, newOptions);\n },\n );\n }\n}\n"]}
|
|
@@ -153,18 +153,41 @@ To work with multiple accounts for the same Client ID and Tenant ID, please prov
|
|
|
153
153
|
expiresOnTimestamp: response.expiresOn.getTime(),
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
|
+
async function getTokenByClientSecret(scopes, clientSecret, options = {}) {
|
|
157
|
+
msalLogger.getToken.info(`Attempting to acquire token using client secret`);
|
|
158
|
+
state.msalConfig.auth.clientSecret = clientSecret;
|
|
159
|
+
const msalApp = await getConfidentialApp(options);
|
|
160
|
+
return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
|
|
161
|
+
scopes,
|
|
162
|
+
authority: state.msalConfig.auth.authority,
|
|
163
|
+
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
async function getTokenByClientAssertion(scopes, clientAssertion, options = {}) {
|
|
167
|
+
msalLogger.getToken.info(`Attempting to acquire token using client assertion`);
|
|
168
|
+
state.msalConfig.auth.clientAssertion = clientAssertion;
|
|
169
|
+
const msalApp = await getConfidentialApp(options);
|
|
170
|
+
return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
|
|
171
|
+
scopes,
|
|
172
|
+
authority: state.msalConfig.auth.authority,
|
|
173
|
+
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
174
|
+
clientAssertion,
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
async function getTokenByClientCertificate(scopes, certificate, options = {}) {
|
|
178
|
+
msalLogger.getToken.info(`Attempting to acquire token using client certificate`);
|
|
179
|
+
state.msalConfig.auth.clientCertificate = certificate;
|
|
180
|
+
const msalApp = await getConfidentialApp(options);
|
|
181
|
+
return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
|
|
182
|
+
scopes,
|
|
183
|
+
authority: state.msalConfig.auth.authority,
|
|
184
|
+
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
156
187
|
return {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
state.msalConfig.auth.clientSecret = clientSecret;
|
|
161
|
-
const msalApp = await getConfidentialApp(options);
|
|
162
|
-
return withSilentAuthentication(msalApp, scopes, options, () => msalApp.acquireTokenByClientCredential({
|
|
163
|
-
scopes,
|
|
164
|
-
authority: state.msalConfig.auth.authority,
|
|
165
|
-
claims: options === null || options === void 0 ? void 0 : options.claims,
|
|
166
|
-
}));
|
|
167
|
-
},
|
|
188
|
+
getTokenByClientSecret,
|
|
189
|
+
getTokenByClientAssertion,
|
|
190
|
+
getTokenByClientCertificate,
|
|
168
191
|
};
|
|
169
192
|
}
|
|
170
193
|
//# sourceMappingURL=msalClient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"msalClient.js","sourceRoot":"","sources":["../../../../src/msal/nodeFlows/msalClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msal from \"@azure/msal-node\";\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { PluginConfiguration, msalPlugins } from \"./msalPlugins\";\nimport { credentialLogger, formatSuccess } from \"../../util/logging\";\nimport {\n defaultLoggerCallback,\n ensureValidMsalToken,\n getAuthority,\n getKnownAuthorities,\n getMSALLogLevel,\n handleMsalError,\n publicToMsal,\n} from \"../utils\";\n\nimport { AuthenticationRequiredError } from \"../../errors\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { MsalNodeOptions } from \"./msalNodeCommon\";\nimport { getLogLevel } from \"@azure/logger\";\nimport { resolveTenantId } from \"../../util/tenantIdUtils\";\n\n/**\n * The logger for all MsalClient instances.\n */\nconst msalLogger = credentialLogger(\"MsalClient\");\n\n/**\n * Interface for the MSAL (Microsoft Authentication Library) client.\n * This client is used to interact with Microsoft's identity platform.\n */\nexport interface MsalClient {\n /**\n * Retrieves an access token by using a client secret.\n *\n * @param scopes - The scopes for which the access token is requested. These represent the resources that the application wants to access.\n * @param clientSecret - The client secret of the application. This is a credential that the application can use to authenticate itself.\n * @param options - Additional options that may be provided to the method.\n * @returns An access token\n */\n getTokenByClientSecret(\n scopes: string[],\n clientSecret: string,\n options?: GetTokenOptions,\n ): Promise<AccessToken>;\n}\n\n/**\n * Options for creating an instance of the MsalClient.\n */\nexport type MsalClientOptions = Partial<Omit<MsalNodeOptions, \"clientId\" | \"tenantId\">>;\n\n/**\n * Generates the configuration for MSAL (Microsoft Authentication Library).\n *\n * @param clientId - The client ID of the application.\n * @param tenantId - The tenant ID of the Azure Active Directory.\n * @param msalClientOptions - Optional. Additional options for creating the MSAL client.\n * @returns The MSAL configuration object.\n */\nexport function generateMsalConfiguration(\n clientId: string,\n tenantId: string,\n msalClientOptions: MsalClientOptions = {},\n): msal.Configuration {\n const resolvedTenant = resolveTenantId(msalLogger, tenantId, clientId);\n\n // TODO: move and reuse getIdentityClientAuthorityHost\n const authority = getAuthority(\n resolvedTenant,\n msalClientOptions.authorityHost ?? process.env.AZURE_AUTHORITY_HOST,\n );\n\n const httpClient = new IdentityClient({\n ...msalClientOptions.tokenCredentialOptions,\n authorityHost: authority,\n loggingOptions: msalClientOptions.loggingOptions,\n });\n\n const msalConfig: msal.Configuration = {\n auth: {\n clientId,\n authority,\n knownAuthorities: getKnownAuthorities(\n resolvedTenant,\n authority,\n msalClientOptions.disableInstanceDiscovery,\n ),\n },\n system: {\n networkClient: httpClient,\n loggerOptions: {\n loggerCallback: defaultLoggerCallback(msalClientOptions.logger ?? msalLogger),\n logLevel: getMSALLogLevel(getLogLevel()),\n piiLoggingEnabled: msalClientOptions.loggingOptions?.enableUnsafeSupportLogging,\n },\n },\n };\n return msalConfig;\n}\n\n/**\n * Represents the state necessary for the MSAL (Microsoft Authentication Library) client to operate.\n * This includes the MSAL configuration, cached account information, Azure region, and a flag to disable automatic authentication.\n *\n * @internal\n */\ninterface MsalClientState {\n /** The configuration for the MSAL client. */\n msalConfig: msal.Configuration;\n\n /** The cached account information, or null if no account information is cached. */\n cachedAccount: msal.AccountInfo | null;\n\n /** Configured plugins */\n pluginConfiguration: PluginConfiguration;\n\n /** Claims received from challenges, cached for the next request */\n cachedClaims?: string;\n}\n\n/**\n * Creates an instance of the MSAL (Microsoft Authentication Library) client.\n *\n * @param clientId - The client ID of the application.\n * @param tenantId - The tenant ID of the Azure Active Directory.\n * @param createMsalClientOptions - Optional. Additional options for creating the MSAL client.\n * @returns An instance of the MSAL client.\n *\n * @public\n */\nexport function createMsalClient(\n clientId: string,\n tenantId: string,\n createMsalClientOptions: MsalClientOptions = {},\n): MsalClient {\n const state: MsalClientState = {\n msalConfig: generateMsalConfiguration(clientId, tenantId, createMsalClientOptions),\n cachedAccount: createMsalClientOptions.authenticationRecord\n ? publicToMsal(createMsalClientOptions.authenticationRecord)\n : null,\n pluginConfiguration: msalPlugins.generatePluginConfiguration(createMsalClientOptions),\n };\n\n const confidentialApps: Map<string, msal.ConfidentialClientApplication> = new Map();\n async function getConfidentialApp(\n options: GetTokenOptions = {},\n ): Promise<msal.ConfidentialClientApplication> {\n const appKey = options.enableCae ? \"CAE\" : \"default\";\n\n let confidentialClientApp = confidentialApps.get(appKey);\n if (confidentialClientApp) {\n return confidentialClientApp;\n }\n\n // Initialize a new app and cache it\n const cachePlugin = options.enableCae\n ? state.pluginConfiguration.cache.cachePluginCae\n : state.pluginConfiguration.cache.cachePlugin;\n\n state.msalConfig.auth.clientCapabilities = options.enableCae ? [\"cp1\"] : undefined;\n\n confidentialClientApp = new msal.ConfidentialClientApplication({\n ...state.msalConfig,\n broker: { nativeBrokerPlugin: state.pluginConfiguration.broker.nativeBrokerPlugin },\n cache: { cachePlugin: await cachePlugin },\n });\n\n confidentialApps.set(appKey, confidentialClientApp);\n\n return confidentialClientApp;\n }\n\n async function getTokenSilent(\n app: msal.ConfidentialClientApplication | msal.PublicClientApplication,\n scopes: string[],\n options: GetTokenOptions = {},\n ): Promise<msal.AuthenticationResult> {\n if (state.cachedAccount === null) {\n const cache = app.getTokenCache();\n const accounts = await cache.getAllAccounts();\n\n if (accounts === undefined || accounts.length === 0) {\n throw new AuthenticationRequiredError({ scopes });\n }\n\n if (accounts.length > 1) {\n msalLogger.info(`More than one account was found authenticated for this Client ID and Tenant ID.\nHowever, no \"authenticationRecord\" has been provided for this credential,\ntherefore we're unable to pick between these accounts.\nA new login attempt will be requested, to ensure the correct account is picked.\nTo work with multiple accounts for the same Client ID and Tenant ID, please provide an \"authenticationRecord\" when initializing a credential to prevent this from happening.`);\n throw new AuthenticationRequiredError({ scopes });\n }\n\n state.cachedAccount = accounts[0];\n }\n\n // Keep track and reuse the claims we received across challenges\n if (options.claims) {\n state.cachedClaims = options.claims;\n }\n\n // TODO: port over changes for broker\n // https://github.com/Azure/azure-sdk-for-js/blob/727a7208251961b5036d8e1d86edaa944c42e3d6/sdk/identity/identity/src/msal/nodeFlows/msalNodeCommon.ts#L383-L395\n msalLogger.getToken.info(\"Attempting to acquire token silently\");\n return app.acquireTokenSilent({\n account: state.cachedAccount,\n scopes,\n claims: state.cachedClaims,\n });\n }\n\n /**\n * Performs silent authentication using MSAL to acquire an access token.\n * If silent authentication fails, falls back to interactive authentication.\n *\n * @param msalApp - The MSAL application instance.\n * @param scopes - The scopes for which to acquire the access token.\n * @param options - The options for acquiring the access token.\n * @param onAuthenticationRequired - A callback function to handle interactive authentication when silent authentication fails.\n * @returns A promise that resolves to an AccessToken object containing the access token and its expiration timestamp.\n */\n async function withSilentAuthentication(\n msalApp: msal.ConfidentialClientApplication | msal.PublicClientApplication,\n scopes: Array<string>,\n options: GetTokenOptions,\n onAuthenticationRequired: () => Promise<msal.AuthenticationResult | null>,\n ): Promise<AccessToken> {\n let response: msal.AuthenticationResult | null = null;\n try {\n response = await getTokenSilent(msalApp, scopes, options);\n } catch (e: any) {\n if (e.name !== \"AuthenticationRequiredError\") {\n throw e;\n }\n if (createMsalClientOptions.disableAutomaticAuthentication) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Automatic authentication has been disabled. You may call the authentication() method.\",\n });\n }\n }\n\n // Silent authentication failed\n if (response === null) {\n try {\n response = await onAuthenticationRequired();\n } catch (err: any) {\n throw handleMsalError(scopes, err, options);\n }\n }\n\n // At this point we should have a token, process it\n ensureValidMsalToken(scopes, response, options);\n state.cachedAccount = response?.account ?? null;\n\n msalLogger.getToken.info(formatSuccess(scopes));\n\n return {\n token: response.accessToken,\n expiresOnTimestamp: response.expiresOn.getTime(),\n };\n }\n\n return {\n async getTokenByClientSecret(scopes, clientSecret, options = {}) {\n msalLogger.getToken.info(`Attempting to acquire token using client secret`);\n\n // TODO: understand and implement processMultiTenantRequest\n state.msalConfig.auth.clientSecret = clientSecret;\n\n const msalApp = await getConfidentialApp(options);\n\n return withSilentAuthentication(msalApp, scopes, options, () =>\n msalApp.acquireTokenByClientCredential({\n scopes,\n authority: state.msalConfig.auth.authority,\n claims: options?.claims,\n }),\n );\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"msalClient.js","sourceRoot":"","sources":["../../../../src/msal/nodeFlows/msalClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport * as msal from \"@azure/msal-node\";\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { PluginConfiguration, msalPlugins } from \"./msalPlugins\";\nimport { credentialLogger, formatSuccess } from \"../../util/logging\";\nimport {\n defaultLoggerCallback,\n ensureValidMsalToken,\n getAuthority,\n getKnownAuthorities,\n getMSALLogLevel,\n handleMsalError,\n publicToMsal,\n} from \"../utils\";\n\nimport { AuthenticationRequiredError } from \"../../errors\";\nimport { CertificateParts } from \"../types\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { MsalNodeOptions } from \"./msalNodeCommon\";\nimport { getLogLevel } from \"@azure/logger\";\nimport { resolveTenantId } from \"../../util/tenantIdUtils\";\n\n/**\n * The logger for all MsalClient instances.\n */\nconst msalLogger = credentialLogger(\"MsalClient\");\n\n/**\n * Represents a client for interacting with the Microsoft Authentication Library (MSAL).\n */\nexport interface MsalClient {\n /**\n * Retrieves an access token by using a client certificate.\n *\n * @param arrayScopes - The scopes for which the access token is requested. These represent the resources that the application wants to access.\n * @param certificate - The client certificate used for authentication.\n * @param options - Additional options that may be provided to the method.\n * @returns An access token.\n */\n getTokenByClientCertificate(\n arrayScopes: string[],\n certificate: CertificateParts,\n options?: GetTokenOptions,\n ): Promise<AccessToken>;\n\n /**\n * Retrieves an access token by using a client assertion.\n *\n * @param arrayScopes - The scopes for which the access token is requested. These represent the resources that the application wants to access.\n * @param clientAssertion - The client assertion used for authentication.\n * @param options - Additional options that may be provided to the method.\n * @returns An access token.\n */\n getTokenByClientAssertion(\n arrayScopes: string[],\n clientAssertion: string,\n options?: GetTokenOptions,\n ): Promise<AccessToken>;\n\n /**\n * Retrieves an access token by using a client secret.\n *\n * @param scopes - The scopes for which the access token is requested. These represent the resources that the application wants to access.\n * @param clientSecret - The client secret of the application. This is a credential that the application can use to authenticate itself.\n * @param options - Additional options that may be provided to the method.\n * @returns An access token.\n */\n getTokenByClientSecret(\n scopes: string[],\n clientSecret: string,\n options?: GetTokenOptions,\n ): Promise<AccessToken>;\n}\n\n/**\n * Options for creating an instance of the MsalClient.\n */\nexport type MsalClientOptions = Partial<Omit<MsalNodeOptions, \"clientId\" | \"tenantId\">>;\n\n/**\n * Generates the configuration for MSAL (Microsoft Authentication Library).\n *\n * @param clientId - The client ID of the application.\n * @param tenantId - The tenant ID of the Azure Active Directory.\n * @param msalClientOptions - Optional. Additional options for creating the MSAL client.\n * @returns The MSAL configuration object.\n */\nexport function generateMsalConfiguration(\n clientId: string,\n tenantId: string,\n msalClientOptions: MsalClientOptions = {},\n): msal.Configuration {\n const resolvedTenant = resolveTenantId(msalLogger, tenantId, clientId);\n\n // TODO: move and reuse getIdentityClientAuthorityHost\n const authority = getAuthority(\n resolvedTenant,\n msalClientOptions.authorityHost ?? process.env.AZURE_AUTHORITY_HOST,\n );\n\n const httpClient = new IdentityClient({\n ...msalClientOptions.tokenCredentialOptions,\n authorityHost: authority,\n loggingOptions: msalClientOptions.loggingOptions,\n });\n\n const msalConfig: msal.Configuration = {\n auth: {\n clientId,\n authority,\n knownAuthorities: getKnownAuthorities(\n resolvedTenant,\n authority,\n msalClientOptions.disableInstanceDiscovery,\n ),\n },\n system: {\n networkClient: httpClient,\n loggerOptions: {\n loggerCallback: defaultLoggerCallback(msalClientOptions.logger ?? msalLogger),\n logLevel: getMSALLogLevel(getLogLevel()),\n piiLoggingEnabled: msalClientOptions.loggingOptions?.enableUnsafeSupportLogging,\n },\n },\n };\n return msalConfig;\n}\n\n/**\n * Represents the state necessary for the MSAL (Microsoft Authentication Library) client to operate.\n * This includes the MSAL configuration, cached account information, Azure region, and a flag to disable automatic authentication.\n *\n * @internal\n */\ninterface MsalClientState {\n /** The configuration for the MSAL client. */\n msalConfig: msal.Configuration;\n\n /** The cached account information, or null if no account information is cached. */\n cachedAccount: msal.AccountInfo | null;\n\n /** Configured plugins */\n pluginConfiguration: PluginConfiguration;\n\n /** Claims received from challenges, cached for the next request */\n cachedClaims?: string;\n}\n\n/**\n * Creates an instance of the MSAL (Microsoft Authentication Library) client.\n *\n * @param clientId - The client ID of the application.\n * @param tenantId - The tenant ID of the Azure Active Directory.\n * @param createMsalClientOptions - Optional. Additional options for creating the MSAL client.\n * @returns An instance of the MSAL client.\n *\n * @public\n */\nexport function createMsalClient(\n clientId: string,\n tenantId: string,\n createMsalClientOptions: MsalClientOptions = {},\n): MsalClient {\n const state: MsalClientState = {\n msalConfig: generateMsalConfiguration(clientId, tenantId, createMsalClientOptions),\n cachedAccount: createMsalClientOptions.authenticationRecord\n ? publicToMsal(createMsalClientOptions.authenticationRecord)\n : null,\n pluginConfiguration: msalPlugins.generatePluginConfiguration(createMsalClientOptions),\n };\n\n const confidentialApps: Map<string, msal.ConfidentialClientApplication> = new Map();\n async function getConfidentialApp(\n options: GetTokenOptions = {},\n ): Promise<msal.ConfidentialClientApplication> {\n const appKey = options.enableCae ? \"CAE\" : \"default\";\n\n let confidentialClientApp = confidentialApps.get(appKey);\n if (confidentialClientApp) {\n return confidentialClientApp;\n }\n\n // Initialize a new app and cache it\n const cachePlugin = options.enableCae\n ? state.pluginConfiguration.cache.cachePluginCae\n : state.pluginConfiguration.cache.cachePlugin;\n\n state.msalConfig.auth.clientCapabilities = options.enableCae ? [\"cp1\"] : undefined;\n\n confidentialClientApp = new msal.ConfidentialClientApplication({\n ...state.msalConfig,\n broker: { nativeBrokerPlugin: state.pluginConfiguration.broker.nativeBrokerPlugin },\n cache: { cachePlugin: await cachePlugin },\n });\n\n confidentialApps.set(appKey, confidentialClientApp);\n\n return confidentialClientApp;\n }\n\n async function getTokenSilent(\n app: msal.ConfidentialClientApplication | msal.PublicClientApplication,\n scopes: string[],\n options: GetTokenOptions = {},\n ): Promise<msal.AuthenticationResult> {\n if (state.cachedAccount === null) {\n const cache = app.getTokenCache();\n const accounts = await cache.getAllAccounts();\n\n if (accounts === undefined || accounts.length === 0) {\n throw new AuthenticationRequiredError({ scopes });\n }\n\n if (accounts.length > 1) {\n msalLogger.info(`More than one account was found authenticated for this Client ID and Tenant ID.\nHowever, no \"authenticationRecord\" has been provided for this credential,\ntherefore we're unable to pick between these accounts.\nA new login attempt will be requested, to ensure the correct account is picked.\nTo work with multiple accounts for the same Client ID and Tenant ID, please provide an \"authenticationRecord\" when initializing a credential to prevent this from happening.`);\n throw new AuthenticationRequiredError({ scopes });\n }\n\n state.cachedAccount = accounts[0];\n }\n\n // Keep track and reuse the claims we received across challenges\n if (options.claims) {\n state.cachedClaims = options.claims;\n }\n\n // TODO: port over changes for broker\n // https://github.com/Azure/azure-sdk-for-js/blob/727a7208251961b5036d8e1d86edaa944c42e3d6/sdk/identity/identity/src/msal/nodeFlows/msalNodeCommon.ts#L383-L395\n msalLogger.getToken.info(\"Attempting to acquire token silently\");\n return app.acquireTokenSilent({\n account: state.cachedAccount,\n scopes,\n claims: state.cachedClaims,\n });\n }\n\n /**\n * Performs silent authentication using MSAL to acquire an access token.\n * If silent authentication fails, falls back to interactive authentication.\n *\n * @param msalApp - The MSAL application instance.\n * @param scopes - The scopes for which to acquire the access token.\n * @param options - The options for acquiring the access token.\n * @param onAuthenticationRequired - A callback function to handle interactive authentication when silent authentication fails.\n * @returns A promise that resolves to an AccessToken object containing the access token and its expiration timestamp.\n */\n async function withSilentAuthentication(\n msalApp: msal.ConfidentialClientApplication | msal.PublicClientApplication,\n scopes: Array<string>,\n options: GetTokenOptions,\n onAuthenticationRequired: () => Promise<msal.AuthenticationResult | null>,\n ): Promise<AccessToken> {\n let response: msal.AuthenticationResult | null = null;\n try {\n response = await getTokenSilent(msalApp, scopes, options);\n } catch (e: any) {\n if (e.name !== \"AuthenticationRequiredError\") {\n throw e;\n }\n if (createMsalClientOptions.disableAutomaticAuthentication) {\n throw new AuthenticationRequiredError({\n scopes,\n getTokenOptions: options,\n message:\n \"Automatic authentication has been disabled. You may call the authentication() method.\",\n });\n }\n }\n\n // Silent authentication failed\n if (response === null) {\n try {\n response = await onAuthenticationRequired();\n } catch (err: any) {\n throw handleMsalError(scopes, err, options);\n }\n }\n\n // At this point we should have a token, process it\n ensureValidMsalToken(scopes, response, options);\n state.cachedAccount = response?.account ?? null;\n\n msalLogger.getToken.info(formatSuccess(scopes));\n\n return {\n token: response.accessToken,\n expiresOnTimestamp: response.expiresOn.getTime(),\n };\n }\n\n async function getTokenByClientSecret(\n scopes: string[],\n clientSecret: string,\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n msalLogger.getToken.info(`Attempting to acquire token using client secret`);\n\n state.msalConfig.auth.clientSecret = clientSecret;\n\n const msalApp = await getConfidentialApp(options);\n\n return withSilentAuthentication(msalApp, scopes, options, () =>\n msalApp.acquireTokenByClientCredential({\n scopes,\n authority: state.msalConfig.auth.authority,\n claims: options?.claims,\n }),\n );\n }\n\n async function getTokenByClientAssertion(\n scopes: string[],\n clientAssertion: string,\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n msalLogger.getToken.info(`Attempting to acquire token using client assertion`);\n\n state.msalConfig.auth.clientAssertion = clientAssertion;\n\n const msalApp = await getConfidentialApp(options);\n\n return withSilentAuthentication(msalApp, scopes, options, () =>\n msalApp.acquireTokenByClientCredential({\n scopes,\n authority: state.msalConfig.auth.authority,\n claims: options?.claims,\n clientAssertion,\n }),\n );\n }\n\n async function getTokenByClientCertificate(\n scopes: string[],\n certificate: CertificateParts,\n options: GetTokenOptions = {},\n ): Promise<AccessToken> {\n msalLogger.getToken.info(`Attempting to acquire token using client certificate`);\n\n state.msalConfig.auth.clientCertificate = certificate;\n\n const msalApp = await getConfidentialApp(options);\n\n return withSilentAuthentication(msalApp, scopes, options, () =>\n msalApp.acquireTokenByClientCredential({\n scopes,\n authority: state.msalConfig.auth.authority,\n claims: options?.claims,\n }),\n );\n }\n\n return {\n getTokenByClientSecret,\n getTokenByClientAssertion,\n getTokenByClientCertificate,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/msal/types.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * @internal\n */\nexport type AppType = \"public\" | \"confidential\" | \"publicFirst\" | \"confidentialFirst\";\n\n/**\n * The shape we use return the token (and the expiration date).\n * @internal\n */\nexport interface MsalToken {\n accessToken?: string;\n expiresOn: Date | null;\n}\n\n/**\n * Represents a valid (i.e. complete) MSAL token.\n */\nexport type ValidMsalToken = { [P in keyof MsalToken]-?: NonNullable<MsalToken[P]> };\n\n/**\n * Internal representation of MSAL's Account information.\n * Helps us to disambiguate the MSAL classes accross environments.\n * @internal\n */\nexport interface MsalAccountInfo {\n homeAccountId: string;\n environment?: string;\n tenantId: string;\n username: string;\n localAccountId: string;\n name?: string;\n // Leaving idTokenClaims as object since that's how MSAL has this assigned.\n /* eslint-disable-next-line @typescript-eslint/ban-types */\n idTokenClaims?: object;\n}\n\n/**\n * Represents the common properties of any of the MSAL responses.\n * @internal\n */\nexport interface MsalResult {\n authority?: string;\n account: MsalAccountInfo | null;\n accessToken: string;\n expiresOn: Date | null;\n}\n\n/**\n * The record to use to find the cached tokens in the cache.\n */\nexport interface AuthenticationRecord {\n /**\n * The associated authority, if used.\n */\n authority: string;\n /**\n * The home account Id.\n */\n homeAccountId: string;\n /**\n * The associated client ID.\n */\n clientId: string;\n /**\n * The associated tenant ID.\n */\n tenantId: string;\n /**\n * The username of the logged in account.\n */\n username: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/msal/types.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * @internal\n */\nexport type AppType = \"public\" | \"confidential\" | \"publicFirst\" | \"confidentialFirst\";\n\n/**\n * The shape we use return the token (and the expiration date).\n * @internal\n */\nexport interface MsalToken {\n accessToken?: string;\n expiresOn: Date | null;\n}\n\n/**\n * Represents a valid (i.e. complete) MSAL token.\n */\nexport type ValidMsalToken = { [P in keyof MsalToken]-?: NonNullable<MsalToken[P]> };\n\n/**\n * Internal representation of MSAL's Account information.\n * Helps us to disambiguate the MSAL classes accross environments.\n * @internal\n */\nexport interface MsalAccountInfo {\n homeAccountId: string;\n environment?: string;\n tenantId: string;\n username: string;\n localAccountId: string;\n name?: string;\n // Leaving idTokenClaims as object since that's how MSAL has this assigned.\n /* eslint-disable-next-line @typescript-eslint/ban-types */\n idTokenClaims?: object;\n}\n\n/**\n * Represents the common properties of any of the MSAL responses.\n * @internal\n */\nexport interface MsalResult {\n authority?: string;\n account: MsalAccountInfo | null;\n accessToken: string;\n expiresOn: Date | null;\n}\n\n/**\n * The record to use to find the cached tokens in the cache.\n */\nexport interface AuthenticationRecord {\n /**\n * The associated authority, if used.\n */\n authority: string;\n /**\n * The home account Id.\n */\n homeAccountId: string;\n /**\n * The associated client ID.\n */\n clientId: string;\n /**\n * The associated tenant ID.\n */\n tenantId: string;\n /**\n * The username of the logged in account.\n */\n username: string;\n}\n\n/**\n * Represents a parsed certificate\n * @internal\n */\nexport interface CertificateParts {\n /**\n * Hex encoded X.509 SHA-1 thumbprint of the certificate.\n */\n thumbprint: string;\n\n /**\n * The PEM encoded private key.\n */\n privateKey: string;\n /**\n * x5c header.\n */\n x5c?: string;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure/identity",
|
|
3
3
|
"sdk-type": "client",
|
|
4
|
-
"version": "4.1.1-alpha.
|
|
4
|
+
"version": "4.1.1-alpha.20240418.1",
|
|
5
5
|
"description": "Provides credential implementations for Azure SDK libraries that can authenticate with Microsoft Entra ID",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist-esm/src/index.js",
|
package/types/identity.d.ts
CHANGED
|
@@ -520,10 +520,10 @@ export declare class ChainedTokenCredential implements TokenCredential {
|
|
|
520
520
|
* Authenticates a service principal with a JWT assertion.
|
|
521
521
|
*/
|
|
522
522
|
export declare class ClientAssertionCredential implements TokenCredential {
|
|
523
|
-
private
|
|
523
|
+
private msalClient;
|
|
524
524
|
private tenantId;
|
|
525
525
|
private additionallyAllowedTenantIds;
|
|
526
|
-
private
|
|
526
|
+
private getAssertion;
|
|
527
527
|
private options;
|
|
528
528
|
/**
|
|
529
529
|
* Creates an instance of the ClientAssertionCredential with the details
|
|
@@ -564,7 +564,9 @@ export declare interface ClientAssertionCredentialOptions extends MultiTenantTok
|
|
|
564
564
|
export declare class ClientCertificateCredential implements TokenCredential {
|
|
565
565
|
private tenantId;
|
|
566
566
|
private additionallyAllowedTenantIds;
|
|
567
|
-
private
|
|
567
|
+
private certificateConfiguration;
|
|
568
|
+
private sendCertificateChain?;
|
|
569
|
+
private msalClient;
|
|
568
570
|
/**
|
|
569
571
|
* Creates an instance of the ClientCertificateCredential with the details
|
|
570
572
|
* needed to authenticate against Microsoft Entra ID with a certificate.
|
|
@@ -606,6 +608,8 @@ export declare class ClientCertificateCredential implements TokenCredential {
|
|
|
606
608
|
* TokenCredential implementation might make.
|
|
607
609
|
*/
|
|
608
610
|
getToken(scopes: string | string[], options?: GetTokenOptions): Promise<AccessToken>;
|
|
611
|
+
private buildClientCertificate;
|
|
612
|
+
private parseCertificate;
|
|
609
613
|
}
|
|
610
614
|
|
|
611
615
|
/**
|
|
@@ -663,7 +667,8 @@ export declare interface ClientCertificatePEMCertificatePath {
|
|
|
663
667
|
export declare class ClientSecretCredential implements TokenCredential {
|
|
664
668
|
private tenantId;
|
|
665
669
|
private additionallyAllowedTenantIds;
|
|
666
|
-
private
|
|
670
|
+
private msalClient;
|
|
671
|
+
private clientSecret;
|
|
667
672
|
/**
|
|
668
673
|
* Creates an instance of the ClientSecretCredential with the details
|
|
669
674
|
* needed to authenticate against Microsoft Entra ID with a client
|