Почему я Вас нашел только сейчас? Как так мимо меня пролетает все самое полезное и прекрасное? Спасибо огромное за Ваши старания, я уверен, что Ваши видео помогли уже многим тысячам человек. Не ожидал, что на русском языке найдется настолько доступное, настолько структурированное и грамотное объяснение всех этих вещей
До этого видео столько времени потратил, чтобы во всем этом разобраться и так ничего не понял, в этой документации от майкрософт ничего нормально не изложено, а тут все понятно и по полочкам. Мне нравится, что вы не вырезаете свои ошибки или ляпы, показываете все как есть и с какими проблемами можно столкнуться. Узнал много полезного, огромное спасибо!
если у кого-то начали падать ошибки, то вы используете свежую версию IS4. Вам нужно поменять регистрацию скопов и ресурсов, мне помогло. GetApiResources() => new List { new ApiResource("OrdersApi") {Scopes = new List() { "OrdersApi" }}, }; GetApiScopes() { return new[] { new ApiScope("OrdersApi") }; } в стартапе добавить .AddInMemoryApiScopes(ConfigIS4.GetApiScopes()) Спасибо большое автору канала!
@@SergeiCalabonga var tokenResponse = await authClient.RequestClientCredentialsTokenAsync( new ClientCredentialsTokenRequest { Address = discoveryDocument.TokenEndpoint, ClientId = "client_id", ClientSecret = "client_secret", Scope = "OrdersAPI" }); почему на последнем этапе может возникать 400 ошибка?
@@sakhirikтут много чего может быть * неверный cleintId * неверный client_secret * не попадает в scope проще искать в старых исходниках IdentityServer4 или лучще перейти на бесплатный OpenIddict
- Service-to-service - 5:08 - создание проектов - 5:50 - создание проекта под шаблон - 8:32 - создание шаблона - 11:19 - изменение портов - 11:41 - версия 1 - вызов из User.Api Orders.Api без identity - 22:04 - версия 2 - Добавляем identityserver - 36:37 well-known/openid-configuration - 38:37 пишем запрос к identityserver
в итоге все заработало ,правда пришлось полистать офф документацию так как скопы по другому теперь объявляются ну и еще по мелочи,но лучше так ,чем готовый код с репозитория форкать. спасибо за уроки.
А когда прилетел запрос на Order.Api - Order.Api не лезет на identity server? Каким образом токен на Order.Api прочитается? Имеется ввиду как ордер.апи проверит валидность токена без секретного ключа?
@@SergeiCalabonga я кажется понял, IdentityServer подписывает токены при помощи RSA SHA 256, а для этого требуется пара приватный-публичный ключ. Вот для чего и нужен сертификат, тестовый генерится как раз в AddDeveloperSigningCredential и добавляет тестовые ключи для подписи JWT-токенов. RSA SHA 256 - это ассиметричный алгоритм и для валидации токена нужен только публичный ключ, который и хранится по пути .well-known/openid-configuration, а точнее там есть ссылка: .well-known/openid-configuration/jwks, там и лежит публичный ключ. Т.е. секретная часть ключа в ассиметричном алгоритме нужна только для подписи токена при генерации токена.
осталось проверить как часто Order.Api "лезет" на .well-known/openid-configuration. По логике надо только при старте приложения прочитать необходимое. Если при каждом вызове сам Order.Api будет ходить на .well-known/openid-configuration то не слабый оверхед получим.
Повторял код вслед за видео, но на 36:39 в scopes_supported почему-то не появился OrdersAPI, в Configuration и StartUp всё необходимое добавлял, в чём может быть причина?
@@SergeiCalabonga благодарю за ответ. Для удобства я создал репозиторий, в нём коммитил по ходу видео и дойдя до указанного времени указанная выше настройка не появилась, для воспроизведения результата можно открыть последний коммит в ветке master github.com/Artyma93/Calabonga. Я также нашёл примерное решение и добавил это решение в отдельную ветку AddInMemoryApiScopes. Однако странно, что в видео работает и без этого дополнительного метода.
@@SergeiCalabonga благодарю за ответ. Почему-то ютуб не пропустил мой предыдущий ответ Вам, в котором я отправлял ссылку на свой репозиторий на GitHub, но не страшно. Оказалось проблема в том, что в Вашем видео и проекте используется IdentityServer4 версии 3.1.3, а самая актуальная версия 4.0.3, которая и устанавливается, если делать всё самостоятельно с нуля. И как оказалось для этой версии необходимо добавить в класс Startup метод AddInMemoryApiScopes и в класс Configuration метод GetApiScopes. Тогда в scopes_supported появляется OrdersAPI. Но когда посылается запрос приходит всё равно ответ Unauthorized, т.к. теперь ему не хватает Audience в Access_token и получается следующая ошибка Bearer error="invalid_token", error_description="The audience is invalid". Решение которой на stackoverflow вроде как есть, но не совсем понятно, там предлагается в клиенте в классе Startup добавить метод app.UseOpenIdConnectAuthentication, но всё же остаются вопросы. В связи с чем прошу осветить данную тему и обновить версию IdentityServer4 в одном из будущих видео. С уважением Артём.
@@SergeiCalabonga Благодарю за такую отзывчивость. Пользуясь случаем, можно ли Вас попросить осветить ещё такие вопросы в дальнейших уроках: 1. Аутентификация с помощью провайдера от Microsoft, на сколько я понимаю там можно разными вариантами это делать, например в документации у них рассказывается про Azure Active Directory, Azure Active Directory B2C и Azure Active Directory B2B. 2. Расскажите пожалуйста о том, как правильно делать аутентификацию с помощью стороннего провайдера (например Azure Active Directory или с помощью любого другого), если используется SPA приложение, но не на базе пустого Asp Core приложения, а как отдельное (например часто, когда делают SPA на React используют шаблон create-react-app, но это актуально и для Angular с Vue, на сколько я понимаю), с использованием Flow Code GrantType. Понятен общий принцип для SPA, когда используется Implicit Flow, пользователь указывает логин и пароль, а после на клиент, т.е. в случае SPA, access_token прилетает в браузер пользователя и после с этим токеном он идёт в нужный API (например OrdersAPI). Но при этом говорят, что использовать Implicit Flow менее безопасно, поэтому рекомендуется, чтобы использовался Code Flow и чтобы code (с помощью которого в последствии получается access_token) прилетал не в сам SPA, а в бекэнд часть клиента. И вот тут на сколько я понимаю, в случае MVC всё просто, т.к. есть View, которые доступны в браузере, есть Controlles, которые находятся на бекэнде. Но в случае с отдельным SPA, получается, что надо добавить ещё один проект на Asp Core, который будет обеспечивать бекэнд часть клиента? И вот тут самое не понятное, получается общая последовательность такая: а) Есть клиент, он состоит из фронтэнд (отдельное SPA приложение ClientSPA) и бекэнд (Asp core проект ClientBackend), есть отдельный сервис авторизации (сторонний провайдер), есть отдельный проект (OrdersAPI). б) ClientSPA делает запрос через ClientBackend на OrdersAPI, тот из-за отсутствия access_token перенаправляет его к стороннему провайдеру. в) Сторонний провайдер возвращает code в ClientBackend. Вот очень не понятно, ClientBackend в свою очередь преобразует code в access_token или снова отправляет code стороннему провайдеру, чтобы тот в ответ прислал access_token? И уже после ClientBackend access_token отправляет в OrdersAPI? И тогда после получения access_token вся цепочка взаимодействия такая: при каждом запросе пользователем информации ClientSPA идёт в ClientBackend (т.к. мы же спрятали и code и access_token в нём, чтобы его не украли) за тем ClientBackend обращается в OrdersAPI и уже OrdersAPI (после проверки access_token) возвращает ответ в ClientSPA, так? 3) Ещё интересно послушать про протокол SAML и в чём его отличия от OIDC. Извиняюсь, что столько много вопросов, но задать их больше некому. С уважением Артём.
Версия nuget пакетов наверняка изменилась. А это значит, что настройки работы сервиса авторизации могут быть недонастроены. Проверяйте работу сервисов по отдельности. Например, через postman
public static IEnumerable GetApiScopes() => new List { new ApiScope("OrdersAPI") }; добавь это и в стартапе добавь ,изменились параметры. Вообще в идеале полистай офф документацию
Сколько видео смотрю. Везде IdentityServer работает со своими таблицами и объектами, а можно так работать,чтобы объекты IdentityServer4 oбъекты были только прослойкой между нашей БД и IdetityServer4
@@SergeiCalabonga : да. К примеру есть такой класс как IdentityUser c которым работает IdentityServer. Мы берем данные из нашей БД, мри помощи мапинга преопразуем в объект IdentityUser и прередаем в IdentityServer. Просто я не совсем понимаю, для чего нам создавать эти таблицы в IdetityDataBase ,когда у меня в базе данных есть таблица прав,таблица пользователей и таблица людей, за которыми эти пользователи закрепленны
@@ziegimondvishneuski3317 получается, что так. Потому что один - это авторизация и аутентификации, а другой - делегирование этих самых авторизации и аутентификации
Почему я Вас нашел только сейчас? Как так мимо меня пролетает все самое полезное и прекрасное?
Спасибо огромное за Ваши старания, я уверен, что Ваши видео помогли уже многим тысячам человек. Не ожидал, что на русском языке найдется настолько доступное, настолько структурированное и грамотное объяснение всех этих вещей
Спасибо за добрый комментарий. Чертовски приятно!
До этого видео столько времени потратил, чтобы во всем этом разобраться и так ничего не понял, в этой документации от майкрософт ничего нормально не изложено, а тут все понятно и по полочкам. Мне нравится, что вы не вырезаете свои ошибки или ляпы, показываете все как есть и с какими проблемами можно столкнуться. Узнал много полезного, огромное спасибо!
Рад, что пригодилась информация
Спасибо за труды! Очень доходчиво!
Спасибо, я именно этого и добивался, чтобы было понятно. :)
если у кого-то начали падать ошибки, то вы используете свежую версию IS4. Вам нужно поменять регистрацию скопов и ресурсов, мне помогло.
GetApiResources() =>
new List
{
new ApiResource("OrdersApi") {Scopes = new List() { "OrdersApi" }},
};
GetApiScopes()
{
return new[]
{
new ApiScope("OrdersApi")
};
}
в стартапе добавить
.AddInMemoryApiScopes(ConfigIS4.GetApiScopes())
Спасибо большое автору канала!
Спасибо за то, что поделились решением!
@@SergeiCalabonga var tokenResponse = await authClient.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = discoveryDocument.TokenEndpoint,
ClientId = "client_id",
ClientSecret = "client_secret",
Scope = "OrdersAPI"
}); почему на последнем этапе может возникать 400 ошибка?
@@sakhirikтут много чего может быть
* неверный cleintId
* неверный client_secret
* не попадает в scope
проще искать в старых исходниках IdentityServer4 или лучще перейти на бесплатный OpenIddict
- Service-to-service
- 5:08 - создание проектов
- 5:50 - создание проекта под шаблон
- 8:32 - создание шаблона
- 11:19 - изменение портов
- 11:41 - версия 1
- вызов из User.Api Orders.Api без identity
- 22:04 - версия 2
- Добавляем identityserver
- 36:37 well-known/openid-configuration
- 38:37 пишем запрос к identityserver
Спасибо
Офигеть! Ну ты мой герой :)
Спасибо!
Большое спасибо!
Лучше так boosty.to/calabonga/donate 🤭
в итоге все заработало ,правда пришлось полистать офф документацию так как скопы по другому теперь объявляются ну и еще по мелочи,но лучше так ,чем готовый код с репозитория форкать. спасибо за уроки.
Рад, что всё получилось
Не подскажете, где можно найти информацию по этому или какие-то материалы по этому
@@exsey4010 всё что нашёл, рассказал на видео. Больше не знаю где взять. На официальном сайте IdentityServer ещё можно.
А когда прилетел запрос на Order.Api - Order.Api не лезет на identity server? Каким образом токен на Order.Api прочитается? Имеется ввиду как ордер.апи проверит валидность токена без секретного ключа?
Хороший вопрос. Особенности работы OAuth2.0 описаны в спецификации. Одно скажу, "лезет", но не каждому раз.
@@SergeiCalabonga я кажется понял, IdentityServer подписывает токены при помощи RSA SHA 256, а для этого требуется пара приватный-публичный ключ. Вот для чего и нужен сертификат, тестовый генерится как раз в AddDeveloperSigningCredential и добавляет тестовые ключи для подписи JWT-токенов. RSA SHA 256 - это ассиметричный алгоритм и для валидации токена нужен только публичный ключ, который и хранится по пути .well-known/openid-configuration, а точнее там есть ссылка: .well-known/openid-configuration/jwks, там и лежит публичный ключ. Т.е. секретная часть ключа в ассиметричном алгоритме нужна только для подписи токена при генерации токена.
осталось проверить как часто Order.Api "лезет" на .well-known/openid-configuration. По логике надо только при старте приложения прочитать необходимое. Если при каждом вызове сам Order.Api будет ходить на .well-known/openid-configuration то не слабый оверхед получим.
Хорошие домыслы! Остается только подтвердить их! 😄
Супер!
Как вы называете красную точечку для дебага? )) Не могу разобрать )))
Бряка? Breakpoint?
Сергей, насколько этот IdentityServer актуален? Что сейчас испоьзуете в продакшене вместо платной последней версии?
Рекомендую посмотреть в сторону OpenIddict
Повторял код вслед за видео, но на 36:39 в scopes_supported почему-то не появился OrdersAPI, в Configuration и StartUp всё необходимое добавлял, в чём может быть причина?
Трудно сказать, могу провести личную консультацию, но после того как из отпуска приеду. 🙂
@@SergeiCalabonga благодарю за ответ. Для удобства я создал репозиторий, в нём коммитил по ходу видео и дойдя до указанного времени указанная выше настройка не появилась, для воспроизведения результата можно открыть последний коммит в ветке master github.com/Artyma93/Calabonga. Я также нашёл примерное решение и добавил это решение в отдельную ветку AddInMemoryApiScopes. Однако странно, что в видео работает и без этого дополнительного метода.
@@SergeiCalabonga благодарю за ответ. Почему-то ютуб не пропустил мой предыдущий ответ Вам, в котором я отправлял ссылку на свой репозиторий на GitHub, но не страшно. Оказалось проблема в том, что в Вашем видео и проекте используется IdentityServer4 версии 3.1.3, а самая актуальная версия 4.0.3, которая и устанавливается, если делать всё самостоятельно с нуля. И как оказалось для этой версии необходимо добавить в класс Startup метод AddInMemoryApiScopes и в класс Configuration метод GetApiScopes. Тогда в scopes_supported появляется OrdersAPI. Но когда посылается запрос приходит всё равно ответ Unauthorized, т.к. теперь ему не хватает Audience в Access_token и получается следующая ошибка Bearer error="invalid_token",
error_description="The audience is invalid". Решение которой на stackoverflow вроде как есть, но не совсем понятно, там предлагается в клиенте в классе Startup добавить метод app.UseOpenIdConnectAuthentication, но всё же остаются вопросы. В связи с чем прошу осветить данную тему и обновить версию IdentityServer4 в одном из будущих видео. С уважением Артём.
Шаблоны для построения микросервисной архитектуры уже обновлены. Возможно и этот оепозиторий я обновлю, если будет время. Спасибо за комментарий.
@@SergeiCalabonga Благодарю за такую отзывчивость. Пользуясь случаем, можно ли Вас попросить осветить ещё такие вопросы в дальнейших уроках:
1. Аутентификация с помощью провайдера от Microsoft, на сколько я понимаю там можно разными вариантами это делать, например в документации у них рассказывается про Azure Active Directory, Azure Active Directory B2C и Azure Active Directory B2B.
2. Расскажите пожалуйста о том, как правильно делать аутентификацию с помощью стороннего провайдера (например Azure Active Directory или с помощью любого другого), если используется SPA приложение, но не на базе пустого Asp Core приложения, а как отдельное (например часто, когда делают SPA на React используют шаблон create-react-app, но это актуально и для Angular с Vue, на сколько я понимаю), с использованием Flow Code GrantType. Понятен общий принцип для SPA, когда используется Implicit Flow, пользователь указывает логин и пароль, а после на клиент, т.е. в случае SPA, access_token прилетает в браузер пользователя и после с этим токеном он идёт в нужный API (например OrdersAPI). Но при этом говорят, что использовать Implicit Flow менее безопасно, поэтому рекомендуется, чтобы использовался Code Flow и чтобы code (с помощью которого в последствии получается access_token) прилетал не в сам SPA, а в бекэнд часть клиента. И вот тут на сколько я понимаю, в случае MVC всё просто, т.к. есть View, которые доступны в браузере, есть Controlles, которые находятся на бекэнде. Но в случае с отдельным SPA, получается, что надо добавить ещё один проект на Asp Core, который будет обеспечивать бекэнд часть клиента? И вот тут самое не понятное, получается общая последовательность такая:
а) Есть клиент, он состоит из фронтэнд (отдельное SPA приложение ClientSPA) и бекэнд (Asp core проект ClientBackend), есть отдельный сервис авторизации (сторонний провайдер), есть отдельный проект (OrdersAPI).
б) ClientSPA делает запрос через ClientBackend на OrdersAPI, тот из-за отсутствия access_token перенаправляет его к стороннему провайдеру.
в) Сторонний провайдер возвращает code в ClientBackend. Вот очень не понятно, ClientBackend в свою очередь преобразует code в access_token или снова отправляет code стороннему провайдеру, чтобы тот в ответ прислал access_token? И уже после ClientBackend access_token отправляет в OrdersAPI? И тогда после получения access_token вся цепочка взаимодействия такая: при каждом запросе пользователем информации ClientSPA идёт в ClientBackend (т.к. мы же спрятали и code и access_token в нём, чтобы его не украли) за тем ClientBackend обращается в OrdersAPI и уже OrdersAPI (после проверки access_token) возвращает ответ в ClientSPA, так?
3) Ещё интересно послушать про протокол SAML и в чём его отличия от OIDC.
Извиняюсь, что столько много вопросов, но задать их больше некому. С уважением Артём.
Межсервисное взаимодействие стало чуть понятнее ! )
Отлично 👍
Спасибо !
Пожалуйста!
Это самое доходчивое и четкое разъяснение! Спасибо вам большое за ваш труд! Снимаю шляпу!
Шляпу не надо, а вот рублями, сколько не жалко можно тут sobe.ru/na/calabonganet поделиться :)
Для микросервисов Ocelot будет?
Вероятность такая есть. Все зависит рт наличия свободного времени.
А должно работать по http? У меня работает только по https
разобрался, services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, config =>
{
config.RequireHttpsMetadata = false;
config.Authority = "localhost:8000";
});
Конечно можно! :)
Именно так! :)
делал вроде всё как на видео, токен всегда null возвращает, в чем может быть проблема?
Версия nuget пакетов наверняка изменилась. А это значит, что настройки работы сервиса авторизации могут быть недонастроены. Проверяйте работу сервисов по отдельности. Например, через postman
public static IEnumerable GetApiScopes() =>
new List
{
new ApiScope("OrdersAPI")
}; добавь это и в стартапе добавь ,изменились параметры. Вообще в идеале полистай офф документацию
Да, в новой версии это стало обязательным.
Очень круто, все подробно, очень помог❤ Спасибо огромное, а то я уже отчаялся не понять эту тему
Благодарности принимаются sobe.ru/na/calabonganet
Да тут прям клад знаний. Спасибо огромное за ваши старание.
Спасибо на хлеб не намажешь!
Спасибо! Очень полезный материал! Огромное спасибо за пример!
Добро пожаловать на канал!
subtitles in English next time? ^^
I'll try next time. Thx. 🙂
Отличное видео
Спасибо!
Сколько видео смотрю. Везде IdentityServer работает со своими таблицами и объектами, а можно так работать,чтобы объекты IdentityServer4 oбъекты были только прослойкой между нашей БД и IdetityServer4
Не совсем понял, что вы имеете в виду. То есть, чтобы IdentityServer чтобы свои таблицы хранил в вашей БД?
@@SergeiCalabonga : да. К примеру есть такой класс как IdentityUser c которым работает IdentityServer. Мы берем данные из нашей БД, мри помощи мапинга преопразуем в объект IdentityUser и прередаем в IdentityServer. Просто я не совсем понимаю, для чего нам создавать эти таблицы в IdetityDataBase ,когда у меня в базе данных есть таблица прав,таблица пользователей и таблица людей, за которыми эти пользователи закрепленны
@Siarhei Vishneuski IdentityServer тут совсем не причём. Надо понимать отличие и взаимодействия между двумя фреймворками.
@@SergeiCalabonga : значит я не совсем понял, как это работает
@@ziegimondvishneuski3317 получается, что так. Потому что один - это авторизация и аутентификации, а другой - делегирование этих самых авторизации и аутентификации
Отличные у вас видео, можно попросить в будущем делайте шрифт больше, с мобильного плохо видно текст
Спасибо за комментарий. Я услышал вас. Постараюсь.
Вот это мегаполезные видео, когда видишь как человек руками программирует. Про шаблоны к своему стыду, не знал.
Мы все вместе учимся. 😁