Skip to content

Commit 9b63237

Browse files
committed
Fix auth
1 parent 7e25dfb commit 9b63237

11 files changed

Lines changed: 97 additions & 44 deletions

File tree

l10n/bundle.l10n.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
"Your preview isn't updated. Please upload your site to see the latest changes.": "Your preview isn't updated. Please upload your site to see the latest changes.",
136136
"Upload changes": "Upload changes",
137137
"The preview shown is for published changes. Please publish any pending changes to see them in the preview.": "The preview shown is for published changes. Please publish any pending changes to see them in the preview.",
138+
"Please login to preview the site.": "Please login to preview the site.",
138139
"Enter the name of the web template": "Enter the name of the web template",
139140
"Please enter a name for the web template.": "Please enter a name for the web template.",
140141
"A webtemplate with the same name already exists. Please enter a different name.": "A webtemplate with the same name already exists. Please enter a different name.",

loc/translations-export/vscode-powerplatform.xlf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ The {3} represents Dataverse Environment's Organization ID (GUID)</note>
460460
<trans-unit id="++CODE++7f6276dc63b573d177b7d6e17f787b108e3c8c7d449324ac13a6d06b1be59d8e">
461461
<source xml:lang="en">Please enter a name for the webpage.</source>
462462
</trans-unit>
463+
<trans-unit id="++CODE++6355962eca901310bd24d2142605263344a3f09fb4fc30fc0f9dcf4cd56bf534">
464+
<source xml:lang="en">Please login to preview the site.</source>
465+
</trans-unit>
463466
<trans-unit id="++CODE++1bac158cc07a75506df3774db0ad7c188c19ccad4943c4cf03da8b6700ef9ce4">
464467
<source xml:lang="en">Power Pages Copilot is now connected to the environment: {0} : {1}</source>
465468
<note>{0} represents the environment name</note>
@@ -795,7 +798,7 @@ The second line should be '[TRANSLATION HERE](command:microsoft.powerplatform.pa
795798
</trans-unit>
796799
<trans-unit id="pacCLI.authPanel.welcome.whenInteractiveNotSupported">
797800
<source xml:lang="en">No auth profiles found on this computer.
798-
Interactive Authentication is not availalbe for remote scenarios; auth profiles must be created by the command line. The `--deviceCode` flow must be used for users with MFA requirements, or whose tenants use ADFS.
801+
Interactive Authentication is not available for remote scenarios; auth profiles must be created by the command line. The `--deviceCode` flow must be used for users with MFA requirements, or whose tenants use ADFS.
799802
[View Auth Profile Help](command:pacCLI.pacAuthHelp)</source>
800803
<note>This is a Markdown formatted string, and the formatting must persist across translations.
801804
The second line should not translate the argument `--deviceCode`

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
]
2121
},
2222
"pacCLI.authPanel.welcome.whenInteractiveNotSupported": {
23-
"message": "No auth profiles found on this computer.\nInteractive Authentication is not availalbe for remote scenarios; auth profiles must be created by the command line. The `--deviceCode` flow must be used for users with MFA requirements, or whose tenants use ADFS.\n[View Auth Profile Help](command:pacCLI.pacAuthHelp)",
23+
"message": "No auth profiles found on this computer.\nInteractive Authentication is not available for remote scenarios; auth profiles must be created by the command line. The `--deviceCode` flow must be used for users with MFA requirements, or whose tenants use ADFS.\n[View Auth Profile Help](command:pacCLI.pacAuthHelp)",
2424
"comment": [
2525
"This is a Markdown formatted string, and the formatting must persist across translations.",
2626
"The second line should not translate the argument `--deviceCode`",

src/client/extension.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ import { ActionsHub } from "./power-pages/actions-hub/ActionsHub";
4747
import { extractAuthInfo, extractOrgInfo } from "./power-pages/commonUtility";
4848
import PacContext from "./pac/PacContext";
4949
import ArtemisContext from "./ArtemisContext";
50-
import { bapServiceAuthentication } from "../common/services/AuthenticationProvider";
50+
import { authenticateUser } from "../common/services/AuthenticationProvider";
51+
import { PROVIDER_ID } from "../common/services/Constants";
5152

5253
let client: LanguageClient;
5354
let _context: vscode.ExtensionContext;
@@ -67,6 +68,14 @@ export async function activate(
6768
"pac.userId": readUserSettings().uniqueId
6869
});
6970

71+
_context.subscriptions.push(
72+
vscode.authentication.onDidChangeSessions(async (event) => {
73+
if (event.provider.id === PROVIDER_ID) {
74+
await authenticateUser(true);
75+
}
76+
})
77+
);
78+
7079
// Setup context switches
7180
if (
7281
vscode.env.remoteName === undefined ||
@@ -86,7 +95,7 @@ export async function activate(
8695
);
8796
}
8897

89-
await bapServiceAuthentication(); //Authentication for extension
98+
await authenticateUser(); //Authentication for extension
9099

91100
// portal web view panel
92101
_context.subscriptions.push(

src/client/power-pages/actions-hub/ActionsHubCommandHandlers.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { ServiceEndpointCategory, WebsiteDataModel } from '../../../common/servi
1818
import { SiteTreeItem } from './tree-items/SiteTreeItem';
1919
import { PreviewSite } from '../preview-site/PreviewSite';
2020
import { PacWrapper } from '../../pac/PacWrapper';
21-
import { dataverseAuthentication } from '../../../common/services/AuthenticationProvider';
21+
import { authenticateUser, dataverseAuthentication } from '../../../common/services/AuthenticationProvider';
2222
import { createAuthProfileExp } from '../../../common/utilities/PacAuthUtil';
2323
import { IOtherSiteInfo, IWebsiteDetails, WebsiteYaml } from '../../../common/services/Interfaces';
2424
import { getActiveWebsites, getAllWebsites } from '../../../common/utilities/WebsiteUtil';
@@ -199,14 +199,17 @@ export const previewSite = async (siteTreeItem: SiteTreeItem) => {
199199
}
200200
};
201201

202-
export const createNewAuthProfile = async (pacWrapper: PacWrapper, orgUrl: string): Promise<void> => {
202+
export const createNewAuthProfile = async (pacWrapper: PacWrapper): Promise<void> => {
203203
traceInfo(Constants.EventNames.ACTIONS_HUB_CREATE_AUTH_PROFILE_CALLED, { methodName: createNewAuthProfile.name });
204204
try {
205+
const orgUrl = PacContext.OrgInfo?.OrgUrl ?? '';
206+
205207
// if orgUrl is present then directly call dataverseAuthentication
206208
if (orgUrl) {
207-
await dataverseAuthentication(orgUrl, true);
209+
await authenticateUser();
208210
return;
209211
}
212+
210213
const pacAuthCreateOutput = await createAuthProfileExp(pacWrapper);
211214
if (pacAuthCreateOutput && pacAuthCreateOutput.Status === SUCCESS) {
212215
const results = pacAuthCreateOutput.Results;

src/client/power-pages/actions-hub/ActionsHubTreeDataProvider.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import CurrentSiteContext from "./CurrentSiteContext";
1717
import { IOtherSiteInfo, IWebsiteDetails } from "../../../common/services/Interfaces";
1818
import { orgChangeErrorEvent } from "../../OrgChangeNotifier";
1919
import { getBaseEventInfo } from "./TelemetryHelper";
20-
import { BAP_SERVICE_SCOPE_DEFAULT, PROVIDER_ID } from "../../../common/services/Constants";
20+
import { PROVIDER_ID } from "../../../common/services/Constants";
2121

2222
export class ActionsHubTreeDataProvider implements vscode.TreeDataProvider<ActionsHubTreeItem> {
2323
private readonly _disposables: vscode.Disposable[] = [];
@@ -42,7 +42,9 @@ export class ActionsHubTreeDataProvider implements vscode.TreeDataProvider<Actio
4242
CurrentSiteContext.onChanged(() => this.refresh()),
4343

4444
// Register an event listener for org change error as action hub will not be re-initialized in extension.ts
45-
orgChangeErrorEvent(() => this.refresh())
45+
orgChangeErrorEvent(() => this.refresh()),
46+
47+
vscode.authentication.onDidChangeSessions((_) => this.refresh())
4648
);
4749
this._context = context;
4850
}
@@ -71,16 +73,13 @@ export class ActionsHubTreeDataProvider implements vscode.TreeDataProvider<Actio
7173

7274
private async checkAuthInfo(): Promise<boolean> {
7375
const authInfo = PacContext.AuthInfo;
74-
const session = await vscode.authentication.getSession(
75-
PROVIDER_ID,
76-
[BAP_SERVICE_SCOPE_DEFAULT],
77-
{ silent: true }
78-
);
76+
const session = await vscode.authentication.getSession(PROVIDER_ID, [], { silent: true });
77+
7978
if (session && session.accessToken && authInfo && authInfo.OrganizationFriendlyName) {
8079
return true;
81-
} else {
82-
return false;
8380
}
81+
82+
return false;
8483
}
8584

8685
public static initialize(context: vscode.ExtensionContext, pacTerminal: PacTerminal): ActionsHubTreeDataProvider {
@@ -145,7 +144,7 @@ export class ActionsHubTreeDataProvider implements vscode.TreeDataProvider<Actio
145144
vscode.commands.registerCommand("microsoft.powerplatform.pages.actionsHub.activeSite.preview", previewSite),
146145

147146
vscode.commands.registerCommand("microsoft.powerplatform.pages.actionsHub.newAuthProfile", async () => {
148-
await createNewAuthProfile(pacTerminal.getWrapper(), PacContext.OrgInfo?.OrgUrl ?? '');
147+
await createNewAuthProfile(pacTerminal.getWrapper());
149148
}),
150149

151150
vscode.commands.registerCommand("microsoft.powerplatform.pages.actionsHub.currentActiveSite.revealInOS.windows", revealInOS),

src/client/power-pages/preview-site/Constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export const Messages = {
3232
UNABLE_TO_CLEAR_CACHE: vscode.l10n.t("Unable to clear cache"),
3333
PREVIEW_WARNING: vscode.l10n.t("Your preview isn't updated. Please upload your site to see the latest changes."),
3434
UPLOAD_CHANGES: vscode.l10n.t("Upload changes"),
35-
PREVIEW_SHOWN_FOR_PUBLISHED_CHANGES: vscode.l10n.t("The preview shown is for published changes. Please publish any pending changes to see them in the preview.")
35+
PREVIEW_SHOWN_FOR_PUBLISHED_CHANGES: vscode.l10n.t("The preview shown is for published changes. Please publish any pending changes to see them in the preview."),
36+
LOGIN_REQUIRED: vscode.l10n.t("Please login to preview the site.")
3637
};
3738

3839
export const Events = {

src/client/power-pages/preview-site/PreviewSite.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ export class PreviewSite {
239239

240240
const authResponse = await dataverseAuthentication(orgDetails.OrgUrl);
241241

242+
if (!authResponse) {
243+
progress.report({ message: Messages.LOGIN_REQUIRED });
244+
return;
245+
}
246+
242247
const clearCacheResponse = await fetch(requestUrl, {
243248
headers: {
244249
authorization: "Bearer " + authResponse.accessToken,

src/common/copilot/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const CopilotStylePathSegments = ['src', 'common', 'copilot', 'assets', '
1616
export const EUROPE_GEO = 'eu';
1717
export const UK_GEO = 'uk';
1818
export const COPILOT_UNAVAILABLE = 'copilotunavailable';
19-
export const AUTH_CREATE_MESSAGE = vscode.l10n.t('Creating new Auth Profile');
19+
export const AUTH_CREATE_MESSAGE = vscode.l10n.t('Creating new authentication profile');
2020
export const AUTH_CREATE_FAILED = vscode.l10n.t("Error creating auth profile for org")
2121
export const RELEVANCY_CHECK_FAILED = 'RelevancyCheckFailed';
2222
export const INAPPROPRIATE_CONTENT = 'InappropriateContentDetected';

src/common/services/AuthenticationProvider.ts

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
} from "./Constants";
4040
import jwt_decode from 'jwt-decode';
4141
import { showErrorDialog } from "../utilities/errorHandlerUtil";
42+
import { oneDSLoggerWrapper } from "../OneDSLoggerTelemetry/oneDSLoggerWrapper";
4243

4344
const serviceScopeMapping: { [key in ServiceEndpointCategory]: string } = {
4445
[ServiceEndpointCategory.NONE]: "",
@@ -86,14 +87,16 @@ export async function intelligenceAPIAuthentication(sessionID: string, orgId: st
8687
let user = '';
8788
let userId = '';
8889
try {
89-
let session = await vscode.authentication.getSession(PROVIDER_ID, [`${INTELLIGENCE_SCOPE_DEFAULT}`], { silent: true });
90+
const session = await vscode.authentication.getSession(PROVIDER_ID, [`${INTELLIGENCE_SCOPE_DEFAULT}`], { silent: true });
91+
9092
if (!session) {
91-
session = await vscode.authentication.getSession(PROVIDER_ID, [`${INTELLIGENCE_SCOPE_DEFAULT}`], { createIfNone: true });
92-
firstTimeAuth = true;
93+
return { accessToken, user, userId };
9394
}
95+
9496
accessToken = session?.accessToken ?? '';
95-
user = session.account.label;
97+
user = session?.account?.label ?? '';
9698
userId = getOIDFromToken(accessToken);
99+
97100
if (!accessToken) {
98101
throw new Error(ERROR_CONSTANTS.NO_ACCESS_TOKEN);
99102
}
@@ -116,23 +119,17 @@ export async function dataverseAuthentication(
116119
let accessToken = "";
117120
let userId = "";
118121
try {
119-
let session = await vscode.authentication.getSession(
122+
const session = await vscode.authentication.getSession(
120123
PROVIDER_ID,
121124
[
122125
`${dataverseOrgURL}${SCOPE_OPTION_DEFAULT}`,
123126
`${SCOPE_OPTION_OFFLINE_ACCESS}`,
124127
],
125128
{ silent: true }
126129
);
130+
127131
if (!session) {
128-
session = await vscode.authentication.getSession(
129-
PROVIDER_ID,
130-
[
131-
`${dataverseOrgURL}${SCOPE_OPTION_DEFAULT}`,
132-
`${SCOPE_OPTION_OFFLINE_ACCESS}`,
133-
],
134-
{ createIfNone: true }
135-
);
132+
return { accessToken, userId };
136133
}
137134

138135
accessToken = session?.accessToken ?? "";
@@ -259,18 +256,14 @@ export async function bapServiceAuthentication(
259256
): Promise<string> {
260257
let accessToken = "";
261258
try {
262-
let session = await vscode.authentication.getSession(
259+
const session = await vscode.authentication.getSession(
263260
PROVIDER_ID,
264261
[BAP_SERVICE_SCOPE_DEFAULT],
265262
{ silent: true }
266263
);
267264

268265
if (!session) {
269-
session = await vscode.authentication.getSession(
270-
PROVIDER_ID,
271-
[BAP_SERVICE_SCOPE_DEFAULT],
272-
{ createIfNone: true }
273-
);
266+
return accessToken;
274267
}
275268

276269
accessToken = session?.accessToken ?? "";
@@ -321,18 +314,14 @@ export async function powerPlatformAPIAuthentication(
321314
let accessToken = "";
322315
const PPAPI_WEBSITES_ENDPOINT = serviceScopeMapping[serviceEndpointStamp];
323316
try {
324-
let session = await vscode.authentication.getSession(
317+
const session = await vscode.authentication.getSession(
325318
PROVIDER_ID,
326319
[PPAPI_WEBSITES_ENDPOINT],
327320
{ silent: true }
328321
);
329322

330323
if (!session) {
331-
session = await vscode.authentication.getSession(
332-
PROVIDER_ID,
333-
[PPAPI_WEBSITES_ENDPOINT],
334-
{ createIfNone: true }
335-
);
324+
return accessToken;
336325
}
337326

338327
accessToken = session?.accessToken ?? "";
@@ -363,3 +352,41 @@ export async function powerPlatformAPIAuthentication(
363352

364353
return accessToken;
365354
}
355+
356+
/**
357+
* Authenticate the user using Microsoft as authentication provider.
358+
* @param isSilent - If true, the authentication will be done silently without showing a dialog.
359+
* @returns A promise that resolves when the authentication is complete.
360+
*
361+
*/
362+
export async function authenticateUser(isSilent = false): Promise<void> {
363+
if (isSilent) {
364+
await authenticateUserInternal(false);
365+
} else {
366+
const isAuthenticated = await authenticateUserInternal(true);
367+
if (!isAuthenticated) {
368+
await authenticateUserInternal(false);
369+
}
370+
}
371+
}
372+
373+
/**
374+
* Authenticate the user using the authentication provider.
375+
* @param createIfNone - If true, an authentication dialog will be shown to user.
376+
* @returns A promise that resolves to true if authentication is successful, false otherwise.
377+
*/
378+
async function authenticateUserInternal(createIfNone: boolean): Promise<boolean> {
379+
try {
380+
const session = await vscode.authentication.getSession(PROVIDER_ID, [], { createIfNone: createIfNone });
381+
382+
if (session) {
383+
const userId = getOIDFromToken(session.accessToken);
384+
oneDSLoggerWrapper.getLogger().traceInfo("VSCodeDesktopUserAuthenticationSuccessful", { userId, createIfNone });
385+
return true;
386+
}
387+
} catch (error) {
388+
const errorMessage = error as Error;
389+
oneDSLoggerWrapper.getLogger().traceError("VSCodeDesktopUserAuthenticationFailed", errorMessage.message, errorMessage, { createIfNone });
390+
}
391+
return false;
392+
}

0 commit comments

Comments
 (0)