You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Angular UI与.NET Core后端采用OAuth流访问VSTS API?

Absolutely, this setup is completely achievable—even if you can’t find a single end-to-end example, all the building blocks exist and play nicely together. Let’s break down how to implement OAuth for Azure DevOps (formerly VSTS) with an Angular frontend and .NET Core backend:

Core Concept

The key here is to keep sensitive credentials (like your app’s client secret) out of the frontend. The flow will be:

  1. Frontend redirects users to Azure DevOps’ OAuth authorization page
  2. User grants access, and Azure DevOps sends an authorization code to your backend’s callback endpoint
  3. Backend exchanges this code for an access token (and refresh token)
  4. Backend either uses the token to call Azure DevOps APIs directly (and returns data to the frontend) or securely passes a limited token to the frontend for direct calls (though proxying via backend is safer)
Backend (.NET Core) Setup

1. Register Your Azure DevOps App

First, create an app registration in Azure DevOps:

  • Go to your Azure DevOps organization settings → OAuth Configuration → New Application
  • Fill in the name, set the callback URL to your backend’s endpoint (e.g., https://your-backend/api/auth/azure-devops-callback)
  • Note down the Client ID and Client Secret (keep this secret safe—never expose it to the frontend)
  • Select the required scopes (e.g., vso.project_read for reading projects, vso.work_write for modifying work items)

2. Configure OAuth in .NET Core

You can use the built-in authentication middleware or handle the code flow manually. Here’s a simplified example using manual handling (more flexible for custom logic):

Add Required Packages

Install these NuGet packages:

Install-Package Microsoft.AspNetCore.Http.Extensions
Install-Package System.Net.Http.Json

Create a Callback Controller

[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
    private readonly IConfiguration _config;
    private readonly HttpClient _httpClient;

    public AuthController(IConfiguration config, HttpClient httpClient)
    {
        _config = config;
        _httpClient = httpClient;
    }

    // Endpoint to receive the authorization code from Azure DevOps
    [HttpGet("azure-devops-callback")]
    public async Task<IActionResult> AzureDevOpsCallback([FromQuery] string code)
    {
        // Exchange code for access token
        var tokenRequest = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["client_id"] = _config["AzureDevOps:ClientId"],
            ["client_secret"] = _config["AzureDevOps:ClientSecret"],
            ["code"] = code,
            ["grant_type"] = "authorization_code",
            ["redirect_uri"] = _config["AzureDevOps:CallbackUrl"]
        });

        var tokenResponse = await _httpClient.PostAsync("https://app.vssps.visualstudio.com/oauth2/token", tokenRequest);
        var tokenData = await tokenResponse.Content.ReadFromJsonAsync<AzureDevOpsToken>();

        // Store the access token and refresh token (e.g., in a database linked to the user)
        // ... your storage logic here ...

        // Redirect back to frontend with a success flag
        return Redirect($"{_config["FrontendUrl"]}/auth-success");
    }

    // Example proxy endpoint to call Azure DevOps API
    [HttpGet("azure-devops/projects")]
    public async Task<IActionResult> GetProjects(string userId)
    {
        // Retrieve the stored access token for the user
        var accessToken = await GetStoredToken(userId);

        var apiResponse = await _httpClient.GetAsync("https://dev.azure.com/your-org/_apis/projects?api-version=7.1-preview.4", 
            new HttpRequestMessageOptions
            {
                Headers = { { "Authorization", $"Bearer {accessToken}" } }
            });

        var projects = await apiResponse.Content.ReadFromJsonAsync<AzureDevOpsProjects>();
        return Ok(projects);
    }

    // Helper method to fetch stored token
    private async Task<string> GetStoredToken(string userId)
    {
        // Implement your token retrieval logic (database/cache)
        return "your-stored-access-token";
    }
}

// Helper classes for deserialization
public class AzureDevOpsToken
{
    public string access_token { get; set; }
    public string refresh_token { get; set; }
    public int expires_in { get; set; }
}

public class AzureDevOpsProjects
{
    public List<Project> value { get; set; }
}

public class Project
{
    public string id { get; set; }
    public string name { get; set; }
}

Add Configuration to appsettings.json

{
  "AzureDevOps": {
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "CallbackUrl": "https://your-backend/api/auth/azure-devops-callback",
    "OrgUrl": "https://dev.azure.com/your-org"
  },
  "FrontendUrl": "https://your-angular-app"
}
Frontend (Angular) Setup

1. Create an Authorization Redirect

Add a button or link in your Angular component to send users to Azure DevOps’ authorization page:

Component Template

<button (click)="connectToAzureDevOps()">Connect to Azure DevOps</button>

Component Logic

import { Component } from '@angular/core';
import { environment } from '../environments/environment';

@Component({
  selector: 'app-auth',
  templateUrl: './auth.component.html'
})
export class AuthComponent {
  connectToAzureDevOps(): void {
    const authUrl = `https://app.vssps.visualstudio.com/oauth2/authorize?client_id=${environment.azureDevOpsClientId}&response_type=code&redirect_uri=${environment.azureDevOpsCallbackUrl}&scope=vso.project_read`;
    window.location.href = authUrl;
  }
}

Add Environment Variables

In src/environments/environment.ts:

export const environment = {
  production: false,
  azureDevOpsClientId: 'your-client-id',
  azureDevOpsCallbackUrl: 'https://your-backend/api/auth/azure-devops-callback'
};

2. Handle Post-Authorization Flow

After the user grants access, they’ll be redirected back to your frontend (via the backend’s callback redirect). You can then call your backend’s proxy endpoints to fetch Azure DevOps data:

// Example service to call backend proxy
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class AzureDevOpsService {
  constructor(private http: HttpClient) {}

  getProjects(userId: string) {
    return this.http.get(`https://your-backend/api/auth/azure-devops/projects?userId=${userId}`);
  }
}
Key Notes for Success
  • Token Refresh: Azure DevOps access tokens expire quickly (usually 1 hour). Implement logic in your backend to use the refresh token to get a new access token automatically when needed.
  • Security: Never expose the client secret to the frontend. All token exchanges must happen server-side.
  • Scopes: Only request the scopes your app actually needs—this reduces security risk and makes users more likely to grant access.
  • Azure DevOps Naming: Remember that VSTS was rebranded to Azure DevOps, so all modern documentation uses this name, and API endpoints now use dev.azure.com instead of visualstudio.com.

内容的提问来源于stack exchange,提问作者Nikheel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:42:30