Autenticación de Azure SignalR Service

Este tutorial continúa en la aplicación de salón de chat presentada en Creación de un salón de chat con SignalR Service. Complete primero esa guía de inicio rápido para configurar el salón de chat.

En este tutorial, aprenderá a crear e integrar el método de autenticación mediante Microsoft Azure SignalR Service.

La autenticación utilizada inicialmente en la aplicación de salón de chat de la guía de inicio rápido es demasiado simple para escenarios del mundo real. La aplicación permite que cada cliente notifique quién es y el servidor lo acepta simplemente. Este enfoque es ineficaz en el mundo real porque usuarios malintencionados pueden usar identidades falsas para acceder a datos confidenciales.

GitHub proporciona API de autenticación basadas en un protocolo estándar del sector muy popular llamado OAuth. Estas API permiten a aplicaciones de terceros autenticar cuentas de GitHub. En este tutorial, puede usar estas API para implementar la autenticación mediante una cuenta de GitHub antes de permitir inicios de sesión de clientes en la aplicación de salón de chat. Después de la autenticación de la cuenta de GitHub, la información de la cuenta se agregará como una cookie que será utilizada por el cliente web para la autenticación.

Para más información sobre las API de autenticación de OAuth proporcionadas a través de GitHub, consulte Conceptos básicos de autenticación.

Puede usar cualquier editor de código para realizar los pasos de esta guía de inicio rápido. Sin embargo, Visual Studio Code es una excelente opción disponible en las plataformas Windows, macOS y Linux.

El código de este tutorial está disponible para su descarga en el repositorio de GitHub AzureSignalR-samples.

OAuth Complete hosted in Azure

En este tutorial, aprenderá a:

  • Registrar una nueva aplicación de OAuth con su cuenta de GitHub
  • Agregar un controlador de autenticación para admitir la autenticación de GitHub
  • Implementar la aplicación web de ASP.NET Core en Azure

Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar.

Requisitos previos

Para realizar este tutorial, debe disponer de los siguientes requisitos previos:

Creación de una aplicación de OAuth

  1. Abra un explorador web, vaya a https://github.com e inicie sesión en su cuenta.

  2. En su cuenta, vaya a Configuración>Configuración de desarrollador>Aplicaciones de OAuth y seleccione Nueva aplicación de OAuth en Aplicaciones de OAuth.

  3. Utilice la siguiente configuración para la nueva aplicación de OAuth y, a continuación, seleccione Registrar aplicación:

    Nombre de la configuración Valor sugerido Descripción
    Nombre de la aplicación Azure SignalR Chat El usuario de GitHub debe ser capaz de reconocer y confiar en la aplicación con la que se autentica.
    Dirección URL de la página principal https://localhost:5001
    Descripción de la aplicación Un ejemplo de salón de chat con Azure SignalR Service y la autenticación de GitHub Una descripción útil de la aplicación que ayuda a los usuarios de la aplicación a entender el contexto de la autenticación que se va a usar.
    Dirección URL de devolución de llamada de autorización https://localhost:5001/signin-github Esta configuración es la más importante para la aplicación de OAuth. Es la dirección URL de devolución de llamada que GitHub devuelve al usuario después de una autenticación correcta. En este tutorial, debe usar la dirección URL de devolución de llamada predeterminada para el paquete AspNet.Security.OAuth.GitHub, /signin-github.
  4. Una vez completado el nuevo registro de aplicación de OAuth, agregue el Identificador de cliente y el Secreto de cliente al administrador de secretos utilizando los comandos siguientes. Reemplace Your_GitHub_Client_Id y Your_GitHub_Client_Secret por los valores de la aplicación de OAuth.

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

Implementación del flujo de OAuth

Vamos a reutilizar la aplicación de chat creada en el tutorial Creación de un salón de chat con SignalR Service.

Actualizar Program.cs para admitir la autenticación de GitHub

  1. Agregue una referencia a los paquetes AspNet.Security.OAuth.GitHub más recientes y restaure todos los paquetes.

    dotnet add package AspNet.Security.OAuth.GitHub
    
  2. Abra Program.cs y actualice el código al siguiente fragmento 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 del código, AddAuthentication y UseAuthentication se usan para agregar la compatibilidad de autenticación con la aplicación OAuth de GitHub y el método de asistencia GetUserCompanyInfoAsync es un código de ejemplo que muestra cómo cargar la información de la empresa desde OAuth de GitHub y guardarla en la identidad del usuario. También puede observar que se usa UseHttpsRedirection(), ya que la OAuth de GitHub establece la cookie secure que solo pasa a través del esquema https protegido. Tampoco olvide actualizar el local Properties/lauchSettings.json para agregar el punto de conexión https:

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

Agregar un controlador de autenticación

En esta sección, implementará una API Login que autentica a los clientes mediante la aplicación OAuth de GitHub. Una vez autenticada, la API agrega una cookie a la respuesta al cliente web antes de redirigir al cliente de vuelta a la aplicación de chat. Después, esa cookie se usa para identificar al cliente.

  1. Agregue un nuevo archivo de código de controlador al directorio GitHubChat\Controllers. Llame al archivo AuthController.cs.

  2. Agregue el código siguiente para el controlador de autenticación. Asegúrese de actualizar el espacio de nombres si el directorio del proyecto no 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. Guarde los cambios.

Actualización de la clase Hub

De forma predeterminada, el cliente web se conecta a SignalR Service mediante un token de acceso generado por el SDK de Azure SignalR automáticamente.

En esta sección, integrará el flujo de trabajo de autenticación real mediante la adición del atributo Authorize a la clase del concentrador y actualizará los métodos del concentrador para leer el nombre de usuario desde la notificación del usuario autenticado.

  1. Abra Hub\ChatSampleHub.cs y actualice el código al fragmento de código siguiente. El código agrega el atributo Authorize a la clase ChatSampleHub y utiliza la identidad autenticada del usuario en los métodos del concentrador. Además, se agrega el método OnConnectedAsync, que registra un mensaje del sistema en el salón de chat cada vez que se conecte un cliente nuevo.

    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. Guarde los cambios.

Actualización del código del cliente web

  1. Abra wwwroot\index.html y reemplace el código que solicita el nombre de usuario por el código para usar la cookie devuelta por el controlador de autenticación.

    Actualice el código dentro de la función getUserName en index.html a lo siguiente 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. Actualice la función onConnected para quitar el parámetro username al invocar el método del concentrador broadcastMessage y 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. En la parte inferior de index.html, actualice el controlador de errores para connection.start() tal y como se muestra a continuación para solicitar al usuario que inicie sesión.

    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. Guarde los cambios.

Compilación y ejecución de la aplicación localmente

  1. Guarde los cambios en todos los archivos.

  2. Utilice el siguiente comando para ejecutar la aplicación web localmente:

    dotnet run
    

    La aplicación se hospeda localmente en el puerto 5000 de forma predeterminada:

    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 una ventana del explorador y vaya a https://localhost:5001. Seleccione el vínculo aquí en la parte superior para iniciar sesión con GitHub.

    OAuth Complete hosted in Azure

    Se le pedirá autorizar el acceso de la aplicación de chat a su cuenta de GitHub. Seleccione el botón Autorizar.

    Authorize OAuth App

    Se le redirigirá de vuelta a la aplicación de chat y se inicia sesión con su nombre de cuenta de GitHub. La aplicación web ha determinado su nombre de cuenta al autenticarlo con la nueva autenticación que agregó.

    Account identified

    Con la aplicación de chat ahora se realiza la autenticación con GitHub y se almacena la información de autenticación como cookies, el siguiente paso implica la implementación en Azure. Este enfoque permite a otros usuarios autenticarse mediante sus respectivas cuentas y comunicarse desde varias estaciones de trabajo.

Implementar la aplicación en Azure

Preparación del entorno para la CLI de Azure:

En esta sección, usará la CLI de Azure para crear una nueva aplicación web en Azure App Service para hospedar la aplicación ASP.NET en Azure. La aplicación web se configura para usar la implementación de Git local. La aplicación web también se configura con la cadena de conexión de SignalR, los secretos de la aplicación OAuth de GitHub y un usuario de implementación.

Al crear los recursos siguientes, asegúrese de usar el mismo grupo de recursos en el que reside el recurso del servicio SignalR. Este enfoque hace mucho más fácil la limpieza cuando posteriormente desee eliminar todos los recursos. En los ejemplos se da por supuesto que usa el nombre de grupo recomendado en los tutoriales anteriores, SignalRTestResources.

Creación de la aplicación web y el plan

Copie el texto de los comandos siguientes y actualice los parámetros. Pegue el script actualizado en Azure Cloud Shell y presione ENTRAR para crear un nuevo plan y una aplicación web de App Service.

#========================================================================
#=== 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 Descripción
ResourceGroupName Este nombre de grupo de recursos se sugirió en tutoriales anteriores. Es una buena idea mantener agrupados todos los recursos de los tutoriales. Use el mismo grupo de recursos que utilizó en los tutoriales anteriores.
WebAppPlan Escriba un nombre nuevo y único del plan de App Service.
WebAppName Este parámetro es el nombre de la nueva aplicación web y parte de la dirección URL. Debe ser único. Por ejemplo, signalrtestwebapp22665120.

Adición de la configuración de la aplicación a la aplicación web

En esta sección, agregará la configuración de la aplicación para los siguientes componentes:

  • Cadena de conexión de los recursos del servicio SignalR
  • Identificador de cliente de la aplicación de OAuth de GitHub
  • Secreto de cliente de la aplicación de OAuth de GitHub

Copie el texto de los comandos siguientes y actualice los parámetros. Pegue el script actualizado en Azure Cloud Shell y presione ENTRAR para agregar la configuración de la aplicación:

#========================================================================
#=== 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 Descripción
GitHubClientId Asigne a esta variable el identificador de cliente secreto de la aplicación OAuth de GitHub.
GitHubClientSecret Asigne a esta variable la contraseña secreta de la aplicación de OAuth de GitHub.
ResourceGroupName Actualice esta variable para que sea el mismo nombre de grupo de recursos que usó en la sección anterior.
SignalRServiceResource Actualice esta variable con el nombre del recurso del servicio SignalR que creó en la guía de inicio rápido. Por ejemplo, signalrtestsvc48778624.
WebAppName Actualice esta variable con el nombre de la nueva aplicación web que creó en la sección anterior.

Configuración de la aplicación web para la implementación de Git local

En Azure Cloud Shell, pegue el siguiente script. Este script crea un nuevo nombre de usuario de implementación y una contraseña que va a utilizar al implementar el código en la aplicación web con Git. El script también configura la aplicación web para la implementación con un repositorio de Git local y devuelve la dirección URL de implementación de 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 Descripción
DeploymentUserName Elija un nuevo nombre de usuario de implementación.
DeploymentUserPassword Elija una contraseña para el nuevo usuario de implementación.
ResourceGroupName Utilice el mismo nombre de grupo de recursos que usó en la sección anterior.
WebAppName Este parámetro es el nombre de la nueva aplicación web que creó anteriormente.

Anote la dirección URL de implementación de Git que devuelve este comando. Más adelante usará esta dirección URL.

Implementación del código en la aplicación web de Azure

Para implementar el código, ejecute los comandos siguientes en un shell de Git.

  1. Vaya a la raíz del directorio del proyecto. Si no ha inicializado el proyecto con un repositorio Git, ejecute el comando siguiente:

    git init
    
  2. Agregue un remoto para la dirección URL de implementación de Git que anotó anteriormente:

    git remote add Azure <your git deployment url>
    
  3. Almacene provisionalmente todos los archivos en el repositorio inicializado y agregue una instrucción commit.

    git add -A
    git commit -m "init commit"
    
  4. Implemente el código en la aplicación web en Azure.

    git push Azure main
    

    Se le pedirá autenticarse para implementar el código en Azure. Escriba el nombre de usuario y la contraseña del usuario de implementación que creó anteriormente.

Actualización de la aplicación de OAuth de GitHub

El último paso que debe realizar es actualizar la dirección URL de la página principal y la dirección URL de devolución de llamada de autorización de la aplicación de OAuth de GitHub para que apunte a la nueva aplicación hospedada.

  1. Abra https://github.com en un explorador y, en la cuenta, vaya a Configuración>Opciones del desarrollador>Aplicaciones de Oauth.

  2. Seleccione en la aplicación de autenticación y actualice la dirección URL de la página principal y la URL de devolución de llamada de autorización tal y como se muestra a continuación:

    Configuración Ejemplo
    Dirección URL de la página principal https://signalrtestwebapp22665120.azurewebsites.net
    Dirección URL de devolución de llamada de autorización https://signalrtestwebapp22665120.azurewebsites.net/signin-github
  3. Vaya a la dirección URL de la aplicación web y pruebe la aplicación.

    OAuth Complete hosted in Azure

Limpieza de recursos

Si va a continuar con el siguiente tutorial, puede mantener los recursos creados en esta guía de inicio rápido y volverlos a utilizar con el siguiente tutorial.

En caso contrario, si ya ha terminado con la aplicación de ejemplo de la guía de inicio rápido, puede eliminar los recursos de Azure creados en este tutorial para evitar cargos.

Importante

La eliminación de un grupo de recursos es irreversible y el grupo de recursos y todos los recursos que contiene se eliminarán de forma permanente. Asegúrese de no eliminar por accidente el grupo de recursos o los recursos equivocados. Si ha creado los recursos para hospedar este ejemplo dentro de un grupo de recursos existente que contiene recursos que desea mantener, puede eliminar cada recurso individualmente de sus hojas respectivas, en lugar de eliminar el grupo de recursos.

Inicie sesión en Azure Portal y después seleccione Grupos de recursos.

Escriba el nombre del grupo de recursos en el cuadro de texto Filtrar por nombre... . En las instrucciones de este artículo se usa un grupo de recursos llamado SignalRTestResources. En el grupo de recursos de la lista de resultados, haga clic en ... y, a continuación, en Eliminar grupo de recursos.

Delete

Se le pedirá que confirme la eliminación del grupo de recursos. Escriba el nombre del grupo de recursos para confirmar y seleccione Eliminar.

Transcurridos unos instantes, el grupo de recursos y todos los recursos que contiene se eliminan.

Pasos siguientes

En este tutorial, ha agregado la autenticación con OAuth para proporcionar un enfoque más adecuado para la autenticación con el servicio Azure SignalR. Para más información sobre el uso de Azure SignalR Server, continúe con los ejemplos de la CLI de Azure para SignalR Service.