Mengautentikasi dan mengamankan ekstensi web

Layanan Azure DevOps | Azure DevOps Server | Azure DevOps Server 2022

Artikel ini hanya membahas autentikasi untuk ekstensi web . Ini tidak berlaku untuk ekstensi tugas alur atau ekstensi titik akhir layanan.

Petunjuk / Saran

Untuk panduan pengembangan ekstensi terbaru, termasuk tema dan migrasi dari VSS. SDK, lihat portal pengembang Azure DevOps Extension SDK.

Memanggil REST API dari ekstensi Anda

Sebagian besar ekstensi memanggil REST API Azure DevOps atas nama pengguna saat ini.

  • Menggunakan klien SDK REST: Autentikasi ditangani secara otomatis. Klien meminta token akses dari SDK dan mengatur Authorization header.

  • Menggunakan permintaan HTTP kustom: Minta token dari SDK dan atur header sendiri:

    import * as SDK from "azure-devops-extension-sdk";
    
    SDK.init();
    
    SDK.ready().then(async () => {
        const token = await SDK.getAccessToken();
        const authHeader = `Bearer ${token}`;
    
        // Use authHeader in your fetch/XMLHttpRequest calls
    });
    

Mengautentikasi permintaan ke layanan Anda

Saat ekstensi memanggil layanan backend yang Anda kontrol, Anda perlu memverifikasi bahwa permintaan berasal dari ekstensi yang berjalan di Azure DevOps. SDK menyediakan getAppToken(), yang mengembalikan JWT yang ditandatangani dengan sertifikat ekstensi Anda. Layanan Anda memvalidasi token ini untuk mengautentikasi permintaan.

Dapatkan kunci ekstensi Anda

Kunci unik ekstensi Anda dihasilkan saat Anda menerbitkan. Gunakan untuk memverifikasi keaslian token dari ekstensi Anda.

  1. Buka portal manajemen ekstensi.
  2. Klik kanan ekstensi yang anda terbitkan dan pilih Sertifikat.

kunci

Peringatan

Perubahan cakupan menyebabkan sertifikat berubah. Dapatkan kunci baru setelah memodifikasi cakupan.

Membuat token untuk layanan Anda

Gunakan getAppToken() untuk mendapatkan JWT yang ditandatangani dengan sertifikat ekstensi Anda, lalu kirimkan ke layanan Anda.

import * as SDK from "azure-devops-extension-sdk";

SDK.init();

SDK.ready().then(async () => {
    const token = await SDK.getAppToken();
    
    // Pass this token to your backend as a header or query parameter
    const response = await fetch("https://your-service.example.com/api/data", {
        headers: {
            "Authorization": `Bearer ${token}`
        }
    });
});

Validasi token

Layanan backend Anda memvalidasi JWT menggunakan kunci rahasia ekstensi Anda. Contoh berikut menunjukkan cara menerapkan validasi.

Penting

Jangan pernah memasukkan secara permanen rahasia ekstensi Anda dalam kode sumber. Muat dari variabel lingkungan, Azure Key Vault, atau penyimpanan konfigurasi aman lainnya.

.NET (aplikasi konsol)

Instal paket NuGet:

dotnet add package System.IdentityModel.Tokens.Jwt

Nota

Gunakan versi 7.x atau yang lebih baru. Versi 6.x dan yang lebih lama tidak digunakan lagi. Lihat Siklus hidup versi IdentityModel untuk detailnya.

using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;

string secret = Environment.GetEnvironmentVariable("EXTENSION_SECRET")
    ?? throw new InvalidOperationException("EXTENSION_SECRET not configured");
string issuedToken = ""; // Token from the extension request

var validationParameters = new TokenValidationParameters()
{
    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(secret)),
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidateActor = false,
    RequireSignedTokens = true,
    RequireExpirationTime = true,
    ValidateLifetime = true
};

var tokenHandler = new JwtSecurityTokenHandler();
var principal = tokenHandler.ValidateToken(issuedToken, validationParameters, out SecurityToken token);

ASP.NET Core Web API

Instal paket NuGet:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

Program.cs

using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

string secret = builder.Configuration["ExtensionSecret"]
    ?? throw new InvalidOperationException("ExtensionSecret not configured");

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)),
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateActor = false,
            RequireSignedTokens = true,
            RequireExpirationTime = true,
            ValidateLifetime = true
        };
    });

var app = builder.Build();

app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();

app.Run();

Pengontrol API:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[Authorize]
public class SampleLogicController : ControllerBase
{
   // Requests without a valid token return 401 Unauthorized
}