Autenticação do Serviço Azure SignalR

Este tutorial continua no aplicativo de sala de chat introduzido em Criar uma sala de chat com o Serviço do SignalR. Conclua o início rápido primeiro para configurar sua sala de chat.

Neste tutorial, saiba como criar e integrar o seu método de autenticação usando o Serviço do Microsoft Azure SignalR.

A autenticação inicialmente usada no aplicativo de sala de chat do início rápido é muito simples para cenários do mundo real. O aplicativo permite que cada cliente de declare quem é e o servidor aceita. Esta abordagem é ineficaz no mundo real porque usuários mal-intencionados podem usar identidades falsas para acessar dados confidenciais.

O GitHub fornece APIs de autenticação com base em um protocolo padrão da indústria popular chamado OAuth. Essas APIs permitem que aplicativos de terceiros autenticam contas do GitHub. Neste tutorial, você pode usar essas APIs para implementar a autenticação por meio de uma conta do GitHub antes de permitir logons do cliente no aplicativo da sala de chat. Após a autenticação da conta do GitHub, as informações da conta serão adicionadas como um cookie a ser usado pelo cliente Web para autenticação.

Para obter mais informações sobre a autenticação das APIs OAuth fornecidas pelo GitHub, consulte Noções básicas de autenticação.

Você pode usar qualquer editor de código para concluir as etapas deste início rápido. No entanto, o Visual Studio Code é uma opção excelente nas plataformas Windows, macOS e Linux.

O código para este tutorial está disponível para download no repositório AzureSignalR-samples do GitHub.

OAuth Complete hosted in Azure

Neste tutorial, você aprenderá a:

  • Registrar um novo aplicativo OAuth com sua conta do GitHub
  • Adicionar um controlador de autenticação para oferecer suporte à autenticação do GitHub
  • Implantar seu aplicativo da web ASP.NET Core ao Azure

Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.

Pré-requisitos

Para concluir o tutorial, você deve ter os pré-requisitos a seguir:

Crie um aplicativo OAuth

  1. Abra um navegador da web e navegue até https://github.com e entre em sua conta.

  2. Para sua conta, navegue até Configurações>Configurações de desenvolvedor>Aplicativos OAuth e selecione Novo aplicativo OAuth em Aplicativos OAuth.

  3. Use as seguintes configurações para o novo aplicativo OAuth e selecione Registrar aplicativo:

    Nome da Configuração Valor Sugerido Descrição
    Nome do aplicativo Azure SignalR Chat O usuário do GitHub deve ser capaz de reconhecer e confiar no aplicativo com o qual está se autenticando.
    URL da homepage https://localhost:5001
    Descrição do aplicativo Um exemplo de sala de chat usando o Serviço do Azure SignalR com a autenticação do GitHub Uma descrição útil do aplicativo que ajuda os usuários do aplicativo a entender o contexto da autenticação que está sendo usada.
    URL de retorno de chamada da autorização https://localhost:5001/signin-github Essa configuração é a configuração mais importante para seu aplicativo OAuth. É a URL de retorno de chamada GitHub retorna ao usuário após uma autenticação bem-sucedida. Neste tutorial, você deve usar a URL de retorno de chamada padrão para o pacote AspNet.Security.OAuth.GitHub pacote, /signin-github.
  4. Quando o novo registro de aplicativo OAuth for concluído, adicione a ID do cliente e Segredo do cliente ao Gerenciador de segredo usando os seguintes comandos. Substituir Your_GitHub_Client_Id e Your_GitHub_Client_Secret pelos valores para seu aplicativo OAuth.

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

Implementar o fluxo de OAuth

Vamos reutilizar o aplicativo de chat criado no tutorial Criar uma sala de chat com o Serviço do SignalR.

Atualize Program.cs para dar suporte à autenticação do GitHub

  1. Adicione uma referência aos pacotes AspNet.Security.OAuth.GitHub mais recentes e restaure todos os pacotes.

    dotnet add package AspNet.Security.OAuth.GitHub
    
  2. Abra Program.cs e atualize o código para o seguinte snippet de código:

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

    Dentro do código, AddAuthentication e UseAuthentication são usados para adicionar suporte à autenticação com o aplicativo OAuth do GitHub, e o método auxiliar GetUserCompanyInfoAsync é um código de exemplo mostrando como carregar as informações da empresa do OAuth do GitHub e salvar na identidade do usuário. Você também pode observar que UseHttpsRedirection() é usado, já que o OAuth do GitHub definiu o cookie secure que passa apenas para o esquema protegido https. Além disso, não se esqueça de atualizar o local Properties/lauchSettings.json para adicionar o ponto de extremidade https:

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

Adicionar um controlador de autenticação

Nesta seção, você implementará uma API Login que autentica clientes usando o aplicativo OAuth do GitHub. Depois de autenticada, a API adiciona um cookie à resposta do cliente Web antes de redirecionar o cliente de volta para o aplicativo de chat. Esse cookie é usado para identificar o cliente.

  1. Adicione um novo arquivo de código do controlador ao diretório GitHubChat\Controllers. Nomeie o arquivo AuthController.cs.

  2. Adicione o seguinte código para o controlador de autenticação. Certifique-se de atualizar o namespace se o diretório do projeto não 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. Salve suas alterações.

Atualizar a classe de Hub

Por padrão, o cliente Web se conecta ao Serviço do SignalR usando um token de acesso gerado pelo SDK do Azure SignalR automaticamente.

Nesta seção, você integrará o fluxo de trabalho de autenticação real adicionando o atributo Authorize à classe hub e atualizará os métodos de hub para ler o nome de usuário da declaração do usuário autenticado.

  1. Abra o Hub\ChatSampleHub.cs e atualize o código para o snippet de código abaixo. O código adiciona o atributo Authorize à classe ChatSampleHub e usa a identidade autenticada do usuário nos métodos do hub. Além disso, o método OnConnectedAsync é adicionado, que registra uma mensagem do sistema na sala de chat sempre que um novo cliente se conecta.

    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. Salve suas alterações.

Atualize o código de cliente da web

  1. Abra wwwroot\index.html e substitua o código que solicita o nome de usuário com o código para usar o cookie retornado pelo controlador de autenticação.

    Atualize o código dentro da função getUserName em index.html para o seguinte para usar cookies:

    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. Atualize a função onConnected para remover o parâmetro username ao invocar os métodos broadcastMessage e echo do hub:

    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. Na parte inferior de index.html, atualize o manipulador de erros para connection.start() conforme mostrado abaixo para solicitar a entrada do usuário.

    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. Salve suas alterações.

Compilar e executar o aplicativo localmente

  1. Salve as alterações em todos os arquivos.

  2. Execute o seguinte comando para executar o aplicativo Web localmente:

    dotnet run
    

    O aplicativo é hospedado localmente na porta 5000 por padrão:

    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. Inicie uma janela de navegador e navegue até https://localhost:5001. Selecione o link aqui na parte superior para entrar com o GitHub.

    OAuth Complete hosted in Azure

    Você será solicitado a autorizar o acesso do aplicativo de chat à sua conta do GitHub. Selecione o botão Autorizar.

    Authorize OAuth App

    Você é redirecionado de volta para o aplicativo de chat e conectado com o nome da sua conta do GitHub. O aplicativo Web determinou o nome da sua conta autenticando você usando a nova autenticação que você adicionou.

    Account identified

    Com o aplicativo de chat agora executando a autenticação com o GitHub e armazenando as informações de autenticação como cookies, a próxima etapa envolve implantá-la no Azure. Esta abordagem permite que outros usuários se autentiquem usando suas respectivas contas e se comuniquem em várias estações de trabalho.

Implantar o aplicativo no Azure

Preparar o ambiente para a CLI do Azure:

Nesta seção, você usará a CLI do Azure para criar um novo aplicativo Web no Serviço de Aplicativo do Azure para hospedar o seu aplicativo do ASP.NET no Azure. O aplicativo Web está configurado para usar a implantação local do Git. O aplicativo Web também é configurado com a cadeia de conexão do SignalR, os segredos do aplicativo OAuth do GitHub e um usuário de implantação.

Ao criar os recursos a seguir, certifique-se de usar o mesmo grupo de recursos que o recurso SignalR Service reside. Esta abordagem facilita muito a limpeza mais tarde quando você deseja remover todos os recursos. Os exemplos fornecidos supõe que você usou o nome de grupo nos tutorais anteriores, SignalRTestResources.

Criar o aplicativo web e o plano

Copie o texto para os comandos abaixo e atualize os parâmetros. Cole o script atualizado no Azure Cloud Shell e pressione Enter para criar um novo aplicativo de web e de plano de serviço de aplicativo.

#========================================================================
#=== 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
Parâmetro Descrição
ResourceGroupName Este nome de grupo de recursos foi sugerido nos tutoriais anteriores. É uma boa ideia manter todos os recursos do tutorial agrupados. Use o mesmo nome de grupo de recursos que é usado na seção anterior.
WebAppPlan Insira um nome de Plano do Serviço de Aplicativo nova e exclusivo.
WebAppName Este parâmetro é o nome do novo aplicativo Web e parte da URL. Torne-o exclusivo. Por exemplo, signalrtestwebapp22665120.

Adicionar configurações de aplicativo para o aplicativo Web

Nesta seção, você adicionará configurações de aplicativo para os seguintes componentes:

  • Cadeia de caracteres de conexão do recurso SignalR Service
  • ID do cliente de aplicativo GitHub OAuth
  • Segredo do cliente do aplicativo GitHub OAuth

Copie o texto para os comandos abaixo e atualize os parâmetros. Cole o script atualizado no Azure Cloud Shell e aperte Enter para adicionar as configurações do aplicativo:

#========================================================================
#=== 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"
Parâmetro Descrição
GitHubClientId Atribua a essa variável a ID do segredo do cliente para o seu aplicativo OAuth do GitHub.
GitHubClientSecret Atribua a esta variável a senha secreta para o seu aplicativo GitHub OAuth.
ResourceGroupName Atualize esta variável para ser o mesmo nome do grupo de recurso usado na seção anterior.
SignalRServiceResource Atualize essa variável com o nome do recurso de serviço SignalR criado no início rápido. Por exemplo, signalrtestsvc48778624.
WebAppName Atualize essa variável com o nome do novo aplicativo web que você criou na seção anterior.

Configurar o aplicativo Web para implantação local do Git

No Azure Cloud Shell, cole o script a seguir. Este script cria um novo nome de usuário e senha de implantação que você usa ao implantar seu código no aplicativo Web com o Git. O script também configura o aplicativo Web para implantação com um repositório Git local e retorna a URL de implantação do 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
Parâmetro Descrição
DeploymentUserName Escolha um novo nome de usuário de implantação.
DeploymentUserPassword Escolha uma senha para o novo usuário de implantação.
ResourceGroupName Use o mesmo nome de grupo de recursos que é usado na seção anterior.
WebAppName Este parâmetro é o nome do novo aplicativo Web que você criou anteriormente.

Anote a URL de implantação do Git retornada deste comando. Você usará esta URL mais tarde.

Implantar seu código no novo aplicativo web do Azure

Para implantar seu código, execute os seguintes comandos em um shell do Git.

  1. Navegue até raiz do diretório do projeto. Se você não tiver o projeto inicializado com um repositório Git, execute o seguinte comando:

    git init
    
  2. Adicione um controle remoto para a URL de implantação do Git que você anotou anteriormente:

    git remote add Azure <your git deployment url>
    
  3. Prepare todos os arquivos no repositório inicializado e adicione uma confirmação.

    git add -A
    git commit -m "init commit"
    
  4. Implante seu código no novo aplicativo Web do Azure.

    git push Azure main
    

    Você será solicitado a autenticar-se para implantar o código no Azure. Insira o nome de usuário e a senha do usuário de implantação criado acima.

Atualizar o aplicativo GitHub OAuth

A última coisa que você precisa fazer é atualizar a URL da home page e a URL de retorno de chamada de autorização do aplicativo GitHub OAuth para apontar para o ponto do novo aplicativo hospedado.

  1. Abra https://github.com em um navegador e navegue até Configurações>Configurações do desenvolvedor>Aplicativos Oauth em sua conta.

  2. Selecione o seu aplicativo de autenticação e atualize a URL da página inicial e a URL de retorno de chamada de autorização, conforme mostrado abaixo:

    Configuração Exemplo
    URL da homepage https://signalrtestwebapp22665120.azurewebsites.net
    URL de retorno de chamada da autorização https://signalrtestwebapp22665120.azurewebsites.net/signin-github
  3. Navegue até a URL do aplicativo web e teste o aplicativo.

    OAuth Complete hosted in Azure

Limpar os recursos

Se você seguir adiante com o próximo tutorial, poderá manter os recursos criados neste início rápido e reutilizá-los no próximo tutorial.

Caso contrário, se você não for mais usar o aplicativo de exemplo do início rápido, exclua os recursos do Azure criados neste início rápido para evitar encargos.

Importante

A exclusão de um grupo de recursos é irreversível, e o grupo de recursos e todos os recursos contidos nele são excluídos permanentemente. Não exclua acidentalmente o grupo de recursos ou os recursos incorretos. Se tiver criado os recursos para hospedar este exemplo dentro de um grupo de recursos existente que contém recursos que você quer manter, exclua cada recurso individualmente de suas respectivas folhas, em vez de excluir o grupo de recursos.

Entre no portal do Azure e selecione Grupos de recursos.

Na caixa de texto Filtrar por nome... , digite o nome do seu grupo de recursos. As instruções deste artigo usaram um grupo de recursos chamado SignalRTestResources. Em seu grupo de recursos, na lista de resultados, clique em ... , depois em Excluir grupo de recursos.

Delete

Você receberá uma solicitação para confirmar a exclusão do grupo de recursos. Digite o nome do grupo de recursos para confirmar e selecione Excluir.

Após alguns instantes, o grupo de recursos, e todos os recursos contidos nele, serão excluídos.

Próximas etapas

Neste tutorial, você adicionou a autenticação com o OAuth para fornecer uma abordagem melhor para autenticação com o serviço do Azure SignalR. Para saber mais sobre como usar o Servidor do Azure SignalR, continue para os exemplos de CLI do Azure para o Serviço SignalR.