Posted on 5. November 2023

What’s new with identity in .NET 8

Read this article in your language IT | EN | DE | ES

Що нового в ідентифікації в .NET 8


У квітні 2023 року я писав про зобов’язання команди ASP.NET Core покращити автентифікацію, авторизацію та керування ідентифікацією в .NET 8. Представлений нами план включав три основні результати:


– Нові API для спрощення входу та керування ідентифікацією для клієнтських програм, таких як Single Page Apps (SPA) і Blazor WebAssembly.

– Увімкнення автентифікації та авторизації на основі маркерів у ASP.NET Core Identity для клієнтів, які не можуть використовувати файли cookie.

– Покращення в документації.


Усі три результати з’являтья разом із .NET 8. Крім того, ми змогли додати новий інтерфейс ідентифікації для веб-програм Blazor, який працює з обома новими режимами візуалізації, сервером і WebAssembly.


Давайте розглянемо кілька сценаріїв, уможливлених новими змінами в .NET 8. У цій публікації блогу ми розглянемо:

– Захист простого серверного веб-API

– Використання нового інтерфейсу ідентифікатора Blazor

– Додавання зовнішнього логіна, наприклад Google або Facebook

– Захист програм Blazor WebAssembly за допомогою вбудованих функцій і компонентів

– Використання токенів для клієнтів, які не можуть використовувати файли cookie


Давайте розглянемо найпростіший сценарій використання нових функцій ідентифікації.

Базовий сервер веб-API

Простий спосіб використання нової авторизації — увімкнути її в базовій програмі Web API. Цю ж програму також можна використовувати як серверну частину для Blazor WebAssembly, Angular, React та інших односторінкових веб-програм (SPA). Якщо ви починаєте з проекту ASP.NET Core Web API у .NET 8, який включає OpenAPI, ви можете додати автентифікацію за кілька кроків.


Ідентифікація є "опціональною", тож залишилося додати ще кілька пакунків:

Microsoft.AspNetCore.Identity.EntityFrameworkCoreпакет, який забезпечує інтеграцію EF Core

– Пакет для бази даних, яку ви бажаєте використати, наприклад Microsoft.EntityFrameworkCore.SqlServer(у цьому прикладі ми використаємо базу даних у пам’яті)

 

Ви можете додати ці пакети за допомогою менеджера пакетів NuGet або командного рядка. Наприклад, щоб додати пакети за допомогою командного рядка, перейдіть до теки проєкту та виконайте такі команди dotnet:

 

Ідентифікація дозволяє налаштувати як інформацію про користувача, так і базу даних користувача, якщо у вас є вимоги, що виходять за межі того, що надається в рамках .NET Core. Для нашого базового прикладу ми просто використаємо інформацію про користувача та базу даних за замовчуванням. Для цього ми додамо новий клас до проєкту під назвою, MyUser, який успадковує від IdentityUser:

 

Додайте новий клас під назвою AppDbContext, який успадковує від IdentityDbContext<MyUser>:

Надання спеціального конструктора дає змогу налаштувати базу даних для різних середовищ.


Щоб налаштувати ідентифікатор для програми, відкрийте файл Program.cs. Налаштуйте ідентифікатор на використання автентифікації на основі файлів cookie та ввімкніть перевірку авторизації, додавши наступний код після виклику WebApplication.CreateBuilder(args):

 

Налаштуйте базу даних EF Core. Тут ми використаємо базу даних у пам’яті та назвемо її «AppDb». Вона використовується тут для демонстрації, тому можна легко перезапустити програму та перевірити потік, щоб зареєструватися та ввійти (кожний запуск розпочинатиметься з новою базою даних). Перехід на SQLite збереже користувачів між сеансами, але вимагає належного створення бази даних за допомогою міграцій, як показано в цьому посібнику з початку роботи з EF Core. Ви можете використовувати інші реляційні постачальники, такі як SQL Server, для свого робочого коду.

 

Налаштуйте ідентифікацію для використання бази даних EF Core та відкрийте кінцеві точки ідентифікації:

 

Позначте маршрути для кінцевих точок ідентифікації. Цей код слід розмістити після виклику builder.Build():

Тепер програма готова до автентифікації та авторизації! Щоб захистити ендпоінт, використовуйте метод розширення .RequireAuthorization(), де ви визначаєте маршрут авторизації. Якщо ви використовуєте рішення на основі контролера, ви можете додати атрибут [Authorize]до контролера або дії.

Щоб протестувати програму, запустіть її та перейдіть до інтерфейсу користувача Swagger. Розгорніть захищений ендпоінт, оберіть «випробувати» та виберіть «Виконати». Ендпоінт отримує повідомлення 404 - not found, що, мабуть, є більш безпечним, ніж повідомлення, 401 - not authorized оскільки воно не показує, що кінцева точка існує.

Swagger UI з 404

Тепер розгорніть /register і заповніть свої облікові дані. Якщо ви введете недійсну адресу електронної пошти або неправильний пароль, результат міститиме помилки перевірки.

Swagger UI з помилками перевірки

Помилки в цьому прикладі повертаються у форматі ProblemDetails , щоб ваш клієнт міг легко проаналізувати їх і за потреби відобразити помилки перевірки. Я покажу приклад цього в автономній програмі Blazor WebAssembly.


Успішна реєстрація призводить до відповіді 200 - OK. Тепер ви можете розгорнути /login та ввести ті самі облікові дані. Зауважте, що для цього прикладу є додаткові параметри, які можна видалити. Обов’язково встановіть useCookies true. Успішний вхід призводить до відповіді 200 - OK з файлом cookie в заголовку відповіді.

Тепер ви можете повторно запустити захищений ендпоінт, і він має повернути дійсний результат. Це тому, що автентифікація на основі файлів cookie надійно вбудована у ваш браузер і «просто працює». Ви щойно захистили свою першу кінцеву точку за допомогою ідентифікації!


Деякі веб-клієнти можуть не включати файли cookie в заголовок за умовчанням. Якщо ви використовуєте інструмент для тестування API, вам може знадобитися ввімкнути файли cookie в налаштуваннях. JavaScript API fetch не включає файли cookie за замовчуванням. Ви можете ввімкнути їх, встановивши значення credentials як  include в параметрах. Подібним чином, HttpClient запущений в програмі Blazor WebAssembly потребує HttpRequestMessage для включення облікових даних, наприклад:

Далі перейдемо до веб-програми Blazor.


Інтерфейс ідентифікації Blazor


Велика мета нашої команди, якої ми змогли досягти, полягала в тому, щоб реалізувати користувальницький інтерфейс ідентифікації, який включає параметри реєстрації, входу та налаштування багатофакторної автентифікації в Blazor. Інтерфейс користувача вбудовано в шаблон, коли ви вибираєте параметр «Індивідуальні облікові записи» для автентифікації. На відміну від попередньої версії інтерфейсу ідентифікації, яка була прихована, якщо ви не хотіли її налаштувати, шаблон генерує весь вихідний код, щоб ви могли змінювати його за потреби. Нова версія створена на основі компонентів Razor і працює як із серверними програмами, так і з програмами WebAssembly Blazor.

Сторінка входу Blazor

Нова веб-модель Blazor дозволяє вам налаштувати, чи інтерфейс користувача відображатиметься на стороні сервера чи клієнта, що працює в WebAssembly. Якщо ви обираєте режим WebAssembly, сервер усе одно оброблятиме всі запити на автентифікацію та авторизацію. Він також створить код для спеціальної реалізації AuthenticationStateProvider, яка відстежує стан автентифікації. Постачальник використовує  клас PersistentComponentState для попереднього відтворення стану автентифікації та збереження його на сторінці. PersistentAuthenticationStateProvider у клієнтській програмі WebAssembly використовує компонент для синхронізації стану автентифікації між сервером і браузером. Постачальник стану також може бути названий PersistingRevalidatingAuthenticationStateProvider під час роботи з автоматичною інтерактивністю або IdentityRevalidatingAuthenticationStateProvider для інтерактивності сервера.

Незважаючи на те, що приклади в цій публікації блогу зосереджені на простому сценарії входу з іменем користувача та паролем, ASP.NET Identity підтримує взаємодію на основі електронної пошти, як-от підтвердження облікового запису та відновлення пароля. Також можна налаштувати багатофакторну автентифікацію. Компоненти для всіх цих функцій включені в інтерфейс користувача.

Додайте зовнішній логін

Нам часто задають питання, як інтегрувати зовнішні входи через соціальні веб-сайти з ASP.NET Core Identity. Починаючи з проєкту веб-програми Blazor за замовчуванням, ви можете додати зовнішній логін за кілька кроків.


По-перше, вам потрібно буде зареєструвати свою програму на веб-сайті соціальної мережі. Наприклад, щоб додати логін Twitter, перейдіть на портал розробників Twitter і створіть нову програму. Вам потрібно буде надати певну базову інформацію, щоб отримати облікові дані клієнта. Після створення програми перейдіть до налаштувань програми та натисніть «редагувати» під час автентифікації. Укажіть «нативний додаток» для типу додатка, щоб потік працював правильно, і ввімкніть «запитувати електронні листи від користувачів». Вам потрібно буде надати URL-адресу зворотного виклику. У цьому прикладі ми використаємо URL-адресу зворотного виклику https://localhost:5001/signin-twitter за умовчанням для шаблону веб-програми Blazor. Ви можете просто замінити цю адресу, щоб відповідати URL-адресі вашої програми (тобто замінити 5001 своїм власним портом). Також зверніть увагу на ключ і секрет API.

Далі додайте до своєї програми відповідний пакет автентифікації. Існує список постачальників соціальної автентифікації OAuth 2.0 для ASP.NET Core, який підтримується спільнотою, із багатьма варіантами на вибір. Ви можете комбінувати кілька зовнішніх входів за потреби. Для Twitter я додам пакет AspNet.Security.OAuth.Twitter.

 

З командного рядка в кореневому каталозі проєкту сервера виконайте цю команду, щоб зберегти ключ API (ідентифікатор клієнта) і секрет.

 

Нарешті, налаштуйте вхід в Program.cs, замінивши цей код:

з цим кодом:

Файли cookie є кращим і найбезпечнішим підходом для впровадження ASP.NET Core Identity. Токени підтримуються за потреби та потребують налаштування IdentityConstants.BearerScheme. Токени є пропрієтарними, а потік на основі токенів призначений для простих сценаріїв, тому він не реалізує стандарти OAuth 2.0 або OIDC.

Що далі? Вірите чи ні, ви закінчили. Цього разу, коли ви запускаєте програму, сторінка входу автоматично визначить зовнішній логін і надасть кнопку для його використання.

Сторінка входу Blazor у Twitter

Коли ви ввійдете в систему та авторизуєтесь у програмі, вас буде перенаправлено назад і відбудеться автентифікація.

Захист програм Blazor WebAssembly

Основною мотивацією для додавання нових ідентифікаційних API було  бажання полегшити розробникам захист їхніх браузерних програм, включаючи Single Page Apps (SPA) і Blazor WebAssembly. Немає значення, чи використовуєте ви вбудований постачальник ідентифікації, спеціальну систему входу чи хмарну службу, як-от Microsoft Entra, кінцевим результатом буде ідентифікація, яка або автентифікована за допомогою претензій і ролей, або не автентифікована. У Blazor ви можете захистити компонент Razor, додавши атрибут [Authorize] до компонента або до сторінки, на якій розміщено компонент. Ви також можете захистити маршрут, додавши .RequireAuthorization()метод розширення до визначення маршруту.

Повний вихідний код для цього прикладу доступний у сховищі зразків Blazor.

Тег AuthorizeView забезпечує простий спосіб обробки вмісту, до якого користувач має доступ. Доступ до стану автентифікації можна отримати через властивість context. Зверніть увагу на наступне:

Привітання буде показано всім. У випадку Blazor WebAssembly, коли клієнту може знадобитися асинхронна автентифікація через виклики API, вміст Authorizing буде показано під час запиту та вирішення стану автентифікації. Потім, залежно від того, пройшли ви автентифікацію чи ні, ви побачите своє ім’я або повідомлення про те, що ви не автентифіковані. Як саме клієнт дізнається, чи ви автентифіковані? Ось де з’являється AuthenticationStateProvider.

Сторінка App.razor загорнута в провайдера CascadingAuthenticationState. Цей провайдер відповідає за відстеження стану автентифікації та надання до нього доступу для решти програми. AuthenticationStateProvider впроваджується в провайдера та використовується для відстеження стану. AuthenticationStateProvider також вводиться в компонент AuthorizeView. Коли стан автентифікації змінюється, постачальник сповіщає компонент AuthorizeView, і вміст оновлюється відповідно.

 

По-перше, ми хочемо переконатися, що виклики API відповідно зберігають облікові дані. Для цього я створив обробник під назвою CookieHandler.

 

В Program.cs додав обробник до HttpClient і використав фабрику клієнтів, щоб налаштувати спеціальний клієнт для автентифікації.

 

AuthUrl - це URL-адреса сервера ASP.NET Core, на якому доступні API ідентифікації. Далі я створив CookieAuthenticationStateProvider, який успадковує AuthenticationStateProvider і перевизначає метод GetAuthenticationStateAsync. Основна логіка виглядає так:

Ендпоінт інформації про користувача захищений, тому, якщо користувач не автентифікований, запит не вдасться виконати, і метод поверне неавтентифікований стан. В іншому випадку він створює відповідну ідентифікацію та заявляє та повертає автентифікований стан.


Як програма дізнається, коли стан змінився? Ось як виглядає вхід із Blazor WebAssembly за допомогою ідентифікаційного API:

Після успішного входу викликається метод NotifyAuthenticationStateChanged базового класу AuthenticationStateProvider, щоб повідомити провайдера про зміну стану. Йому передається результат запиту нового стану автентифікації, щоб він міг перевірити наявність файлу cookie. Після цього провайдер оновить компонент AuthorizeView, і користувач побачить автентифікований вміст.

Токени

У рідкісних випадках, коли ваш клієнт не підтримує файли cookie, API входу надає параметр для запиту токенів. Видається спеціальний токен (який є власністю платформи ідентифікації ASP.NET Core), який можна використовувати для автентифікації наступних запитів. Токен передається в хедері  Authorization як маркер токена. Також надається токен оновлення. Це дозволяє вашій програмі запитувати новий токен, коли закінчується термін дії старого, не змушуючи користувача знову входити в систему. Токени не є стандартними веб-токенами JSON (JWT). Це рішення було прийнято навмисно, оскільки вбудована ідентифікація призначена в основному для простих сценаріїв. Параметр маркера не призначений для повнофункціонального постачальника послуг ідентифікації або сервера маркерів, а замість цього є альтернативою параметру cookie для клієнтів, які не можуть використовувати файли cookie.

Не впевнені, чи потрібен вам сервер токенів чи ні? Прочитайте документ, який допоможе вам вибрати правильне рішення ідентифікації ASP.NET Core. Шукаєте більш просунуте рішення ідентифікації? Прочитайте наш список рішень для керування ідентифікацією для ASP.NET Core.

Документи та зразки

Третій результат – документація та зразки. Ми вже представили нову документацію та будемо додавати нові статті та зразки, коли наблизимось до релізу .NET 8. Слідкуйте за релізом № 29452 – документація та зразки для ідентифікації в .NET 8, щоб відстежувати прогрес. Будь ласка, використовуйте випуск, щоб надіслати додаткову документацію або зразки, які ви шукаєте. Ви також можете посилатися на конкретні проблеми для різних документів і залишати там свої відгуки.

Висновок

Нові функції ідентифікації в .NET 8 роблять захист ваших програм простішим, ніж будь-коли. Якщо ваші вимоги прості, тепер ви можете додати автентифікацію та авторизацію до своєї програми за допомогою кількох рядків коду. Нові API дають змогу захистити кінцеві точки веб-API за допомогою автентифікації та авторизації на основі файлів cookie. Існує також опція на основі маркерів для клієнтів, які не можуть використовувати файли cookie.


Дізнайтеся більше про нові функції ідентифікації в документації ASP.NET Core .


Source




Comments are closed