Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2e1a0a3
Initial plan
Copilot Jul 6, 2025
b04ba67
Initial analysis of authentication requirements
Copilot Jul 6, 2025
d8a99e1
Implement Microsoft Account authentication for Azure DevOps with PAT …
Copilot Jul 6, 2025
6cb23a6
Update documentation and add authentication test
Copilot Jul 6, 2025
60c8c80
Final cleanup: update comments and mock data messages for new auth
Copilot Jul 6, 2025
6b7643b
Merge branch 'master' into copilot/fix-47
norschel Jul 7, 2025
f4d3c1a
Merge branch 'master' into copilot/fix-47
norschel Jul 9, 2025
a7d2623
feat: add authentication test for Azure DevOps connection and improve…
norschel Jul 9, 2025
ac00fce
Merge branch 'master' into copilot/fix-47
norschel Jul 16, 2025
230b07c
Implement Microsoft Account authentication for Azure DevOps with PAT …
Copilot Jul 16, 2025
4504629
Enhance Azure DevOps authentication flow with detailed error handling…
norschel Jul 18, 2025
96b3ee2
Restore mcp.json configuration file with server definitions for Micro…
norschel Jul 18, 2025
00de85f
Refactor Azure DevOps connection method to streamline Microsoft Accou…
norschel Jul 18, 2025
4e00c57
Merge branch 'master' into copilot/fix-47
norschel Jul 22, 2025
e23368d
Merge branch 'master' into copilot/fix-47
norschel Jul 22, 2025
5cc6330
Improve Azure DevOps authentication modal with proper VS Code modal d…
Copilot Mar 12, 2026
e3ec22a
Merge branch 'master' into copilot/fix-47
norschel Mar 14, 2026
ec7f238
Apply suggestion from @Copilot
norschel Mar 14, 2026
8787d60
Merge branch 'master' into copilot/fix-47
norschel May 31, 2026
67c2d40
Fix Microsoft auth scope for Azure DevOps and repair corrupted PR fun…
Copilot May 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
{
"id": "microsoft",
"scopes": [
"https://app.vssps.visualstudio.com/user_impersonation"
"499b84ac-1321-427f-aa17-267ca6975798/.default"
]
}
],
Expand Down
4 changes: 2 additions & 2 deletions src-tests/authenticationTest.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tests/authenticationTest.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src-tests/authenticationTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async function testAuthenticationImplementation() {
// Check for Microsoft authentication implementation
const hasMicrosoftAuth = funcString.includes("vscode.authentication.getSession") &&
funcString.includes("microsoft") &&
funcString.includes("https://app.vssps.visualstudio.com/user_impersonation");
funcString.includes("499b84ac-1321-427f-aa17-267ca6975798/.default");

if (!hasMicrosoftAuth) {
console.error("❌ Microsoft authentication implementation not found");
Expand Down Expand Up @@ -55,7 +55,7 @@ async function testAuthenticationImplementation() {

// Check for user prompt options
const hasUserPrompts = funcString.includes("Sign In") &&
funcString.includes("Open Settings") &&
funcString.includes("Configure PAT Token") &&
funcString.includes("showWarningMessage");

if (!hasUserPrompts) {
Expand Down
40 changes: 18 additions & 22 deletions src/azd/azDevOpsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,28 +66,24 @@ export async function getAzureDevOpsConnection(orgUrl: string): Promise<azdev.We
logInfo("Attempting Azure DevOps connection with Microsoft Account authentication");

// Silently check for an existing Microsoft session — no UI prompt at this stage
const scopes = [
"499b84ac-1321-427f-aa17-267ca6975798/.default",
"https://app.vssps.visualstudio.com/user_impersonation"
];
for (const scope of scopes) {
try {
const session = await vscode.authentication.getSession(
"microsoft",
[scope],
{ createIfNone: false }
);
if (session) {
logInfo(`Microsoft authentication successful with scope '${scope}', using Bearer token`);
const authHandler = azdev.getBearerHandler(session.accessToken);
const connection = new azdev.WebApi(orgUrl, authHandler);
connection.connect();
logInfo(`Successfully created Azure DevOps connection using Microsoft Account for organization: ${orgUrl}`);
return connection;
}
} catch (error) {
logInfo(`Microsoft authentication not available with scope '${scope}': ${error}`);
try {
// 499b84ac-1321-427f-aa17-267ca6975798 is the well-known resource/app ID of Azure DevOps.
// The "/.default" suffix is required by the MSAL-based VS Code Microsoft authentication
// provider; the legacy "user_impersonation" scope is rejected as an invalid scope.
const session = await vscode.authentication.getSession(
"microsoft",
["499b84ac-1321-427f-aa17-267ca6975798/.default"],
{ createIfNone: false }
);
if (session) {
logInfo("Microsoft authentication successful (existing session)");
const authHandler = azdev.getBearerHandler(session.accessToken);
const connection = new azdev.WebApi(orgUrl, authHandler);
logInfo(`Successfully created Azure DevOps connection using Microsoft Account for organization: ${orgUrl}`);
return connection;
}
} catch (error) {
logInfo(`Microsoft authentication not available silently: ${error}`);
}

// Fallback to Personal Access Token (PAT)
Expand Down Expand Up @@ -120,7 +116,7 @@ export async function getAzureDevOpsConnection(orgUrl: string): Promise<azdev.We
try {
const session = await vscode.authentication.getSession(
"microsoft",
["https://app.vssps.visualstudio.com/user_impersonation"],
["499b84ac-1321-427f-aa17-267ca6975798/.default"],
{ createIfNone: true }
);

Expand Down
3 changes: 0 additions & 3 deletions src/azd/pullrequests/azDevOpsPullrequestFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ export function StateMultipleAzDPrsInStream(
searchQuery: string
) {
stream.markdown(`🔍 Found ${pullrequests.length} pull request${pullrequests.length !== 1 ? 's' : ''} with title containing "${searchQuery}":\n\n`);
return await getAzureDevOpsConnection(orgUrl);
}

async function getAzureDevOpsConnection(orgUrl: string): Promise<WebApi> {
pullrequests.forEach((pr, index) => {
const statusText = (PullRequestStatus as any)[pr.status] || `Status ${pr.status}`;
stream.markdown(`${index + 1}. 🔵**PR #${pr.pullRequestId}** [_${statusText}_]: **${pr.title}**\n`);
Expand Down