Partilhar via


Autenticar e proteger extensões da Web

Serviços de DevOps do Azure | Azure DevOps Server | Azure DevOps Server 2022

Este artigo aborda apenas a autenticação para extensões web . Não se aplica a extensões de tarefas de pipeline ou extensões de endpoint de serviço.

Sugestão

Para as mais recentes orientações de desenvolvimento de extensões, incluindo tema e migração do VSS. SDK, consulte o portal para programadores do Azure DevOps Extension SDK.

Chamar APIs REST a partir da sua extensão

A maioria das extensões chama APIs REST do Azure DevOps em nome do utilizador atual.

  • Utilizando os clientes SDK REST: A autenticação é gerida automaticamente. Os clientes solicitam um token de acesso ao SDK e definem o Authorization cabeçalho.

  • Usando pedidos HTTP personalizados: Pede um token ao SDK e define o cabeçalho tu mesmo:

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

Autentique solicitações ao seu serviço

Quando a sua extensão chama um serviço backend que controla, precisa de verificar que o pedido veio da sua extensão a correr no Azure DevOps. O SDK fornece getAppToken(), que devolve um JWT assinado com o certificado da sua extensão. O seu serviço valida este token para autenticar o pedido.

Obtenha a chave da sua extensão

A chave única da sua extensão é gerada quando publica. Usa-o para verificar a autenticidade dos tokens da tua extensão.

  1. Vai ao portal de gestão de extensões.
  2. Clique com o botão direito na sua extensão publicada e selecione Certificado.

chave

Advertência

Alterações no âmbito fazem com que o certificado mude. Obtém uma nova chave depois de modificares os telescópios.

Gera um token para o teu serviço

Use getAppToken() para obter um JWT assinado com o certificado da sua extensão e, em seguida, passe-o ao seu serviço.

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

Validar o token

O seu serviço backend valida o JWT usando a chave secreta da sua extensão. Os exemplos seguintes mostram como implementar a validação.

Importante

Nunca codifique a chave secreta da sua extensão no código-fonte. Carrega-o a partir de variáveis de ambiente, Azure Key Vault ou outro armazenamento de configuração seguro.

.NET (aplicação de consola)

Instale o pacote NuGet:

dotnet add package System.IdentityModel.Tokens.Jwt

Observação

Use a versão 7.x ou posterior. A versão 6.x e anteriores estão obsoletas. Consulte o ciclo de vida da versão do IdentityModel para mais detalhes.

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 API Web

Instale o pacote 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();

Controlador de 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
}