Webextensies verifiëren en beveiligen

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

In dit artikel wordt alleen aandacht besteed aan verificatie voor webextensies . Dit geldt niet voor pijplijntaakextensies of service-eindpuntextensies.

Aanbeveling

Voor de nieuwste richtlijnen voor uitbreidingsontwikkeling, inclusief thema's en migratie van VSS. SDK raadpleegt u de ontwikkelaarsportal van de Azure DevOps Extension SDK.

REST API's aanroepen vanuit uw extensie

De meeste extensies roepen Azure DevOps REST API's aan namens de huidige gebruiker.

  • De SDK REST-clients gebruiken: verificatie wordt automatisch verwerkt. De clients vragen een toegangstoken aan bij de SDK en stellen de Authorization header in.

  • Aangepaste HTTP-aanvragen gebruiken: een token aanvragen vanuit de SDK en de header zelf instellen:

    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
    });
    

Aanvragen voor uw service verifiëren

Wanneer uw extensie een back-endservice aanroept die u bepaalt, moet u controleren of de aanvraag afkomstig is van uw extensie die wordt uitgevoerd in Azure DevOps. De SDK biedt getAppToken(), waarmee een JWT wordt geretourneerd die is ondertekend met het certificaat van uw extensie. Uw service valideert dit token om de aanvraag te verifiëren.

Haal uw extensiesleutel op.

De unieke sleutel van uw extensie wordt gegenereerd wanneer u publiceert. Gebruik deze om de echtheid van tokens vanuit uw extensie te verifiëren.

  1. Ga naar de portal voor extensiebeheer.
  2. Klik met de rechtermuisknop op de gepubliceerde extensie en selecteer Certificaat.

sleutel

Waarschuwing

Wijzigingen in het bereik zorgen ervoor dat het certificaat wordt gewijzigd. Haal een nieuwe sleutel op nadat u de reikwijdtes hebt gewijzigd.

Een token genereren voor uw service

Gebruik getAppToken() dit om een JWT te laten ondertekenen met het certificaat van uw extensie en deze vervolgens door te geven aan uw service:

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}`
        }
    });
});

Het token valideren

De back-endservice valideert de JWT met behulp van de geheime sleutel van uw extensie. In de volgende voorbeelden ziet u hoe u validatie implementeert.

Belangrijk

Codeer uw extensiegeheim nooit in broncode. Laad deze vanuit omgevingsvariabelen, Azure Key Vault of een ander beveiligd configuratiearchief.

.NET (console toepassing)

Installeer het NuGet-pakket:

dotnet add package System.IdentityModel.Tokens.Jwt

Opmerking

Gebruik versie 7.x of hoger. Versie 6.x en eerder zijn afgeschaft. Zie de levenscyclus van identityModel-versies voor meer informatie.

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

Installeer het NuGet-pakket:

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();

API-controller:

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

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