Compartilhar via


Autenticar e proteger extensões da Web

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

Este artigo aborda a autenticação somente para extensões da Web . Ele não se aplica a extensões de tarefa de pipeline ou extensões de ponto de extremidade de serviço.

Dica

Para obter as diretrizes mais recentes de desenvolvimento de extensão, incluindo temas e migração do VSS. SDK, consulte o portal do desenvolvedor do SDK de Extensão do Azure DevOps.

Chamar APIs REST a partir da sua extensão

A maioria das extensões chama as APIs REST do Azure DevOps em nome do usuário atual.

  • Usando os clientes REST do SDK: a autenticação é tratada automaticamente. Os clientes solicitam um token de acesso do SDK e definem o Authorization cabeçalho.

  • Usando solicitações HTTP personalizadas: solicite um token do SDK e defina o cabeçalho por conta própria:

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

Autenticar solicitações para seu serviço

Quando sua extensão chama um serviço de back-end que você controla, você precisa verificar se a solicitação veio da sua extensão em execução no Azure DevOps. O SDK fornece getAppToken(), que retorna um JWT assinado com o certificado da sua extensão. Seu serviço valida esse token para autenticar a solicitação.

Obter a chave da extensão

A chave exclusiva da extensão é gerada quando você publica. Use-o para verificar a autenticidade dos tokens de sua extensão.

  1. Acesse o portal de gerenciamento de extensões.
  2. Clique com o botão direito do mouse na extensão publicada e selecione Certificado.

chave

Aviso

Alterações de escopo fazem com que o certificado seja alterado. Obtenha uma nova chave depois de modificar os escopos.

Gerar um token para seu serviço

Use getAppToken() para obter um JWT assinado com o certificado da sua extensão e, em seguida, encaminhe-o para o 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

Seu serviço de back-end valida o JWT usando a chave secreta da extensão. Os exemplos a seguir mostram como implementar a validação.

Importante

Nunca codifique seu segredo de extensão no código-fonte. Carregue-o de variáveis de ambiente, Azure Key Vault ou outro repositório de configuração seguro.

.NET (aplicativo de console)

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 foram preteridas. Consulte o ciclo de vida da versão IdentityModel para obter 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);

API Web do ASP.NET Core

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
}