mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 02:58:56 +01:00
Handle authority & redirectUri in acquireTokenByRefreshToken (#263958)
Handle authority in acquireTokenByRefreshToken This fixes the migration logic for clients that that moving from MSAL to MSAL+Broker
This commit is contained in:
committed by
GitHub
parent
5b25d491ca
commit
2e43a0c0d6
@@ -4,6 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Uri } from 'vscode';
|
||||
|
||||
export const DEFAULT_REDIRECT_URI = 'https://vscode.dev/redirect';
|
||||
|
||||
const VALID_DESKTOP_CALLBACK_SCHEMES = [
|
||||
'vscode',
|
||||
'vscode-insiders',
|
||||
|
||||
@@ -19,6 +19,6 @@ export interface ICachedPublicClientApplication {
|
||||
|
||||
export interface ICachedPublicClientApplicationManager {
|
||||
onDidAccountsChange: Event<{ added: AccountInfo[]; changed: AccountInfo[]; deleted: AccountInfo[] }>;
|
||||
getOrCreate(clientId: string, refreshTokensToMigrate?: string[]): Promise<ICachedPublicClientApplication>;
|
||||
getOrCreate(clientId: string, migrate?: { refreshTokensToMigrate?: string[]; tenant: string }): Promise<ICachedPublicClientApplication>;
|
||||
getAll(): ICachedPublicClientApplication[];
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ import { BetterTokenStorage } from '../betterSecretStorage';
|
||||
import { IStoredSession } from '../AADHelper';
|
||||
import { ExtensionHost, getMsalFlows } from './flows';
|
||||
import { base64Decode } from './buffer';
|
||||
import { Config } from '../common/config';
|
||||
import { DEFAULT_REDIRECT_URI } from '../common/env';
|
||||
|
||||
const redirectUri = 'https://vscode.dev/redirect';
|
||||
const MSA_TID = '9188040d-6c67-4c5b-b112-36a304b66dad';
|
||||
const MSA_PASSTHRU_TID = 'f8cdef31-a31e-4b4a-93e4-5f571e91255a';
|
||||
|
||||
@@ -87,7 +88,7 @@ export class MsalAuthProvider implements AuthenticationProvider {
|
||||
uriHandler: UriEventHandler,
|
||||
env: Environment = Environment.AzureCloud
|
||||
): Promise<MsalAuthProvider> {
|
||||
const publicClientManager = await CachedPublicClientApplicationManager.create(context.secrets, logger, telemetryReporter, env.name);
|
||||
const publicClientManager = await CachedPublicClientApplicationManager.create(context.secrets, logger, telemetryReporter, env);
|
||||
context.subscriptions.push(publicClientManager);
|
||||
const authProvider = new MsalAuthProvider(context, telemetryReporter, logger, uriHandler, publicClientManager, env);
|
||||
await authProvider.initialize();
|
||||
@@ -117,8 +118,8 @@ export class MsalAuthProvider implements AuthenticationProvider {
|
||||
clientTenantMap.get(key)!.refreshTokens.push(session.refreshToken);
|
||||
}
|
||||
|
||||
for (const { clientId, refreshTokens } of clientTenantMap.values()) {
|
||||
await this._publicClientManager.getOrCreate(clientId, refreshTokens);
|
||||
for (const { clientId, tenant, refreshTokens } of clientTenantMap.values()) {
|
||||
await this._publicClientManager.getOrCreate(clientId, { refreshTokensToMigrate: refreshTokens, tenant });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,6 +484,10 @@ export class MsalAuthProvider implements AuthenticationProvider {
|
||||
forceRefresh = true;
|
||||
claims = scopeData.claims;
|
||||
}
|
||||
let redirectUri = DEFAULT_REDIRECT_URI;
|
||||
if (cachedPca.isBrokerAvailable && process.platform === 'darwin') {
|
||||
redirectUri = Config.macOSBrokerRedirectUri;
|
||||
}
|
||||
const result = await cachedPca.acquireTokenSilent({
|
||||
account,
|
||||
authority,
|
||||
|
||||
@@ -9,6 +9,9 @@ import { ICachedPublicClientApplication, ICachedPublicClientApplicationManager }
|
||||
import { CachedPublicClientApplication } from './cachedPublicClientApplication';
|
||||
import { IAccountAccess, ScopedAccountAccess } from '../common/accountAccess';
|
||||
import { MicrosoftAuthenticationTelemetryReporter } from '../common/telemetryReporter';
|
||||
import { Environment } from '@azure/ms-rest-azure-env';
|
||||
import { Config } from '../common/config';
|
||||
import { DEFAULT_REDIRECT_URI } from '../common/env';
|
||||
|
||||
export interface IPublicClientApplicationInfo {
|
||||
clientId: string;
|
||||
@@ -26,6 +29,7 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient
|
||||
readonly onDidAccountsChange = this._onDidAccountsChangeEmitter.event;
|
||||
|
||||
private constructor(
|
||||
private readonly _env: Environment,
|
||||
private readonly _pcasSecretStorage: IPublicClientApplicationSecretStorage,
|
||||
private readonly _accountAccess: IAccountAccess,
|
||||
private readonly _secretStorage: SecretStorage,
|
||||
@@ -44,13 +48,13 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient
|
||||
secretStorage: SecretStorage,
|
||||
logger: LogOutputChannel,
|
||||
telemetryReporter: MicrosoftAuthenticationTelemetryReporter,
|
||||
cloudName: string
|
||||
env: Environment
|
||||
): Promise<CachedPublicClientApplicationManager> {
|
||||
const pcasSecretStorage = await PublicClientApplicationsSecretStorage.create(secretStorage, cloudName);
|
||||
const pcasSecretStorage = await PublicClientApplicationsSecretStorage.create(secretStorage, env.name);
|
||||
// TODO: Remove the migrations in a version
|
||||
const migrations = await pcasSecretStorage.getOldValue();
|
||||
const accountAccess = await ScopedAccountAccess.create(secretStorage, cloudName, logger, migrations);
|
||||
const manager = new CachedPublicClientApplicationManager(pcasSecretStorage, accountAccess, secretStorage, logger, telemetryReporter, [pcasSecretStorage, accountAccess]);
|
||||
const accountAccess = await ScopedAccountAccess.create(secretStorage, env.name, logger, migrations);
|
||||
const manager = new CachedPublicClientApplicationManager(env, pcasSecretStorage, accountAccess, secretStorage, logger, telemetryReporter, [pcasSecretStorage, accountAccess]);
|
||||
await manager.initialize();
|
||||
return manager;
|
||||
}
|
||||
@@ -110,7 +114,7 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient
|
||||
Disposable.from(...this._pcaDisposables.values()).dispose();
|
||||
}
|
||||
|
||||
async getOrCreate(clientId: string, refreshTokensToMigrate?: string[]): Promise<ICachedPublicClientApplication> {
|
||||
async getOrCreate(clientId: string, migrate?: { refreshTokensToMigrate?: string[]; tenant: string }): Promise<ICachedPublicClientApplication> {
|
||||
let pca = this._pcas.get(clientId);
|
||||
if (pca) {
|
||||
this._logger.debug(`[getOrCreate] [${clientId}] PublicClientApplicationManager cache hit`);
|
||||
@@ -122,13 +126,24 @@ export class CachedPublicClientApplicationManager implements ICachedPublicClient
|
||||
}
|
||||
|
||||
// TODO: MSAL Migration. Remove this when we remove the old flow.
|
||||
if (refreshTokensToMigrate?.length) {
|
||||
if (migrate?.refreshTokensToMigrate?.length) {
|
||||
this._logger.debug(`[getOrCreate] [${clientId}] Migrating refresh tokens to PCA...`);
|
||||
for (const refreshToken of refreshTokensToMigrate) {
|
||||
const authority = new URL(migrate.tenant, this._env.activeDirectoryEndpointUrl).toString();
|
||||
let redirectUri = DEFAULT_REDIRECT_URI;
|
||||
if (pca.isBrokerAvailable && process.platform === 'darwin') {
|
||||
redirectUri = Config.macOSBrokerRedirectUri;
|
||||
}
|
||||
for (const refreshToken of migrate.refreshTokensToMigrate) {
|
||||
try {
|
||||
// Use the refresh token to acquire a result. This will cache the refresh token for future operations.
|
||||
// The scopes don't matter here since we can create any token from the refresh token.
|
||||
const result = await pca.acquireTokenByRefreshToken({ refreshToken, forceCache: true, scopes: [] });
|
||||
const result = await pca.acquireTokenByRefreshToken({
|
||||
refreshToken,
|
||||
forceCache: true,
|
||||
scopes: [],
|
||||
authority,
|
||||
redirectUri
|
||||
});
|
||||
if (result?.account) {
|
||||
this._logger.debug(`[getOrCreate] [${clientId}] Refresh token migrated to PCA.`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user