@azure/identity 1.0.0-preview.1 → 1.0.0-preview.2
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/CHANGELOG.md +24 -0
- package/README.md +50 -23
- package/browser/identity.js +9828 -0
- package/browser/identity.js.map +1 -0
- package/browser/identity.min.js +2 -0
- package/browser/identity.min.js.map +1 -0
- package/dist/index.js +475 -205
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/errors.d.ts +1 -1
- package/dist-esm/src/client/errors.d.ts.map +1 -1
- package/dist-esm/src/client/errors.js +9 -1
- package/dist-esm/src/client/errors.js.map +1 -1
- package/dist-esm/src/client/identityClient.d.ts +20 -17
- package/dist-esm/src/client/identityClient.d.ts.map +1 -1
- package/dist-esm/src/client/identityClient.js +42 -206
- package/dist-esm/src/client/identityClient.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.browser.d.ts +7 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.d.ts.map +1 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js +12 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/clientCertificateCredential.d.ts +5 -5
- package/dist-esm/src/credentials/clientCertificateCredential.d.ts.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +59 -5
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.d.ts +3 -3
- package/dist-esm/src/credentials/clientSecretCredential.d.ts.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +27 -4
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.browser.d.ts +7 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.d.ts.map +1 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js +12 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/deviceCodeCredential.d.ts +67 -0
- package/dist-esm/src/credentials/deviceCodeCredential.d.ts.map +1 -0
- package/dist-esm/src/credentials/deviceCodeCredential.js +139 -0
- package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -0
- package/dist-esm/src/credentials/environmentCredential.browser.d.ts +7 -0
- package/dist-esm/src/credentials/environmentCredential.browser.d.ts.map +1 -0
- package/dist-esm/src/credentials/environmentCredential.browser.js +12 -0
- package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/environmentCredential.d.ts.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +0 -4
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.d.ts +32 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.d.ts.map +1 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +112 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.d.ts +12 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.d.ts.map +1 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +17 -0
- package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -0
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.d.ts +24 -0
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.d.ts.map +1 -0
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js +3 -0
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential.browser.d.ts +7 -0
- package/dist-esm/src/credentials/managedIdentityCredential.browser.d.ts.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential.browser.js +15 -0
- package/dist-esm/src/credentials/managedIdentityCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential.d.ts +10 -1
- package/dist-esm/src/credentials/managedIdentityCredential.d.ts.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential.js +144 -2
- package/dist-esm/src/credentials/managedIdentityCredential.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.d.ts +39 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.d.ts.map +1 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.js +67 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -0
- package/dist-esm/src/index.d.ts +4 -0
- package/dist-esm/src/index.d.ts.map +1 -1
- package/dist-esm/src/index.js +3 -0
- package/dist-esm/src/index.js.map +1 -1
- package/package.json +32 -14
- package/src/client/errors.ts +11 -3
- package/src/client/identityClient.ts +64 -246
- package/src/credentials/clientCertificateCredential.browser.ts +27 -0
- package/src/credentials/clientCertificateCredential.ts +72 -22
- package/src/credentials/clientSecretCredential.ts +32 -17
- package/src/credentials/deviceCodeCredential.browser.ts +27 -0
- package/src/credentials/deviceCodeCredential.ts +203 -0
- package/src/credentials/environmentCredential.browser.ts +19 -0
- package/src/credentials/environmentCredential.ts +5 -9
- package/src/credentials/interactiveBrowserCredential.browser.ts +134 -0
- package/src/credentials/interactiveBrowserCredential.ts +31 -0
- package/src/credentials/interactiveBrowserCredentialOptions.ts +30 -0
- package/src/credentials/managedIdentityCredential.browser.ts +22 -0
- package/src/credentials/managedIdentityCredential.ts +179 -8
- package/src/credentials/usernamePasswordCredential.ts +83 -0
- package/src/index.ts +4 -0
|
@@ -1,26 +1,197 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import qs from "qs";
|
|
5
|
+
import {
|
|
6
|
+
AccessToken,
|
|
7
|
+
GetTokenOptions,
|
|
8
|
+
RequestPrepareOptions,
|
|
9
|
+
RestError,
|
|
10
|
+
TokenCredential
|
|
11
|
+
} from "@azure/core-http";
|
|
5
12
|
import { IdentityClientOptions, IdentityClient } from "../client/identityClient";
|
|
6
13
|
|
|
14
|
+
const DefaultScopeSuffix = "/.default";
|
|
15
|
+
export const ImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
|
|
16
|
+
export const ImdsApiVersion = "2018-02-01";
|
|
17
|
+
export const AppServiceMsiApiVersion = "2017-09-01";
|
|
18
|
+
|
|
7
19
|
/**
|
|
8
20
|
* Attempts authentication using a managed identity that has been assigned
|
|
9
21
|
* to the deployment environment. This authentication type works in Azure VMs,
|
|
10
22
|
* App Service and Azure Functions applications, and inside of Azure Cloud Shell.
|
|
11
|
-
*
|
|
23
|
+
*
|
|
12
24
|
* More information about configuring managed identities can be found here:
|
|
13
|
-
*
|
|
25
|
+
*
|
|
14
26
|
* https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
|
|
15
27
|
*/
|
|
16
28
|
export class ManagedIdentityCredential implements TokenCredential {
|
|
17
29
|
private identityClient: IdentityClient;
|
|
18
|
-
private
|
|
30
|
+
private clientId: string | undefined;
|
|
19
31
|
private isEndpointUnavailable: boolean | null = null;
|
|
20
32
|
|
|
21
33
|
constructor(clientId?: string, options?: IdentityClientOptions) {
|
|
22
34
|
this.identityClient = new IdentityClient(options);
|
|
23
|
-
this.
|
|
35
|
+
this.clientId = clientId;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private mapScopesToResource(scopes: string | string[]): string {
|
|
39
|
+
let scope = "";
|
|
40
|
+
if (Array.isArray(scopes)) {
|
|
41
|
+
if (scopes.length !== 1) {
|
|
42
|
+
throw "To convert to a resource string the specified array must be exactly length 1";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
scope = scopes[0];
|
|
46
|
+
} else if (typeof scopes === "string") {
|
|
47
|
+
scope = scopes;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!scope.endsWith(DefaultScopeSuffix)) {
|
|
51
|
+
return scope;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private createImdsAuthRequest(resource: string, clientId?: string): RequestPrepareOptions {
|
|
58
|
+
const queryParameters: any = {
|
|
59
|
+
resource,
|
|
60
|
+
"api-version": ImdsApiVersion
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
if (clientId) {
|
|
64
|
+
queryParameters.client_id = clientId;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
url: ImdsEndpoint,
|
|
69
|
+
method: "GET",
|
|
70
|
+
queryParameters,
|
|
71
|
+
headers: {
|
|
72
|
+
Accept: "application/json",
|
|
73
|
+
Metadata: true
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private createAppServiceMsiAuthRequest(resource: string, clientId?: string): RequestPrepareOptions {
|
|
79
|
+
const queryParameters: any = {
|
|
80
|
+
resource,
|
|
81
|
+
"api-version": AppServiceMsiApiVersion,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (clientId) {
|
|
85
|
+
queryParameters.client_id = clientId;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
url: process.env.MSI_ENDPOINT,
|
|
90
|
+
method: "GET",
|
|
91
|
+
queryParameters,
|
|
92
|
+
headers: {
|
|
93
|
+
Accept: "application/json",
|
|
94
|
+
secret: process.env.MSI_SECRET
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private createCloudShellMsiAuthRequest(resource: string, clientId?: string): RequestPrepareOptions {
|
|
100
|
+
const body: any = {
|
|
101
|
+
resource
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
if (clientId) {
|
|
105
|
+
body.client_id = clientId;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
url: process.env.MSI_ENDPOINT,
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: qs.stringify(body),
|
|
112
|
+
headers: {
|
|
113
|
+
Accept: "application/json",
|
|
114
|
+
Metadata: true,
|
|
115
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private async pingImdsEndpoint(resource: string, clientId?: string): Promise<boolean> {
|
|
121
|
+
const request = this.createImdsAuthRequest(resource, clientId);
|
|
122
|
+
|
|
123
|
+
// This will always be populated, but let's make TypeScript happy
|
|
124
|
+
if (request.headers) {
|
|
125
|
+
// Remove the Metadata header to invoke a request error from
|
|
126
|
+
// IMDS endpoint
|
|
127
|
+
delete request.headers.Metadata;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Create a request with a 500 msec timeout since we expect that
|
|
131
|
+
// not having a "Metadata" header should cause an error to be
|
|
132
|
+
// returned quickly from the endpoint, proving its availability.
|
|
133
|
+
const webResource = this.identityClient.createWebResource(request);
|
|
134
|
+
webResource.timeout = 500;
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await this.identityClient.sendRequest(webResource);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
if (err instanceof RestError && err.code === RestError.REQUEST_SEND_ERROR) {
|
|
140
|
+
// Either request failed or IMDS endpoint isn't available
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If we received any response, the endpoint is available
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private async authenticateManagedIdentity(
|
|
150
|
+
scopes: string | string[],
|
|
151
|
+
checkIfImdsEndpointAvailable: boolean,
|
|
152
|
+
clientId?: string,
|
|
153
|
+
getTokenOptions?: GetTokenOptions
|
|
154
|
+
): Promise<AccessToken | null> {
|
|
155
|
+
let authRequestOptions: RequestPrepareOptions;
|
|
156
|
+
const resource = this.mapScopesToResource(scopes);
|
|
157
|
+
let expiresInParser: ((requestBody: any) => number) | undefined;
|
|
158
|
+
|
|
159
|
+
// Detect which type of environment we are running in
|
|
160
|
+
if (process.env.MSI_ENDPOINT) {
|
|
161
|
+
if (process.env.MSI_SECRET) {
|
|
162
|
+
// Running in App Service
|
|
163
|
+
authRequestOptions = this.createAppServiceMsiAuthRequest(resource, clientId);
|
|
164
|
+
expiresInParser = (requestBody: any) => {
|
|
165
|
+
// Parse a date format like "06/20/2019 02:57:58 +00:00" and
|
|
166
|
+
// convert it into a JavaScript-formatted date
|
|
167
|
+
const m = requestBody.expires_on.match(/(\d\d)\/(\d\d)\/(\d\d\d\d) (\d\d):(\d\d):(\d\d) (\+|-)(\d\d):(\d\d)/)
|
|
168
|
+
return Date.parse(`${m[3]}-${m[1]}-${m[2]}T${m[4]}:${m[5]}:${m[6]}${m[7]}${m[8]}:${m[9]}`)
|
|
169
|
+
};
|
|
170
|
+
} else {
|
|
171
|
+
// Running in Cloud Shell
|
|
172
|
+
authRequestOptions = this.createCloudShellMsiAuthRequest(resource, clientId);
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
// Ping the IMDS endpoint to see if it's available
|
|
176
|
+
if (!checkIfImdsEndpointAvailable || await this.pingImdsEndpoint(resource, clientId)) {
|
|
177
|
+
// Running in an Azure VM
|
|
178
|
+
authRequestOptions = this.createImdsAuthRequest(resource, clientId);
|
|
179
|
+
} else {
|
|
180
|
+
// Returning null tells the ManagedIdentityCredential that
|
|
181
|
+
// no MSI authentication endpoints are available
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const webResource = this.identityClient.createWebResource({
|
|
187
|
+
disableJsonStringifyOnBody: true,
|
|
188
|
+
deserializationMapper: undefined,
|
|
189
|
+
abortSignal: getTokenOptions && getTokenOptions.abortSignal,
|
|
190
|
+
...authRequestOptions
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const tokenResponse = await this.identityClient.sendTokenRequest(webResource, expiresInParser);
|
|
194
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
24
195
|
}
|
|
25
196
|
|
|
26
197
|
/**
|
|
@@ -28,7 +199,7 @@ export class ManagedIdentityCredential implements TokenCredential {
|
|
|
28
199
|
* successful. If authentication cannot be performed at this time, this method may
|
|
29
200
|
* return null. If an error occurs during authentication, an {@link AuthenticationError}
|
|
30
201
|
* containing failure details will be thrown.
|
|
31
|
-
*
|
|
202
|
+
*
|
|
32
203
|
* @param scopes The list of scopes for which the token will have access.
|
|
33
204
|
* @param options The options used to configure any requests this
|
|
34
205
|
* TokenCredential implementation might make.
|
|
@@ -44,10 +215,10 @@ export class ManagedIdentityCredential implements TokenCredential {
|
|
|
44
215
|
// the endpoint is available and need to check for it.
|
|
45
216
|
if (this.isEndpointUnavailable !== true) {
|
|
46
217
|
result =
|
|
47
|
-
await this.
|
|
218
|
+
await this.authenticateManagedIdentity(
|
|
48
219
|
scopes,
|
|
49
220
|
this.isEndpointUnavailable === null,
|
|
50
|
-
this.
|
|
221
|
+
this.clientId,
|
|
51
222
|
options);
|
|
52
223
|
|
|
53
224
|
// If authenticateManagedIdentity returns null, it means no MSI
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
import qs from "qs";
|
|
5
|
+
import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-http";
|
|
6
|
+
import { IdentityClientOptions, IdentityClient } from "../client/identityClient";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Enables authentication to Azure Active Directory with a user's
|
|
10
|
+
* username and password. This credential requires a high degree of
|
|
11
|
+
* trust so you should only use it when other, more secure credential
|
|
12
|
+
* types can't be used.
|
|
13
|
+
*/
|
|
14
|
+
export class UsernamePasswordCredential implements TokenCredential {
|
|
15
|
+
private identityClient: IdentityClient;
|
|
16
|
+
private tenantId: string;
|
|
17
|
+
private clientId: string;
|
|
18
|
+
private username: string;
|
|
19
|
+
private password: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates an instance of the UsernamePasswordCredential with the details
|
|
23
|
+
* needed to authenticate against Azure Active Directory with a username
|
|
24
|
+
* and password.
|
|
25
|
+
*
|
|
26
|
+
* @param tenantIdOrName The Azure Active Directory tenant (directory) ID or name.
|
|
27
|
+
* @param clientId The client (application) ID of an App Registration in the tenant.
|
|
28
|
+
* @param username The user account's e-mail address (user name).
|
|
29
|
+
* @param password The user account's account password
|
|
30
|
+
* @param options Options for configuring the client which makes the authentication request.
|
|
31
|
+
*/
|
|
32
|
+
constructor(
|
|
33
|
+
tenantIdOrName: string,
|
|
34
|
+
clientId: string,
|
|
35
|
+
username: string,
|
|
36
|
+
password: string,
|
|
37
|
+
options?: IdentityClientOptions
|
|
38
|
+
) {
|
|
39
|
+
this.identityClient = new IdentityClient(options);
|
|
40
|
+
this.tenantId = tenantIdOrName;
|
|
41
|
+
this.clientId = clientId;
|
|
42
|
+
this.username = username;
|
|
43
|
+
this.password = password;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Authenticates with Azure Active Directory and returns an {@link AccessToken} if
|
|
48
|
+
* successful. If authentication cannot be performed at this time, this method may
|
|
49
|
+
* return null. If an error occurs during authentication, an {@link AuthenticationError}
|
|
50
|
+
* containing failure details will be thrown.
|
|
51
|
+
*
|
|
52
|
+
* @param scopes The list of scopes for which the token will have access.
|
|
53
|
+
* @param options The options used to configure any requests this
|
|
54
|
+
* TokenCredential implementation might make.
|
|
55
|
+
*/
|
|
56
|
+
public async getToken(
|
|
57
|
+
scopes: string | string[],
|
|
58
|
+
options?: GetTokenOptions
|
|
59
|
+
): Promise<AccessToken | null> {
|
|
60
|
+
const webResource = this.identityClient.createWebResource({
|
|
61
|
+
url: `${this.identityClient.authorityHost}/${this.tenantId}/oauth2/v2.0/token`,
|
|
62
|
+
method: "POST",
|
|
63
|
+
disableJsonStringifyOnBody: true,
|
|
64
|
+
deserializationMapper: undefined,
|
|
65
|
+
body: qs.stringify({
|
|
66
|
+
response_type: "token",
|
|
67
|
+
grant_type: "password",
|
|
68
|
+
client_id: this.clientId,
|
|
69
|
+
username: this.username,
|
|
70
|
+
password: this.password,
|
|
71
|
+
scope: typeof scopes === "string" ? scopes : scopes.join(" ")
|
|
72
|
+
}),
|
|
73
|
+
headers: {
|
|
74
|
+
Accept: "application/json",
|
|
75
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
76
|
+
},
|
|
77
|
+
abortSignal: options && options.abortSignal
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const tokenResponse = await this.identityClient.sendTokenRequest(webResource);
|
|
81
|
+
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -9,8 +9,12 @@ export { IdentityClientOptions } from "./client/identityClient";
|
|
|
9
9
|
export { EnvironmentCredential } from "./credentials/environmentCredential";
|
|
10
10
|
export { ClientSecretCredential } from "./credentials/clientSecretCredential";
|
|
11
11
|
export { ClientCertificateCredential } from "./credentials/clientCertificateCredential";
|
|
12
|
+
export { InteractiveBrowserCredential } from "./credentials/interactiveBrowserCredential";
|
|
13
|
+
export { InteractiveBrowserCredentialOptions, BrowserLoginStyle } from "./credentials/interactiveBrowserCredentialOptions";
|
|
12
14
|
export { ManagedIdentityCredential } from "./credentials/managedIdentityCredential";
|
|
15
|
+
export { DeviceCodeCredential } from "./credentials/deviceCodeCredential";
|
|
13
16
|
export { DefaultAzureCredential } from "./credentials/defaultAzureCredential";
|
|
17
|
+
export { UsernamePasswordCredential } from "./credentials/usernamePasswordCredential";
|
|
14
18
|
export { AuthenticationError, AggregateAuthenticationError } from "./client/errors";
|
|
15
19
|
|
|
16
20
|
export { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-http";
|