Проверка подлинности в службе Azure SignalR

В этом руководстве продолжается приложение комнаты чата, представленное в статье "Создание комнаты чата с Служба SignalR". Сначала выполните это краткое руководство, чтобы настроить комнату чата.

В этом руководстве описано, как создать и интегрировать метод проверки подлинности с помощью Microsoft Служба Azure SignalR.

Изначально используемая аутентификация из этого краткого руководства по приложению комнаты чата, является слишком простой для реального мира. Приложение позволяет каждому клиенту утверждать то, кем он является и сервер это просто принимает. Этот подход неэффективн в реальном мире, так как злоумышленники могут использовать поддельные удостоверения для доступа к конфиденциальным данным.

Портал GitHub предоставляет API аутентификацию, основанную на популярном протоколе отраслевого стандарта OAuth. Эти API позволяют сторонним приложениям проходить аутентификацию учетными записями GitHub. В этом руководстве вы можете использовать эти API для реализации проверки подлинности с помощью учетной записи GitHub перед разрешением входа клиента в приложение комнаты чата. После проверки подлинности учетной записи GitHub сведения об учетной записи будут добавлены в виде файла cookie, который будет использоваться веб-клиентом для проверки подлинности.

Дополнительные сведения о API аутентификации OAuth, предоставленной через GitHub, см. в статье Basics of Authentication (Основы аутентификации).

Вы можете использовать любой редактор кода для выполнения шагов в этом кратком руководстве. Однако Visual Studio Code является отличным вариантом, доступным на платформах Windows, MacOS и Linux.

Код для этого руководства доступен для скачивания в репозитории примеров AzureSignalR на GitHub.

OAuth Complete hosted in Azure

В этом руководстве описано следующее:

  • Регистрировать новое приложение OAuth в учетной записи GitHub.
  • Добавлять контролер аутентификации к поддерживаемой аутентификации GitHub
  • Развертывать веб приложение ASP.NET Core в Azure

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начинать работу.

Необходимые компоненты

Для работы с этим руководством необходимо следующее:

Создание приложения OAuth

  1. Откройте веб-браузер, перейдите к https://github.com и войдите в свою учетную запись.

  2. Для учетной записи перейдите к Параметры> ПараметрамDeveloper> Приложение OAuth и выберите "Создать Приложение OAuth" в разделе Приложение OAuth.

  3. Используйте следующие параметры для новой Приложение OAuth, а затем нажмите кнопку "Зарегистрировать приложение".

    Имя параметра Рекомендуемое значение Description
    Имя приложения Чат SignalR Azure Пользователь GitHub должен иметь возможность распознавать и доверять приложению, с которым они выполняют проверку подлинности.
    URL-адрес домашней страницы https://localhost:5001
    Описание приложения Пример использования службы Azure SignalR в комнате чата с помощью аутентификации GitHub Полезное описание приложения, которое помогает пользователям приложения понять контекст используемой проверки подлинности.
    URL-адрес обратного вызова проверки подлинности https://localhost:5001/signin-github Этот параметр является самым важным параметром для приложения OAuth. Он является URL-адресом обратного вызова, который GitHub возвращает пользователю, после успешной аутентификации. В этом руководстве по умолчанию необходимо использовать URL-адрес обратного вызова для пакета AspNet.Security.OAuth.GitHub, /signin-github.
  4. После завершения регистрации нового приложения OAuth добавьте Идентификатор клиента и Секрет клиента в менеджер секретов с помощью следующих команд. Замените Your_GitHub_Client_Id и Your_GitHub_Client_Secret на значения из собственного приложения OAuth.

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

Реализация потока OAuth

Давайте повторно будем использовать приложение чата, созданное в руководстве по созданию комнаты чата с Служба SignalR.

Обновление Program.cs для поддержки проверки подлинности GitHub

  1. Добавьте ссылку на последние пакеты AspNet.Security.OAuth.GitHub и восстановите все пакеты.

    dotnet add package AspNet.Security.OAuth.GitHub
    
  2. Откройте Program.cs и обновите код до следующего фрагмента кода:

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

    В коде AddAuthentication и UseAuthentication используются для добавления поддержки проверки подлинности с помощью приложения OAuth GitHub, а GetUserCompanyInfoAsync вспомогательный метод — это пример кода, показывающий, как загрузить сведения компании из GitHub OAuth и сохранить его в удостоверение пользователя. Вы также можете заметить, что UseHttpsRedirection() используется, так как GitHub OAuth set secure cookie, который проходит только через безопасную https схему. Кроме того, не забудьте обновить локальный Properties/lauchSettings.json , чтобы добавить конечную точку https:

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

Добавление контроллера проверки подлинности

В этом разделе описано, как реализовать Login API, который проверяет подлинность клиентов с помощью приложения OAuth GitHub. После проверки подлинности API добавляет файл cookie в ответ веб-клиента перед перенаправлением клиента обратно в приложение чата. Затем этот файл cookie используется для идентификации клиента.

  1. Добавьте новый файл кода контроллера в каталог GitHubChat\Controllers . Назовите файл AuthController.cs.

  2. Добавьте следующий код для контроллера аутентификации. Обязательно обновите пространство имен, если каталог проекта не был 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. Сохранение изменений.

Обновление класса Hub

По умолчанию веб-клиент подключается к Служба SignalR с помощью маркера доступа, созданного пакетом SDK Azure SignalR автоматически.

В этом разделе описано, как интегрировать реальный рабочий процесс проверки подлинности, добавив Authorize атрибут в класс концентратора и обновив методы концентратора, чтобы прочитать имя пользователя из утверждения прошедшего проверку подлинности пользователя.

  1. Откройте Hub\ChatSampleHub.cs и обновите код до приведенного ниже фрагмента кода. Код добавляет атрибут ChatSampleHub в Authorize класс и использует удостоверение пользователя, прошедшее проверку подлинности, в методах концентратора. Кроме того, OnConnectedAsync добавляется метод, который регистрирует системное сообщение в комнату чата при каждом подключении нового клиента.

    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. Сохранение изменений.

Обновление кода веб-клиента

  1. Откройте файл wwwroot\index.html и замените код, который предлагает ввести имя пользователя на код, который использует файл cookie, возвращенный контролером аутентификации.

    Обновите код внутри функции getUserName в index.html следующим образом, чтобы использовать файлы 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. Обновление onConnected функции для удаления username параметра при вызове метода broadcastMessage концентратора и 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. В нижней части index.html обновите обработчик ошибок, connection.start() как показано ниже, чтобы пользователю было предложено войти.

    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. Сохранение изменений.

Локальное создание и запуск приложения

  1. Сохраните изменения для всех файлов.

  2. Выполните следующую команду, чтобы запустить веб-приложение локально:

    dotnet run
    

    Приложение размещается локально на порту 5000 по умолчанию:

    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. Запустите окно браузера и перейдите по адресу https://localhost:5001. Выберите здесь ссылку в верхней части, чтобы войти в систему с помощью GitHub.

    OAuth Complete hosted in Azure

    Вам будет предложено авторизовать доступ приложения чата к учетной записи GitHub. Нажмите кнопку Авторизовать.

    Authorize OAuth App

    Вы перенаправляетесь обратно в приложение чата и вошли в систему с именем учетной записи GitHub. Веб-приложение определило имя учетной записи, выполнив проверку подлинности с помощью новой проверки подлинности, которую вы добавили.

    Account identified

    При использовании приложения чата теперь выполняется проверка подлинности с помощью GitHub и хранятся сведения проверки подлинности в виде файлов cookie, на следующем шаге предполагается развертывание в Azure. Этот подход позволяет другим пользователям проходить проверку подлинности с помощью соответствующих учетных записей и обмениваться данными с различных рабочих станций.

Развертывание приложения в Azure

Подготовьте среду к работе с Azure CLI:

  • Используйте среду Bash в Azure Cloud Shell. Дополнительные сведения см . в кратком руководстве по Bash в Azure Cloud Shell.

  • Если вы предпочитаете выполнять справочные команды CLI локально, установите Azure CLI. Если вы работаете в Windows или macOS, Azure CLI можно запустить в контейнере Docker. Дополнительные сведения см. в статье Как запустить Azure CLI в контейнере Docker.

    • Если вы используете локальную установку, выполните вход в Azure CLI с помощью команды az login. Чтобы выполнить аутентификацию, следуйте инструкциям в окне терминала. Сведения о других возможностях, доступных при входе, см. в статье Вход с помощью Azure CLI.

    • Установите расширение Azure CLI при первом использовании, когда появится соответствующий запрос. Дополнительные сведения о расширениях см. в статье Использование расширений с Azure CLI.

    • Выполните команду az version, чтобы узнать установленную версию и зависимые библиотеки. Чтобы обновиться до последней версии, выполните команду az upgrade.

В этом разделе вы используете Azure CLI для создания нового веб-приложения в службе приложение Azure для размещения приложения ASP.NET в Azure. Веб-приложение настроено для использования локального развертывания Git. Веб-приложение также настроено с помощью строка подключения SignalR, секретов приложений OAuth GitHub и пользователя развертывания.

При создании следующего ресурса, обязательно используйте ту же группу ресурсов, в которой находится ресурс службы SignalR. Этот подход упрощает очистку позже, когда вы хотите удалить все ресурсы. В приведенном примере предполагается использование имени группы SignalRTestResources, рекомендованного в предыдущих руководствах.

Создание веб-приложения и плана

Скопируйте текст для команд, приведенных ниже, и обновите параметры. Вставьте обновленный сценарий в Azure Cloud Shell и нажмите клавишу ВВОД, чтобы создать новый план службы приложений и веб-приложений.

#========================================================================
#=== 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
Параметр Описание
ResourceGroupName Это имя группы ресурсов было предложено в предыдущих руководствах. Рекомендуется сохранить все ресурсы учебника сгруппированы вместе. Используйте ту же группу ресурсов, что и в предыдущих руководствах.
WebAppPlan Введите новое, уникальное имя плана служб приложений.
WebAppName Этот параметр является именем нового веб-приложения и частью URL-адреса. Сделайте его уникальным. Например, signalrtestwebapp22665120.

Добавление параметров приложения к веб-приложению

В этом разделе описано, как добавить параметры приложения для следующих компонентов:

  • Ресурсная строка подключения службы SignalR
  • Идентификатор клиента приложения OAuth GitHub
  • Секрет клиента приложения OAuth GitHub

Скопируйте текст для команд, приведенных ниже, и обновите параметры. Вставьте обновленный сценарий в Azure Cloud Shell и нажмите клавишу ВВОД, чтобы добавить параметры приложения.

#========================================================================
#=== 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"
Параметр Описание
GitHubClientId Назначьте эту переменную идентификатору секретного клиента для Приложение OAuth GitHub.
GitHubClientSecret Назначьте этой переменной секретный пароль для приложения OAuth GitHub.
ResourceGroupName Обновите эту переменную, чтобы у нее было то же имя, что и у группы ресурсов, которую вы использовали в предыдущем разделе.
SignalRServiceResource Обновите эту переменную, чтобы у нее было то же имя, что и у ресурса SignalR, который вы создали в кратком руководстве. Например, signalrtestsvc48778624.
WebAppName Обновите эту переменную, чтобы у нее было то же имя, что и у нового веб-приложения, которое вы создали в предыдущем разделе.

Настройка веб-приложения для локального развертывания Git

Вставьте следующий сценарий в Azure Cloud Shell. Этот скрипт создает новое имя пользователя развертывания и пароль, которые вы используете при развертывании кода в веб-приложении с помощью Git. Сценарий также настраивает веб-приложение для развертывания с помощью локального репозитория Git и возвращает URL-адрес развертывания 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
Параметр Описание
DeploymentUserName Выберите новое имя пользователя развертывания.
DeploymentUserPassword Выберите пароль для нового пользователя развертывания.
ResourceGroupName Используйте имя группы ресурсов, которое соответствует имени группы ресурсов, использованному в предыдущем разделе.
WebAppName Этот параметр — это имя созданного ранее веб-приложения.

Запишите URL-адрес развертывания Git, возвращенный из этой команды. Этот URL-адрес используется позже.

Разверните код в веб-приложении Azure

Выполните следующую команду в Git Shell, чтобы развернуть код.

  1. Перейдите в корневой каталог проекта. Если у вас нет проекта, инициализированного с помощью репозитория Git, выполните следующую команду:

    git init
    
  2. Добавьте remote для URL-адреса развертывания Git, записанного ранее.

    git remote add Azure <your git deployment url>
    
  3. Сгруппируйте все файлы в инициализированном репозитории и добавьте фиксацию.

    git add -A
    git commit -m "init commit"
    
  4. Разверните код в веб-приложении Azure.

    git push Azure main
    

    Вам будет предложено выполнить проверку подлинности, чтобы развернуть код в Azure. Введите имя и пароль пользователя развертывания, созданного выше.

Обновление приложения OAuth GitHub

И наконец, для завершения процесса выполните обновление URL-адреса домашней страницы и URL-адреса обратного вызова авторизации приложения OAuth GitHub, чтобы указать новое размещенное приложение.

  1. В браузере откройте https://github.com и в учетной записи перейдите к элементам Параметры>Параметры разработчика>Oauth Apps (Приложения OAuth).

  2. Выберите приложение проверки подлинности и обновите URL-адрес домашней страницы и URL-адрес обратного вызова авторизации, как показано ниже:

    Параметр Пример
    URL-адрес домашней страницы https://signalrtestwebapp22665120.azurewebsites.net
    URL-адрес обратного вызова проверки подлинности https://signalrtestwebapp22665120.azurewebsites.net/signin-github
  3. Перейдите к URL-адресу веб-приложения и протестируйте приложение.

    OAuth Complete hosted in Azure

Очистка ресурсов

Если вы продолжите работу со следующим руководством, вы можете сохранить ресурсы, созданные в этом кратком руководстве, и повторно использовать их с помощью следующего руководства.

В противном случае, если вы закончили работу с примером приложения из краткого руководства, вы можете удалить ресурсы Azure, созданные в текущем руководстве, чтобы избежать ненужных расходов.

Внимание

Удаление группы ресурсов — необратимая операция, и все соответствующие ресурсы удаляются окончательно. Будьте внимательны, чтобы случайно не удалить не ту группу ресурсов или не те ресурсы. Если ресурсы для размещения этого примера созданы в имеющейся группе ресурсов, содержащей ресурсы, которые следует сохранить, можно удалить каждый ресурс отдельно в соответствующих колонках вместо удаления группы ресурсов.

Войдите в портал Azure и выберитеГруппы ресурсов.

Введите имя группы ресурсов в текстовое поле Фильтровать по имени.... В инструкциях в этой статье использовалась группа ресурсов с именем SignalRTestResources. В своей группе ресурсов в списке результатов щелкните ..., а затем Удалить группу ресурсов.

Delete

Подтвердите операцию удаления группы ресурсов. Введите имя группы ресурсов, которую необходимо удалить, и нажмите Удалить.

Через некоторое время группа ресурсов и все ее ресурсы будут удалены.

Следующие шаги

В этом руководстве вы научились добавлять аутентификацию с помощью OAuth, чтобы улучшить подход к аутентификации службы Azure SignalR. Чтобы узнать больше об использовании сервера Azure SignalR, перейдите к примерам Azure CLI для службы SignalR.