autenticazione del servizio Azure SignalR

Questa esercitazione continua sull'applicazione chat room introdotta in Creare una chat room con Servizio SignalR. Completare prima di tutto l'avvio rapido per configurare la chat room.

Questa esercitazione illustra come creare e integrare il metodo di autenticazione usando Microsoft Servizio Azure SignalR.

L'autenticazione utilizzata inizialmente nell'applicazione di chat room della guida di avvio rapido è troppo semplice per gli scenari reali. L'applicazione consente a ogni client di dichiarare la propria identità, mentre il server si limita ad accettare tale identità. Questo approccio è inefficace nel mondo reale perché gli utenti malintenzionati possono usare identità false per accedere ai dati sensibili.

GitHub fornisce API di autenticazione basate su un diffuso protocollo standard di settore chiamato OAuth. Queste API consentono alle applicazioni di terze parti di autenticare account GitHub. In questa esercitazione è possibile usare queste API per implementare l'autenticazione tramite un account GitHub prima di consentire l'accesso client all'applicazione chat room. Dopo l'autenticazione dell'account GitHub, le informazioni sull'account verranno aggiunte come cookie da usare dal client Web per l'autenticazione.

Per altre informazioni sulle API di autenticazione OAuth fornite tramite GitHub, vedere Basics of Authentication (Nozioni di base sull'autenticazione).

Per completare i passaggi descritti in questa guida di avvio rapido è possibile usare qualsiasi editor di codice. Tuttavia, Visual Studio Code è un'ottima scelta per le piattaforme Windows, macOS e Linux.

Il codice per questa esercitazione è disponibile per il download nel repository GitHub AzureSignalR-samples.

OAuth Complete hosted in Azure

In questa esercitazione apprenderai a:

  • Registrare una nuova app OAuth con l'account GitHub
  • Aggiungere un controller di autenticazione per supportare l'autenticazione di GitHub
  • Distribuire l'app Web ASP.NET Core in Azure

Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.

Prerequisiti

Per completare questa esercitazione, sono previsti i prerequisiti seguenti:

Creare un'app OAuth

  1. Aprire un Web browser, passare a https://github.com e accedere al proprio account.

  2. Per l'account passare a Impostazioni> App>OAuth impostazioni di sviluppo e selezionare Nuova app OAuth in App OAuth.

  3. Usare le impostazioni seguenti per la nuova app OAuth e quindi selezionare Registra applicazione:

    Nome dell'impostazione Valore consigliato Descrizione
    Nome applicazione Chat Azure SignalR L'utente di GitHub deve essere in grado di riconoscere e considerare attendibile l'app con cui esegue l'autenticazione.
    URL della home page https://localhost:5001
    Descrizione applicazione Un esempio di chat room che usa il servizio Azure SignalR con l'autenticazione di GitHub Descrizione utile dell'applicazione che consente agli utenti dell'applicazione di comprendere il contesto dell'autenticazione in uso.
    URL di callback dell'autorizzazione https://localhost:5001/signin-github Questa impostazione è la più importante per l'applicazione OAuth. È l'URL di callback che GitHub restituisce all'utente al termine dell'autenticazione. In questa esercitazione è necessario usare l'URL di callback predefinito per il pacchetto AspNet.Security.OAuth.GitHub, ovvero /signin-github.
  4. Una volta completata la registrazione della nuova app OAuth, aggiungere l'ID client e il segreto client a Secret Manager usando i comandi seguenti. Sostituire Your_GitHub_Client_Id e Your_GitHub_Client_Secret con i valori per l'app OAuth.

    dotnet user-secrets set GitHubClientId Your_GitHub_Client_Id
    dotnet user-secrets set GitHubClientSecret Your_GitHub_Client_Secret
    

Implementare il flusso di OAuth

Riusamo l'app di chat creata nell'esercitazione Creare una chat room con Servizio SignalR.

Aggiornamento Program.cs per supportare l'autenticazione GitHub

  1. Aggiungere un riferimento ai pacchetti AspNet.Security.OAuth.GitHub più recenti e ripristinare tutti i pacchetti.

    dotnet add package AspNet.Security.OAuth.GitHub
    
  2. Aprire Program.cs e aggiornare il codice al frammento di codice seguente:

    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authentication.OAuth;
    
    using System.Net.Http.Headers;
    using System.Security.Claims;
    
    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services
        .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie()
        .AddGitHub(options =>
        {
            options.ClientId = builder.Configuration["GitHubClientId"] ?? "";
            options.ClientSecret = builder.Configuration["GitHubClientSecret"] ?? "";
            options.Scope.Add("user:email");
            options.Events = new OAuthEvents
            {
                OnCreatingTicket = GetUserCompanyInfoAsync
            };
        });
    
    builder.Services.AddControllers();
    builder.Services.AddSignalR().AddAzureSignalR();
    
    var app = builder.Build();
    
    app.UseHttpsRedirection();
    app.UseDefaultFiles();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapControllers();
    app.MapHub<ChatSampleHub>("/chat");
    
    app.Run();
    
    static async Task GetUserCompanyInfoAsync(OAuthCreatingTicketContext context)
    {
        var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
    
        var response = await context.Backchannel.SendAsync(request,
            HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
        var user = await response.Content.ReadFromJsonAsync<GitHubUser>();
        if (user?.company != null)
        {
            context.Principal?.AddIdentity(new ClaimsIdentity(new[]
            {
                new Claim("Company", user.company)
            }));
        }
    }
    
    class GitHubUser
    {
        public string? company { get; set; }
    }
    

    All'interno del codice AddAuthentication e UseAuthentication vengono usati per aggiungere il supporto per l'autenticazione con l'app GitHub OAuth e GetUserCompanyInfoAsync il metodo helper è il codice di esempio che mostra come caricare le informazioni aziendali da GitHub OAuth e salvarle nell'identità utente. È anche possibile notare che UseHttpsRedirection() viene usato dal cookie impostato secure da OAuth di GitHub che passa solo allo schema protetto https . Inoltre, non dimenticare di aggiornare l'endpoint locale Properties/lauchSettings.json per aggiungere l'endpoint https:

    {
      "profiles": {
        "GitHubChat" : {
          "commandName": "Project",
          "launchBrowser": true,
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          },
          "applicationUrl": "http://0.0.0.0:5000/;https://0.0.0.0:5001/;"
        }
      }
    }
    

Aggiungere un controller di autenticazione

In questa sezione si implementa un'API Login che autentica i client usando l'app OAuth GitHub. Dopo l'autenticazione, l'API aggiunge un cookie alla risposta del client Web prima di reindirizzare il client all'app di chat. Tale cookie viene quindi usato per identificare il client.

  1. Aggiungere un nuovo file di codice controller alla directory GitHubChat\Controllers . Assegnare il nome AuthController.cs al file.

  2. Aggiungere il codice seguente per il controller di autenticazione. Assicurarsi di aggiornare lo spazio dei nomi, se la directory del progetto non era GitHubChat:

    using AspNet.Security.OAuth.GitHub;
    
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Mvc;
    
    namespace GitHubChat.Controllers
    {
        [Route("/")]
        public class AuthController : Controller
        {
            [HttpGet("login")]
            public IActionResult Login()
            {
                if (User.Identity == null || !User.Identity.IsAuthenticated)
                {
                    return Challenge(GitHubAuthenticationDefaults.AuthenticationScheme);
                }
    
                HttpContext.Response.Cookies.Append("githubchat_username", User.Identity.Name ?? "");
                HttpContext.SignInAsync(User);
                return Redirect("/");
            }
        }
    }
    
  3. Salvare le modifiche.

Aggiornare la classe Hub

Per impostazione predefinita, il client Web si connette a Servizio SignalR usando un token di accesso generato automaticamente da Azure SignalR SDK.

In questa sezione si integra il flusso di lavoro di autenticazione reale aggiungendo l'attributo Authorize alla classe hub e aggiornando i metodi hub per leggere il nome utente dall'attestazione dell'utente autenticato.

  1. Aprire Hub\ChatSampleHub.cs e aggiornare il codice al frammento di codice seguente. Il codice aggiunge l'attributo Authorize alla ChatSampleHub classe e usa l'identità autenticata dell'utente nei metodi hub. Viene inoltre aggiunto il OnConnectedAsync metodo , che registra un messaggio di sistema nella chat room ogni volta che un nuovo client si connette.

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.SignalR;
    
    [Authorize]
    public class ChatSampleHub : Hub
    {
        public override Task OnConnectedAsync()
        {
            return Clients.All.SendAsync("broadcastMessage", "_SYSTEM_", $"{Context.User?.Identity?.Name} JOINED");
        }
    
        // Uncomment this line to only allow user in Microsoft to send message
        //[Authorize(Policy = "Microsoft_Only")]
        public Task BroadcastMessage(string message)
        {
            return Clients.All.SendAsync("broadcastMessage", Context.User?.Identity?.Name, message);
        }
    
        public Task Echo(string message)
        {
            var echoMessage = $"{message} (echo from server)";
            return Clients.Client(Context.ConnectionId).SendAsync("echo", Context.User?.Identity?.Name, echoMessage);
        }
    }
    
  2. Salvare le modifiche.

Aggiornare il codice del client Web

  1. Aprire wwwroot\index.html e sostituire il codice che richiede il nome utente con il codice che usa il cookie restituito dal controller di autenticazione.

    Aggiornare il codice all'interno della funzione getUserName in index.html ai seguenti per usare i cookie:

    function getUserName() {
      // Get the user name cookie.
      function getCookie(key) {
        var cookies = document.cookie.split(";").map((c) => c.trim());
        for (var i = 0; i < cookies.length; i++) {
          if (cookies[i].startsWith(key + "="))
            return unescape(cookies[i].slice(key.length + 1));
        }
        return "";
      }
      return getCookie("githubchat_username");
    }
    
  2. Aggiornare onConnected la funzione per rimuovere il parametro quando si richiama il username metodo broadcastMessage hub e echo:

    function onConnected(connection) {
      console.log("connection started");
      connection.send("broadcastMessage", "_SYSTEM_", username + " JOINED");
      document.getElementById("sendmessage").addEventListener("click", function (event) {
        // Call the broadcastMessage method on the hub.
        if (messageInput.value) {
          connection.invoke("broadcastMessage", messageInput.value)
            .catch((e) => appendMessage("_BROADCAST_", e.message));
        }
    
        // Clear text box and reset focus for next comment.
        messageInput.value = "";
        messageInput.focus();
        event.preventDefault();
      });
      document.getElementById("message").addEventListener("keypress", function (event) {
        if (event.keyCode === 13) {
          event.preventDefault();
          document.getElementById("sendmessage").click();
          return false;
        }
      });
      document.getElementById("echo").addEventListener("click", function (event) {
        // Call the echo method on the hub.
        connection.send("echo", messageInput.value);
    
        // Clear text box and reset focus for next comment.
        messageInput.value = "";
        messageInput.focus();
        event.preventDefault();
      });
    }
    
  3. Nella parte inferiore di index.html aggiornare il gestore degli errori per come illustrato di seguito per connection.start() richiedere all'utente di eseguire l'accesso.

    connection.start()
      .then(function () {
        onConnected(connection);
      })
      .catch(function (error) {
        console.error(error.message);
        if (error.statusCode && error.statusCode === 401) {
          appendMessage(
            "_BROADCAST_",
            "You\"re not logged in. Click <a href="/login">here</a> to login with GitHub."
          );
        }
      });
    
  4. Salvare le modifiche.

Compilare ed eseguire l'app in locale

  1. Salvare le modifiche di tutti i file.

  2. Eseguire il comando seguente per eseguire l'app Web in locale:

    dotnet run
    

    L'app è ospitata localmente sulla porta 5000 per impostazione predefinita:

    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: http://0.0.0.0:5000
    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: https://0.0.0.0:5001
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Development
    
  3. Avviare una finestra del browser e passare a https://localhost:5001. Selezionare il collegamento qui nella parte superiore per accedere con GitHub.

    OAuth Complete hosted in Azure

    Viene richiesto di autorizzare l'accesso dell'app di chat all'account GitHub. Selezionare il pulsante Authorize.

    Authorize OAuth App

    Si viene reindirizzati all'applicazione di chat e si è connessi con il nome dell'account GitHub. L'applicazione Web ha determinato il nome dell'account autenticando l'utente usando la nuova autenticazione aggiunta.

    Account identified

    Con l'app di chat ora esegue l'autenticazione con GitHub e archivia le informazioni di autenticazione come cookie, il passaggio successivo prevede la distribuzione in Azure. Questo approccio consente ad altri utenti di eseguire l'autenticazione usando i rispettivi account e comunicare da diverse workstation.

Distribuire l'app in Azure

Preparare l'ambiente per l'interfaccia della riga di comando di Azure:

In questa sezione si usa l'interfaccia della riga di comando di Azure per creare una nuova app Web in app Azure Servizio per ospitare l'applicazione ASP.NET in Azure. L'app Web è configurata per l'uso della distribuzione Git locale. L'app Web è configurata anche con i segreti dell'app SignalR stringa di connessione, i segreti dell'app OAuth di GitHub e un utente di distribuzione.

Quando si creano le risorse seguenti, assicurarsi di usare lo stesso gruppo di risorse in cui si trova la risorsa servizio SignalR. Questo approccio semplifica notevolmente la pulizia in un secondo momento quando si vogliono rimuovere tutte le risorse. Gli esempi proposti presuppongono che si usi il nome di gruppo consigliato nelle esercitazioni precedenti: SignalRTestResources.

Creare l'app Web e un piano

Copiare il testo per i comandi seguenti e aggiornare i parametri. Incollare lo script aggiornato in Azure Cloud Shell, quindi premere Invio per creare un nuovo piano di servizio app e una nuova app Web.

#========================================================================
#=== Update these variable for your resource group name.              ===
#========================================================================
ResourceGroupName=SignalRTestResources

#========================================================================
#=== Update these variable for your web app.                          ===
#========================================================================
WebAppName=myWebAppName
WebAppPlan=myAppServicePlanName

# Create an App Service plan.
az appservice plan create --name $WebAppPlan --resource-group $ResourceGroupName \
    --sku FREE

# Create the new Web App
az webapp create --name $WebAppName --resource-group $ResourceGroupName \
    --plan $WebAppPlan
Parametro Descrizione
ResourceGroupName Questo nome di gruppo di risorse è stato suggerito nelle esercitazioni precedenti. È consigliabile mantenere raggruppate tutte le risorse dell'esercitazione. Usare lo stesso gruppo di risorse utilizzato nelle esercitazioni precedenti.
WebAppPlan Immettere un nome di piano di servizio app nuovo e univoco.
WebAppName Questo parametro è il nome della nuova app Web e parte dell'URL. Renderlo unico. Ad esempio signalrtestwebapp22665120.

Aggiungere le impostazioni dell'app all'app Web

In questa sezione vengono aggiunte le impostazioni dell'app per i componenti seguenti:

  • Stringa di connessione della risorsa servizio SignalR
  • ID client dell'app OAuth di GitHub
  • Segreto client dell'app OAuth di GitHub

Copiare il testo per i comandi seguenti e aggiornare i parametri. Incollare lo script aggiornato in Azure Cloud Shell, quindi premere Invio per aggiungere le impostazioni dell'app:

#========================================================================
#=== Update these variables for your GitHub OAuth App.                ===
#========================================================================
GitHubClientId=1234567890
GitHubClientSecret=1234567890

#========================================================================
#=== Update these variables for your resources.                       ===
#========================================================================
ResourceGroupName=SignalRTestResources
SignalRServiceResource=mySignalRresourcename
WebAppName=myWebAppName

# Get the SignalR primary connection string
primaryConnectionString=$(az signalr key list --name $SignalRServiceResource \
  --resource-group $ResourceGroupName --query primaryConnectionString -o tsv)

#Add an app setting to the web app for the SignalR connection
az webapp config appsettings set --name $WebAppName \
    --resource-group $ResourceGroupName \
    --settings "Azure__SignalR__ConnectionString=$primaryConnectionString"

#Add the app settings to use with GitHub authentication
az webapp config appsettings set --name $WebAppName \
    --resource-group $ResourceGroupName \
    --settings "GitHubClientId=$GitHubClientId"
az webapp config appsettings set --name $WebAppName \
    --resource-group $ResourceGroupName \
    --settings "GitHubClientSecret=$GitHubClientSecret"
Parametro Descrizione
GitHubClientId Assegnare questa variabile l'ID client segreto per l'app OAuth gitHub.
GitHubClientSecret Assegnare a questa variabile la password segreta per l'app OAuth di GitHub.
ResourceGroupName Aggiornare questa variabile in modo che corrisponda al nome del gruppo di risorse che è stato usato nella sezione precedente.
SignalRServiceResource Aggiornare questa variabile con il nome della risorsa servizio SignalR creata nella guida di avvio rapido. Ad esempio signalrtestsvc48778624.
WebAppName Aggiornare questa variabile con il nome della nuova app Web che è stata creata nella sezione precedente.

Configurare l'app Web per la distribuzione Git locale

In Azure Cloud Shell incollare lo script seguente. Questo script crea un nuovo nome utente e una nuova password di distribuzione usati durante la distribuzione del codice nell'app Web con Git. Lo script consente anche di configurare l'app Web per la distribuzione con un repository Git locale e restituisce l'URL di distribuzione Git.

#========================================================================
#=== Update these variables for your resources.                       ===
#========================================================================
ResourceGroupName=SignalRTestResources
WebAppName=myWebAppName

#========================================================================
#=== Update these variables for your deployment user.                 ===
#========================================================================
DeploymentUserName=myUserName
DeploymentUserPassword=myPassword

# Add the desired deployment user name and password
az webapp deployment user set --user-name $DeploymentUserName \
    --password $DeploymentUserPassword

# Configure Git deployment and note the deployment URL in the output
az webapp deployment source config-local-git --name $WebAppName \
    --resource-group $ResourceGroupName \
    --query [url] -o tsv
Parametro Descrizione
DeploymentUserName Scegliere un nuovo nome utente di distribuzione.
DeploymentUserPassword Scegliere una password per il nuovo utente di distribuzione.
ResourceGroupName Usare lo stesso nome del gruppo di risorse utilizzato nella sezione precedente.
WebAppName Questo parametro è il nome della nuova app Web creata in precedenza.

Annotare l'URL di distribuzione Git restituito dal comando. Questo URL verrà usato in un secondo momento.

Distribuire il codice nell'app Web di Azure

Per distribuire il codice, eseguire i comandi seguenti in una shell di Git.

  1. Passare alla radice della directory di progetto. Se il progetto non è inizializzato con un repository Git, eseguire il comando seguente:

    git init
    
  2. Aggiungere un remote per l'URL di distribuzione Git annotato in precedenza:

    git remote add Azure <your git deployment url>
    
  3. Eseguire lo staging di tutti i file nel repository inizializzato e aggiungere un commit.

    git add -A
    git commit -m "init commit"
    
  4. Distribuire il codice nell'app Web in Azure.

    git push Azure main
    

    Viene richiesto di eseguire l'autenticazione per distribuire il codice in Azure. Immettere il nome utente e la password dell'utente di distribuzione creato in precedenza.

Aggiornare l'app OAuth di GitHub

L'ultima operazione da eseguire è l'aggiornamento dell'URL della home page e dell'URL di callback dell'autorizzazione dell'app OAuth di GitHub in modo da puntare alla nuova app ospitata.

  1. Aprire https://github.com in un browser e passare a Impostazioni>Impostazioni modalità sviluppatore>Oauth Apps (Oauth App) per il proprio account.

  2. Selezionare l'app di autenticazione e aggiornare l'URL della home page e l'URL di callback di autorizzazione, come illustrato di seguito:

    Impostazione Esempio
    URL della home page https://signalrtestwebapp22665120.azurewebsites.net
    URL di callback dell'autorizzazione https://signalrtestwebapp22665120.azurewebsites.net/signin-github
  3. Passare all'URL dell'app Web e testare l'applicazione.

    OAuth Complete hosted in Azure

Pulire le risorse

Se si continuerà all'esercitazione successiva, è possibile mantenere le risorse create in questa guida introduttiva e riutilizzarle con l'esercitazione successiva.

In caso contrario, se l'applicazione di esempio di avvio rapido è stata completata, è possibile eliminare le risorse di Azure create in questa guida introduttiva per evitare addebiti.

Importante

L'eliminazione di un gruppo di risorse è irreversibile e comporta l'eliminazione definitiva del gruppo di risorse e di tutte le risorse incluse nel gruppo. Assicurarsi di non eliminare accidentalmente il gruppo di risorse sbagliato o le risorse errate. Se le risorse per questo esempio sono state create all'interno di un gruppo di risorse esistente che contiene anche elementi da mantenere, è possibile eliminare ogni elemento singolarmente dai rispettivi pannelli anziché eliminare il gruppo di risorse.

Accedere al portale di Azure e selezionare Gruppi di risorse.

Nella casella di testo Filtra per nome... immettere il nome del gruppo di risorse. Le istruzioni di questo articolo usano un gruppo di risorse denominato SignalRTestResources. Nel gruppo di risorse nell'elenco dei risultati fare clic su ... quindi su Elimina gruppo di risorse.

Delete

Verrà chiesto di confermare l'eliminazione del gruppo di risorse. Digitare il nome del gruppo di risorse per confermare e selezionare Elimina.

Dopo qualche istante il gruppo di risorse e tutte le risorse che contiene vengono eliminati.

Passaggi successivi

In questa esercitazione è stata aggiunta l'autenticazione con OAuth per fornire un approccio migliore all'autenticazione con il servizio Azure SignalR. Per altre informazioni sull'uso di Azure SignalR Server, continuare con gli esempi dell'interfaccia della riga di comando di Azure per il servizio SignalR.