Partager via


Authentifier et sécuriser les extensions web

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

Cet article concerne uniquement l’authentification et la sécurité pour les extensions web, et non les extensions de tâche pipelines ou les extensions de point de terminaison de service. Pour ces tâches, vous pouvez utiliser la tâche Publier sur Azure Service Bus.

Appeler des API REST à partir de votre extension

La plupart des extensions doivent appeler des API REST Azure DevOps pour le compte de l’utilisateur actuel.

  • Si vous utilisez l’authentification fournie JavaScript REST clients, l’authentification est automatiquement gérée pour vous. Ces clients demandent un jeton d’accès à partir du Kit de développement logiciel (SDK) principal et le définissent dans l’en-tête d’autorisation de la demande.

  • Si vous n’utilisez pas les clients fournis, vous devez demander un jeton depuis Core SDK et le définir dans l'En-tête d'Autorisation de votre demande :

    import * as SDK from "azure-devops-extension-sdk";
    import { getAccessToken } from "azure-devops-extension-sdk";
    
    SDK.init();
    
    getAccessToken().then((token) => {
        // Format the auth header
        const authHeader = `Bearer ${token}`;
    
        // Add token as an Authorization header to your request
        console.log(authHeader);
    });
    

Conseil / Astuce

Consultez notre documentation la plus récente sur le développement d’extensions à l’aide du Kit de développement logiciel (SDK) d’extension Azure DevOps.

Authentifier les demandes auprès de votre service

Un scénario courant consiste à effectuer des appels à un service back-end à partir d’une extension. Pour vérifier que ces appels proviennent de votre extension s’exécutant dans Azure DevOps et pour authentifier l’utilisateur actuel et d’autres informations de contexte, un type spécial de jeton est fourni à votre extension. Ce jeton contient des informations sur l’appelant et une signature que vous pouvez valider pour vous assurer que la demande provient de votre extension.

Obtenir la clé de votre extension

La clé unique de votre extension, générée lors de la publication de l’extension, peut être utilisée pour vérifier l’authenticité des demandes effectuées à partir de votre extension.

Pour obtenir cette clé, accédez au portail de gestion des extensions, cliquez avec le bouton droit sur une extension publiée, puis sélectionnez Certificat.

key

Avertissement

Les modifications d’étendue dans une extension entraînent la modification du certificat. Si vous apportez des modifications à l’étendue, vous avez besoin d’une nouvelle clé d’extension.

Générer un jeton à remettre à votre service

  1. La méthode du Kit de développement logiciel (SDK) getAppToken Core retourne une promesse qui, lorsqu’elle est résolue, contient un jeton signé avec le certificat de votre extension.

    import * as SDK from "azure-devops-extension-sdk";
    import { getAppToken } from "azure-devops-extension-sdk";
    
    SDK.init();
    
    getAppToken().then((token) => {
    // Add token to your request
    console.log(token);
    });
    
  2. Transmettez ce jeton à votre service en tant que paramètre de requête ou en-tête de requête.

Analyser et valider le jeton

Voici un exemple d’analyse du jeton. Tout d’abord, téléchargez et stockez le secret de votre extension à partir de votre page d’éditeur. Ce secret doit être disponible pour votre application.

.NET Framework

Effectuez la tâche suivante pour ajouter une référence pour obtenir l’exemple à compiler.

Ouvrez le Gestionnaire de package NuGet et ajoutez une référence à System.IdentityModel.Tokens.Jwt. Cet exemple a été généré avec la version 6.8.0 de ce package.

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

namespace TokenSample
{
    class Program
    {
        static void Main(string[] args)
        {
            string secret = ""; // Load your extension's secret
            string issuedToken = ""; // Token you are validating
                
            var validationParameters = new TokenValidationParameters()
            {
                IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(secret)),
                ValidateIssuer = false,
                RequireSignedTokens = true,
                RequireExpirationTime = true,
                ValidateLifetime = true,
                ValidateAudience = false,
                ValidateActor = false
            };

            SecurityToken token = null;
            var tokenHandler = new JwtSecurityTokenHandler();
            var principal = tokenHandler.ValidateToken(issuedToken, validationParameters, out token);
            
            // Use the principal object as needed
            Console.WriteLine(principal.Identity.Name);
        }
    }
}

.NET Core - WebAPI

Effectuez la tâche suivante pour ajouter une référence pour obtenir cet exemple à compiler.

Ouvrez le Gestionnaire de package NuGet et ajoutez une référence à System.IdentityModel.Tokens.Jwt. Cet exemple a été généré avec la version 5.1.4 de ce package.

Startup.cs

using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

namespace TokenSample.Core.API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            string _secret = "ey9asfasdmax..<the secret key downloaded from the Azure DevOps Services publisher page>.9faf7eh";
        
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer((o) =>
                    {
                        o.TokenValidationParameters = new TokenValidationParameters()
                        {
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret)),
                            ValidateIssuer = false,
                            ValidateAudience = false,
                            ValidateActor = false,
                            RequireSignedTokens = true,
                            RequireExpirationTime = true,
                            ValidateLifetime = true
                        };    
                    });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

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

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Vos contrôleurs d’API :

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

[Route("api/[controller]")]
[Authorize]
public class SampleLogicController : ControllerBase
{
   // ...
}