Skip to content

Commit 9931452

Browse files
Fix appending .default to tenant id scope (#1608)
* Cleanup scope related code, add `getSessionFromVSCode` helper * Fix formatting * Bump version to 1.2.2
1 parent d40c937 commit 9931452

4 files changed

+61
-50
lines changed

auth/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auth/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@microsoft/vscode-azext-azureauth",
33
"author": "Microsoft Corporation",
4-
"version": "1.2.1",
4+
"version": "1.2.2",
55
"description": "Azure authentication helpers for Visual Studio Code",
66
"tags": [
77
"azure",

auth/src/VSCodeAzureSubscriptionProvider.ts

+8-47
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { AzureAuthentication } from './AzureAuthentication';
1111
import type { AzureSubscription, SubscriptionId, TenantId } from './AzureSubscription';
1212
import type { AzureSubscriptionProvider } from './AzureSubscriptionProvider';
1313
import { NotSignedInError } from './NotSignedInError';
14+
import { getSessionFromVSCode } from './getSessionFromVSCode';
1415
import { getConfiguredAuthProviderId, getConfiguredAzureEnv } from './utils/configuredAzureEnv';
1516

1617
const EventDebounce = 5 * 1000; // 5 seconds
@@ -131,7 +132,7 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
131132
* @returns True if the user is signed in, false otherwise.
132133
*/
133134
public async isSignedIn(tenantId?: string): Promise<boolean> {
134-
const session = await vscode.authentication.getSession(getConfiguredAuthProviderId(), this.getScopes([], tenantId), { createIfNone: false, silent: true });
135+
const session = await getSessionFromVSCode([], tenantId, { createIfNone: false, silent: true });
135136
return !!session;
136137
}
137138

@@ -143,7 +144,7 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
143144
* @returns True if the user is signed in, false otherwise.
144145
*/
145146
public async signIn(tenantId?: string): Promise<boolean> {
146-
const session = await vscode.authentication.getSession(getConfiguredAuthProviderId(), this.getScopes([], tenantId), { createIfNone: true, clearSessionPreference: true });
147+
const session = await getSessionFromVSCode([], tenantId, { createIfNone: true, clearSessionPreference: true });
147148
return !!session;
148149
}
149150

@@ -237,8 +238,8 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
237238
private async getSubscriptionClient(tenantId?: string): Promise<{ client: SubscriptionClient, credential: TokenCredential, authentication: AzureAuthentication }> {
238239
const armSubs = await import('@azure/arm-subscriptions');
239240

240-
const getSession = async (scopes?: string[]): Promise<vscode.AuthenticationSession> => {
241-
const session = await vscode.authentication.getSession(getConfiguredAuthProviderId(), this.getScopes(scopes, tenantId), { createIfNone: false, silent: true });
241+
const getSession = async (scopes?: string[] | string): Promise<vscode.AuthenticationSession> => {
242+
const session = await getSessionFromVSCode(scopes, tenantId, { createIfNone: false, silent: true });
242243
if (!session) {
243244
throw new NotSignedInError();
244245
}
@@ -248,7 +249,7 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
248249
const credential: TokenCredential = {
249250
getToken: async (scopes) => {
250251
return {
251-
token: (await getSession(this.getScopes(scopes, tenantId))).accessToken,
252+
token: (await getSession(scopes)).accessToken,
252253
expiresOnTimestamp: 0
253254
};
254255
}
@@ -258,58 +259,18 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
258259
client: new armSubs.SubscriptionClient(credential),
259260
credential: credential,
260261
authentication: {
261-
getSession
262+
getSession,
262263
}
263264
};
264265
}
265266

266267
private async getToken(tenantId?: string): Promise<string> {
267-
const session = await vscode.authentication.getSession(getConfiguredAuthProviderId(), this.getScopes([], tenantId), { createIfNone: false, silent: true });
268+
const session = await getSessionFromVSCode([], tenantId, { createIfNone: false, silent: true })
268269

269270
if (!session) {
270271
throw new NotSignedInError();
271272
}
272273

273274
return session.accessToken;
274275
}
275-
276-
/**
277-
* Gets a normalized list of scopes. If no scopes are provided, the return value of {@link getDefaultScope} is used.
278-
*
279-
* Only supports top-level resource scopes (e.g. http://management.azure.com, http://storage.azure.com) or .default scopes.
280-
*
281-
* All resources/scopes will be normalized to the `.default` scope for each resource.
282-
*
283-
* @param scopes An input scope string, list, or undefined
284-
* @param tenantId (Optional) The tenant ID, will be added to the scopes
285-
*/
286-
private getScopes(scopes: string | string[] | undefined, tenantId?: string): string[] {
287-
if (scopes === undefined || scopes === "" || scopes.length === 0) {
288-
scopes = this.getDefaultScope();
289-
}
290-
const arrScopes = (Array.isArray(scopes) ? scopes : [scopes])
291-
.map((scope) => {
292-
if (scope.endsWith('.default')) {
293-
return scope;
294-
} else {
295-
return `${scope}.default`;
296-
}
297-
});
298-
299-
const scopeSet = new Set<string>(arrScopes);
300-
if (tenantId) {
301-
scopeSet.add(`VSCODE_TENANT:${tenantId}`);
302-
}
303-
return Array.from(scopeSet);
304-
}
305-
306-
/**
307-
* Gets the default Azure scopes required for resource management,
308-
* depending on the configured endpoint
309-
*
310-
* @returns The default Azure scopes required
311-
*/
312-
private getDefaultScope(): string {
313-
return `${getConfiguredAzureEnv().resourceManagerEndpointUrl}.default`;
314-
}
315276
}

auth/src/getSessionFromVSCode.ts

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { getConfiguredAuthProviderId, getConfiguredAzureEnv } from "./utils/configuredAzureEnv";
7+
import * as vscode from "vscode";
8+
9+
function getResourceScopes(scopes?: string | string[]): string[] {
10+
if (scopes === undefined || scopes === "" || scopes.length === 0) {
11+
scopes = `${getConfiguredAzureEnv().resourceManagerEndpointUrl}.default`;
12+
}
13+
const arrScopes = (Array.isArray(scopes) ? scopes : [scopes])
14+
.map((scope) => {
15+
if (scope.endsWith('.default')) {
16+
return scope;
17+
} else {
18+
return `${scope}.default`;
19+
}
20+
});
21+
return Array.from(new Set<string>(arrScopes));
22+
}
23+
24+
function addTenantIdScope(scopes: string[], tenantId: string): string[] {
25+
const scopeSet = new Set<string>(scopes);
26+
scopeSet.add(`VSCODE_TENANT:${tenantId}`);
27+
return Array.from(scopeSet);
28+
}
29+
30+
function getScopes(scopes: string | string[] | undefined, tenantId?: string): string[] {
31+
let scopeArr = getResourceScopes(scopes);
32+
if (tenantId) {
33+
scopeArr = addTenantIdScope(scopeArr, tenantId);
34+
}
35+
return scopeArr;
36+
}
37+
38+
/**
39+
* Wraps {@link vscode.authentication.getSession} and handles:
40+
* * Passing the configured auth provider id
41+
* * Getting the list of scopes, adding the tenant id to the scope list if needed
42+
*
43+
* @param scopes - top-level resource scopes (e.g. http://management.azure.com, http://storage.azure.com) or .default scopes. All resources/scopes will be normalized to the `.default` scope for each resource.
44+
* @param tenantId - (Optional) The tenant ID, will be added to the scopes
45+
* @param options - see {@link vscode.AuthenticationGetSessionOptions}
46+
* @returns An authentication session if available, or undefined if there are no sessions
47+
*/
48+
export async function getSessionFromVSCode(scopes?: string | string[], tenantId?: string, options?: vscode.AuthenticationGetSessionOptions): Promise<vscode.AuthenticationSession | undefined> {
49+
return await vscode.authentication.getSession(getConfiguredAuthProviderId(), getScopes(scopes, tenantId), options);
50+
}

0 commit comments

Comments
 (0)