Autenticazione e sicurezza

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Questo articolo riguarda solo le estensioni Web e non le estensioni dell'attività Pipelines o le estensioni dell'endpoint di servizio. Per queste attività, è possibile usare l'attività Pubblica per bus di servizio di Azure.

Suggerimento

Vedere la documentazione più recente sullo sviluppo di estensioni con Azure DevOps Extension SDK.

Chiamata di API REST dall'estensione

La maggior parte delle estensioni deve chiamare le API REST di Azure DevOps per conto dell'utente corrente.

  • Se si usa , JavaScript REST clientsl'autenticazione viene gestita automaticamente. Questi client richiedono automaticamente un token di accesso dall'SDK principale e lo impostano nell'intestazione Authorization della richiesta.

  • Se non si usano i client forniti, è necessario richiedere un token da Core SDK e impostarlo nell'intestazione Authorization della richiesta:

    VSS.require(["VSS/Authentication/Services"],
        function (VSS_Auth_Service) {
            VSS.getAccessToken().then(function(token){
                // Format the auth header
                var authHeader = VSS_Auth_Service.authTokenManager.getAuthorizationHeader(token);
    
                // Add token as an Authorization header to your request
            });
        });
    

Autenticazione delle richieste al servizio

Uno scenario comune consiste nell'effettuare chiamate a un servizio back-end da un'estensione. Per verificare che queste chiamate provenano dall'estensione in esecuzione in Azure DevOps e per verificare l'autenticità dell'utente corrente (e altre informazioni di contesto), viene reso disponibile un tipo speciale di token per l'estensione. Questo token contiene informazioni su chi effettua la chiamata e anche una firma che è possibile convalidare per sapere che la richiesta proviene dall'estensione.

Ottenere la chiave dell'estensione

La chiave univoca dell'estensione (generata quando l'estensione viene pubblicata) può essere usata per verificare l'autenticità delle richieste effettuate dall'estensione.

Per ottenere questa chiave, fare clic con il pulsante destro del mouse su un'estensione pubblicata e selezionare Certificato.

key

Avviso

Le modifiche all'ambito in un'estensione causano la modifica del certificato. Se si apportano modifiche all'ambito, è necessaria una nuova chiave di estensione.

Generare un token da fornire al servizio

  1. Il metodo Core SDK getAppToken restituisce una promessa che, se risolta, contiene un token firmato con il certificato dell'estensione.

    VSS.getAppToken().then(function(token){
        // Add token to your request
    });
    
  2. Passare questo token al servizio come parametro di query o intestazione della richiesta.

Analizzare e convalidare il token

Di seguito è riportato un esempio di analisi del token. Prima di tutto, scaricare e archiviare il segreto per l'estensione. È possibile ottenerlo dalla pagina dell'editore. Questo segreto deve essere disponibile per l'applicazione.

.NET Framework

È necessario aggiungere 1 riferimento per ottenere questo esempio da compilare.

  1. Aprire il Gestione pacchetti NuGet e aggiungere un riferimento a System.IdentityModel.Tokens.Jwt. Questo esempio è stato compilato con la versione 5.2.2 di questo pacchetto.
using System.Collections.Generic;
using System.ServiceModel.Security.Tokens;
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.UTF8Encoding.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);
		}
	}
}

.NET Core - WebAPI

È necessario aggiungere 1 riferimento per ottenere questo esempio da compilare.

  1. Aprire il Gestione pacchetti NuGet e aggiungere un riferimento a System.IdentityModel.Tokens.Jwt. Questo esempio è stato compilato con la versione 5.1.4 di questo pacchetto.

Startup.cs

using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
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.AddMvc();

            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, IHostingEnvironment env)
        {
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseMvc();
            app.UseStaticFiles();
        }
    }
}

Controller API:

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