OAuth 2 Сlient Credentials Flow. Пример на Spring Boot
В этой статье рассмотрим пример Client Credentials flow с новым экспериментальным сервером авторизации на Spring Boot. Новый сервер был анонсирован буквально недавно и еще не полностью готов (текущая версия 0.0.2). Но Client Credentials flow (и Authorization Code flow) он уже поддерживает.
Пример взят из официального репозитория, но переделан под Maven (вместо Gradle). Еще в нем включено логирование запросов. Так что в консоли мы увидим запросы — их отправляет backend клиента и backend сервера ресурсов с помощью RestTemplate и Webclient. Этих скрытых запросов много — все три сервера активно взаимодействуют.
Пример, как и положено, состоит из трёх компонентов. Все они являются Spring Boot приложениями и запускаются на разных серверах:
сервер авторизации. Здесь есть:
конечная точка http://auth-server:9000/oauth2/token. Здесь происходит аутентификация клиента по Client Credentials и ему выдается access-token (он же JWT-токен)
конечная точка http://auth-server:9000/oauth2/jwks. Здесь происходит проверка этого JWT-токена. Вообще этот токен отправляет клиент на сервер ресурсов с каждым запросом. Но сервер ресурсов проверяет его не сам, а обращается на эту точку, чтобы проверить токен.
сервер ресурсов. Он получает запрос от клиента с JWT-токеном и отправляет этот токен серверу авторизации на проверку. Если все ок, то выдает ресурс.
клиент. Он должен быть заранее зарегистрирован на сервере авторизации со своими Client Credentials. Клиент отправляет эти Client Credentials серверу авторизации, чтобы получить JWT-токен, а затем шлет запросы с приложенным JWT-токеном серверу ресурсов.
Вообще Client Credentials flow используется, если клиент — не человек, а машина. То есть перенаправления на страницу сервера авторизации и получения согласия живого пользователя не требуется, что упрощает flow. Наш клиент — это микросервис, который предоставляет API веб-интерфейсу. Но важно понимать, что несмотря на наличие веб-интерфейса, клиентом является именно приложение на сервере, а не в браузере. Приложение в браузере задействовало бы уже Implicit Flow, что не наш случай. (А наш случай — Client Credentials flow).
Перед запуском примера в файл C:\Windows\System32\drivers\etc\hosts нужно добавить строку 127.0.0.1 auth-server
Client Credentials flow
Flow уже был изложен выше при перечислении трех серверов, но теперь то же самое на картинке, а затем по пунктам:
Выглядит так:
Client Credentials Flow
Предварительно мы регистрируем клиент на сервере авторизации с client_id и client_secret. У нас значениями будут messaging-client и secret.
Клиент (серверное приложение) отправляет Client Credentials (под которыми он зарегистрирован) на сервер авторизации.
В ответ получает access token (он же JWT-токен).
С access token клиент обращается на сервер ресурсов.
Сервер ресурсов не может сам проверить access token, он обращается за проверкой на сервер авторизации.
Если проверка прошла успешно, сервер ресурсов возвращает клиенту ресурс.
Сервер авторизации и регистрация на нем клиента
Чтобы сделать приложение сервером авторизации, добавим в него зависимость:
С этим токеном (access_token) можно будет обращаться на сервер ресурсов. Если расшифровать токен на сайте jwt.io, мы увидим, что в нем есть идентификатор клиента, его права, издатель токена, время жизни токена:
Для валидации токена достаточно знать client_secret и открытые данные токена. По ним вычисляется подпись, и если она совпадает с реальной, то токен валидный. Но как уже упоминалось в начале, сервер ресурсов обращается за валидацией на сервер авторизации, сам он не знает client_secret.
Сервер ресурсов
На сервер ресурсов будем обращаться на /messages за данными:
В вышеприведенном коде мы сказали, что авторизация осуществляется через OAuth 2, то есть для доступа необходимо иметь в запросе заголовок Authorization с JWT-токеном (он же access token).
Но как сервер ресурсов поймет, корректен ли пришедший в заголовке JWT-токен? Для этого в настройках application.yml указываем, куда сервер ресурсов должен обращаться за проверкой корректности:
GET /messages HTTP/1.1
Host: localhost:8090
Authorization: Bearer eyJraWQiOiI5ZGM3MDA3Mi0xMDk2LTRkYjctOTRkYi1kY2RmMzE0OTJjZjIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYwMzcwOTg4NSwic2NvcGUiOlsibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwczpcL1wvb2F1dGgyLnByb3ZpZGVyLmNvbSIsImV4cCI6MTYwMzcxMzQ4NSwiaWF0IjoxNjAzNzA5ODg1LCJqdGkiOiI1N2RmY2UxNi1lOGRiLTRlY2MtYTdhOC0zZjc5MjRmOTJjMmUifQ.RBSysR0WVSQBXsFPfFg_u2QNxlE7HANdWnUuROxxzJbvTfapQ3T8WB0QS8V46f4yGaWymNzLAz8e_rdBsY3AKXMlZv7H0bDwifqJBQde2bpYPUIdLdzO3lJkWqMkUGY32tM1hN9ZOOrk9sQ9fW5PuKgZGXZpsKMc8DLZrzuhavc7lM94ft5EJOuEBwlOcBUOTx0qOrL6BkLGm1dcmVmTP983vgd7A9pSwY9ZHlKLfdVjQK3iFyrGA0WF7NEQQ8soWqW_otHapUQ08XVRW4vcsUSyH1QAHqonGk2R7T6dv18Vk_9nGjUfbmS4pGswgLRE0JnhSXZoTWsKHh7i-ixXpA
GET /messages HTTP/1.1
Host: localhost:8090
Authorization: Bearer eyJraWQiOiI5ZGM3MDA3Mi0xMDk2LTRkYjctOTRkYi1kY2RmMzE0OTJjZjIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYwMzcwOTg4NSwic2NvcGUiOlsibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwczpcL1wvb2F1dGgyLnByb3ZpZGVyLmNvbSIsImV4cCI6MTYwMzcxMzQ4NSwiaWF0IjoxNjAzNzA5ODg1LCJqdGkiOiI1N2RmY2UxNi1lOGRiLTRlY2MtYTdhOC0zZjc5MjRmOTJjMmUifQ.RBSysR0WVSQBXsFPfFg_u2QNxlE7HANdWnUuROxxzJbvTfapQ3T8WB0QS8V46f4yGaWymNzLAz8e_rdBsY3AKXMlZv7H0bDwifqJBQde2bpYPUIdLdzO3lJkWqMkUGY32tM1hN9ZOOrk9sQ9fW5PuKgZGXZpsKMc8DLZrzuhavc7lM94ft5EJOuEBwlOcBUOTx0qOrL6BkLGm1dcmVmTP983vgd7A9pSwY9ZHlKLfdVjQK3iFyrGA0WF7NEQQ8soWqW_otHapUQ08XVRW4vcsUSyH1QAHqonGk2R7T6dv18Vk_9nGjUfbmS4pGswgLRE0JnhSXZoTWsKHh7i-ixXpA
Этот же запрос в Postman с ответом:
Если же токен не прикладывать, вернется 401 с заголовком:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
WWW-Authenticate: Bearer
WWW-Authenticate: Bearer
WWW-Authenticate: Bearer
Однако, в реальности при запросе ресурса выполняется не один запрос, а два — есть еще дополнительный запрос от сервера ресурсов к серверу авторизации для проверки токена. И это можно увидеть в консоли в IntelliJ IDEA.
Проверка access токена
В консоли запущенного сервера ресурсов мы увидим, что он обращается на сервер авторизации по адресу
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
http://auth-server:9000/oauth2/jwks
http://auth-server:9000/oauth2/jwks
http://auth-server:9000/oauth2/jwks
для проверки access токена:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
2020-10-2613:32:37.387 DEBUG 13124 --- [nio-8090-exec-2] o.s.web.client.RestTemplate: HTTP GET http://auth-server:9000/oauth2/jwks
Теперь конечная точка /authorize, которая инициирует обращение к ресурсам. На нее идет перенаправление после того, как пользователь или микросервис авторизовался:
@Controller
public class AuthorizationController {
private final WebClient webClient;
private final String messagesBaseUri;
public AuthorizationController(WebClient webClient,
@Value("${messages.base-uri}") String messagesBaseUri) {
this.webClient = webClient;
this.messagesBaseUri = messagesBaseUri;
}
@GetMapping(value = "/authorize", params = "grant_type=client_credentials")
public String clientCredentialsGrant(Model model) {
System.out.println("before");
String[] messages = this.webClient
.get()
.uri(this.messagesBaseUri)
.attributes(clientRegistrationId("messaging-client-client-credentials"))
.retrieve()
.bodyToMono(String[].class)
.block();
model.addAttribute("messages", messages);
return "index";
}
}
@Controller
public class AuthorizationController {
private final WebClient webClient;
private final String messagesBaseUri;
public AuthorizationController(WebClient webClient,
@Value("${messages.base-uri}") String messagesBaseUri) {
this.webClient = webClient;
this.messagesBaseUri = messagesBaseUri;
}
@GetMapping(value = "/authorize", params = "grant_type=client_credentials")
public String clientCredentialsGrant(Model model) {
System.out.println("before");
String[] messages = this.webClient
.get()
.uri(this.messagesBaseUri)
.attributes(clientRegistrationId("messaging-client-client-credentials"))
.retrieve()
.bodyToMono(String[].class)
.block();
model.addAttribute("messages", messages);
return "index";
}
}
Клиент у нас веб-приложение. Инициировать нужный flow можно, щелкнув по ссылке:
Главная страница клиента
Щелкнув Client Credentials (http://localhost:8080/authorize?grant_type=client_credentials), мы попадаем в контроллер выше. В контроллере WebClient обращается к серверу ресурсов по адресу http://localhost:8090/messages (messagesBaseUri), но перед этим WebClient получил токен на сервере авторизации.
То есть в консоли мы увидим два запроса вместо одного: сначала за токеном на сервер авторизации, а затем с токеном в заголовке на сервер ресурсов:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
2020-10-2620:06:52.714 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate :HTTP POST http://auth-server:9000/oauth2/token
2020-10-2620:06:53.111 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate :Response200 OK
2020-10-2620:06:53.112 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate :Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json;charset=UTF-8"
2020-10-2620:06:53.386 WARN 5748 --- [oundedElastic-1] o.a.c.util.SessionIdGeneratorBase :Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [247] milliseconds.
2020-10-26 20:06:52.714 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : HTTP POST http://auth-server:9000/oauth2/token
2020-10-26 20:06:52.716 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Accept=[application/json, application/*+json]
2020-10-26 20:06:52.716 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Writing [{grant_type=[client_credentials], scope=[message.read message.write]}] as "application/x-www-form-urlencoded;charset=UTF-8"
2020-10-26 20:06:53.111 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Response 200 OK
2020-10-26 20:06:53.112 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json;charset=UTF-8"
2020-10-26 20:06:53.386 WARN 5748 --- [oundedElastic-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [247] milliseconds.
2020-10-26 20:06:53.471 TRACE 5748 --- [oundedElastic-1] o.s.w.r.f.client.ExchangeFunctions : HTTP GET http://localhost:8090/messages, headers=[Authorization:"Bearer eyJraWQiOiI0NzQyZDFhYy1kOWQ2LTQzYTQtYTM3OS1kZjdiZDExOGVmMWIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYwMzcyNDgxMywic2NvcGUiOlsibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwczpcL1wvb2F1dGgyLnByb3ZpZGVyLmNvbSIsImV4cCI6MTYwMzcyODQxMywiaWF0IjoxNjAzNzI0ODEzLCJqdGkiOiI3OGMxZWNhMS1mMzE5LTQ1YTEtODAzZC02NzE4MDZjNTgxMzcifQ.Rh7Dsyfz7icMdliElh0A_8NkDTD_uAHD5KWkMwEXbydPLebw3VK-uXMKi8WP10DPoSWWADe-YatCWdpUnLS83OHKOa2qfCBIinaZPEpw6QtPUKuiS_8zM9JJmFJPEo2mqvzhm3RqUG1LGDk9oYHSOhk5AbastWNIP4Gw1yC4DnKGsyhbGzX4fD1AhkjggHvODSddfRIwLd1akfpC5VFtHty86DcYk-YBqh8kTsJ0AXIHRGh3tP-LBQVA5Dpe_6sF6wh5bpWfifeoCzxsaQieHj-QZ53OHHDcSRqJGqE30Pp9fiTF9077pT4i--yrjGDGsUUJmZSGWspZYLAwlPWgdw"]
2020-10-26 20:06:53.971 TRACE 5748 --- [ctor-http-nio-1] o.s.w.r.f.client.ExchangeFunctions : Response 200 OK, headers=[X-Content-Type-Options:"nosniff", ...]
2020-10-26 20:06:52.714 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : HTTP POST http://auth-server:9000/oauth2/token
2020-10-26 20:06:52.716 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Accept=[application/json, application/*+json]
2020-10-26 20:06:52.716 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Writing [{grant_type=[client_credentials], scope=[message.read message.write]}] as "application/x-www-form-urlencoded;charset=UTF-8"
2020-10-26 20:06:53.111 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Response 200 OK
2020-10-26 20:06:53.112 DEBUG 5748 --- [oundedElastic-1] o.s.web.client.RestTemplate : Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json;charset=UTF-8"
2020-10-26 20:06:53.386 WARN 5748 --- [oundedElastic-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [247] milliseconds.
2020-10-26 20:06:53.471 TRACE 5748 --- [oundedElastic-1] o.s.w.r.f.client.ExchangeFunctions : HTTP GET http://localhost:8090/messages, headers=[Authorization:"Bearer eyJraWQiOiI0NzQyZDFhYy1kOWQ2LTQzYTQtYTM3OS1kZjdiZDExOGVmMWIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYwMzcyNDgxMywic2NvcGUiOlsibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwczpcL1wvb2F1dGgyLnByb3ZpZGVyLmNvbSIsImV4cCI6MTYwMzcyODQxMywiaWF0IjoxNjAzNzI0ODEzLCJqdGkiOiI3OGMxZWNhMS1mMzE5LTQ1YTEtODAzZC02NzE4MDZjNTgxMzcifQ.Rh7Dsyfz7icMdliElh0A_8NkDTD_uAHD5KWkMwEXbydPLebw3VK-uXMKi8WP10DPoSWWADe-YatCWdpUnLS83OHKOa2qfCBIinaZPEpw6QtPUKuiS_8zM9JJmFJPEo2mqvzhm3RqUG1LGDk9oYHSOhk5AbastWNIP4Gw1yC4DnKGsyhbGzX4fD1AhkjggHvODSddfRIwLd1akfpC5VFtHty86DcYk-YBqh8kTsJ0AXIHRGh3tP-LBQVA5Dpe_6sF6wh5bpWfifeoCzxsaQieHj-QZ53OHHDcSRqJGqE30Pp9fiTF9077pT4i--yrjGDGsUUJmZSGWspZYLAwlPWgdw"]
2020-10-26 20:06:53.971 TRACE 5748 --- [ctor-http-nio-1] o.s.w.r.f.client.ExchangeFunctions : Response 200 OK, headers=[X-Content-Type-Options:"nosniff", ...]
Для просмотра полного текста фрагмента выше наведите курсор и щелкните иконку с горизонтальными линиями — Open code in new window — откроется блокнот с настоящим текстом.
То есть ровно то, что мы делали в Postman двумя запросами, клиент делает сам.
Итоги
Исходный код на Maven с включенными логами и закомментированным Authorization Code Flow есть на GitHub.
Уважаемвй автор. Не могли бы вы сделать туториал на тему, как авторизоваться с помощью spring boot и oauth2 на сторонних серверах (не google, facebook и пр. которые входят в коробку), а напримере vk.com?
Очень хочется понять, как сделать кастомный вариант.
В интернете почти нет на эту тему информации.
К сожалению, VK ответы выдает нестандартные (не полностью соответствующие протоколу OAuth 2). Так что это целая история — поддержать VK, и чтоб остальные провайдеры (которые поддерживаются в Spring Security по умолчанию) при этом не слетели.
В Client Credentials Flow пользователи не фигурируют, они есть в Authorization Code Flow, пример тут
Разница с этим примером только в части AuthorizationServer:
— раскомментируем две строки, которые как раз отвечают за Authorization Code Flow:
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) и
.redirectUri
Так Authorization Code Flow стал доступен.
— вместо @Bean UserDetails с InMemory-пользователем задаем свой CustomUserDetailsService, в котором прописано, каким образом брать пользователей из базы (подробнее тут). В примере база h2 с тремя пользователями (и Hibernate), но можно подключить любую базу.
Ну oauth 2 (authorization code flow) и есть реализация sso. Несколько клиентов используют единый Authorization Server для входа пользователей (перенаправляют их туда для логина и получения разрешений). Другое дело, что есть ещё стандарт openid (похож на oauth2, но он исключительно для входа, без выдачи разрешений). Так вот не знаю, поддерживает ли данный Authorization Server от Spring стандарт openid. Потому что он еще в процессе разработки, но подозреваю, что да. Пример почти без изменений взят из официального репозитория, там же и список issues есть, можно поискать или спросить. А можно взять keyloak — сторонний сервер авторизации, он точно давно готов полностью (но у меня с ним примера нет)
Да, действительно. хотел удалить комментарий, но не получилось. не обратил внимания на заметку в начале, о длобавлении «127.0.0.1 auth-server» (вчера там было применительно к Linux). Только зачем так сделали? Не проще ли было использовать localhost в адресе…
Мне вот интересно, а если стоит задача настроить SSO с уже существующим authentication server-ом. Например, есть корпоративный аккаунт на Keycloak, мы пишем корпоративный же веб-вервис который должен аутертифицировать пользователей с помощью Keycloak. Что в этом случае измениться? Как я понимаю, это уже будет Authorization Code flow, а Client будет являтся и Resource server-ом?
1) без псевдонима не работает (из-за перенаправления в браузере между одним доменом с разными портами, но это неточно)
2) Да, если это именно люди, которые в браузере перенаправляются на сервер авторизации, входят там в систему, дают согласие на доступ клиента к ресурсам, а потом перебрасываются обратно, то это Authorization Code flow.
Веб-сервис — это наверно Resource-сервер, а клиент отдельно, иначе зачем вообще OAuth2. Но вам виднее. (Resource-сервер может одновременно быть и Authorization сервер, если это соцсеть GitHub или Google — там и вход в систему, и ресурсы-фотографии)
Можно узнать практическое применение данного примера?
В этом примере клиент — это микросервис (приложение на сервере), , который предоставляет API веб-интерфейсу.
Например, есть web-приложение (на Angular, Vue или чистый JS) + приложение Java на микросервисах.
Web-приложение обращается к клиенту за доступом к ресурсам (чтение-запись в БД), клиент определяет уровень доступа пользователя, и в зависимости от этого отклоняет запрос или перенаправляет в другой микросервис для получения запрошенного ресурса.
Возможно такое применение вашего примера?
Или он совсем о другом?
И для моего случая достаточно просто REST API авторизации?
Опечатка:
«Пример, как и положено, состоит их трех компонентов. »
«…из трёх…»
Уважаемвй автор. Не могли бы вы сделать туториал на тему, как авторизоваться с помощью spring boot и oauth2 на сторонних серверах (не google, facebook и пр. которые входят в коробку), а напримере vk.com?
Очень хочется понять, как сделать кастомный вариант.
В интернете почти нет на эту тему информации.
Постараюсь
Спасибо. С нетерпением ждём!! 🙂
побыстрее))
К сожалению, VK ответы выдает нестандартные (не полностью соответствующие протоколу OAuth 2). Так что это целая история — поддержать VK, и чтоб остальные провайдеры (которые поддерживаются в Spring Security по умолчанию) при этом не слетели.
Пример SSO с VK (+github и Google) https://sysout.ru/single-sign-on-s-postavshhikom-vk/
ребята а есть пример сервиса авторизации с подключённой бд в которой хранятся пользователи для входа в систему?
В Client Credentials Flow пользователи не фигурируют, они есть в Authorization Code Flow, пример тут
Разница с этим примером только в части AuthorizationServer:
— раскомментируем две строки, которые как раз отвечают за Authorization Code Flow:
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) и
.redirectUri
Так Authorization Code Flow стал доступен.
— вместо @Bean UserDetails с InMemory-пользователем задаем свой CustomUserDetailsService, в котором прописано, каким образом брать пользователей из базы (подробнее тут). В примере база h2 с тремя пользователями (и Hibernate), но можно подключить любую базу.
Спасибо.
А ваши примеры подойдут для реализации Single Sign-On?
Ну oauth 2 (authorization code flow) и есть реализация sso. Несколько клиентов используют единый Authorization Server для входа пользователей (перенаправляют их туда для логина и получения разрешений). Другое дело, что есть ещё стандарт openid (похож на oauth2, но он исключительно для входа, без выдачи разрешений). Так вот не знаю, поддерживает ли данный Authorization Server от Spring стандарт openid. Потому что он еще в процессе разработки, но подозреваю, что да. Пример почти без изменений взят из официального репозитория, там же и список issues есть, можно поискать или спросить. А можно взять keyloak — сторонний сервер авторизации, он точно давно готов полностью (но у меня с ним примера нет)
Не работает ваш authorization server. Запрос с postman не проходит
Почему? все сработало, внимательнее смотрите (только что перепроверено).
Да, действительно. хотел удалить комментарий, но не получилось. не обратил внимания на заметку в начале, о длобавлении «127.0.0.1 auth-server» (вчера там было применительно к Linux). Только зачем так сделали? Не проще ли было использовать localhost в адресе…
Мне вот интересно, а если стоит задача настроить SSO с уже существующим authentication server-ом. Например, есть корпоративный аккаунт на Keycloak, мы пишем корпоративный же веб-вервис который должен аутертифицировать пользователей с помощью Keycloak. Что в этом случае измениться? Как я понимаю, это уже будет Authorization Code flow, а Client будет являтся и Resource server-ом?
1) без псевдонима не работает (из-за перенаправления в браузере между одним доменом с разными портами, но это неточно)
2) Да, если это именно люди, которые в браузере перенаправляются на сервер авторизации, входят там в систему, дают согласие на доступ клиента к ресурсам, а потом перебрасываются обратно, то это Authorization Code flow.
Веб-сервис — это наверно Resource-сервер, а клиент отдельно, иначе зачем вообще OAuth2. Но вам виднее. (Resource-сервер может одновременно быть и Authorization сервер, если это соцсеть GitHub или Google — там и вход в систему, и ресурсы-фотографии)
пример SSO с Keyloak https://sysout.ru/single-sign-on-s-postavshhikom-keyloak/
Можно узнать практическое применение данного примера?
В этом примере клиент — это микросервис (приложение на сервере), , который предоставляет API веб-интерфейсу.
Например, есть web-приложение (на Angular, Vue или чистый JS) + приложение Java на микросервисах.
Web-приложение обращается к клиенту за доступом к ресурсам (чтение-запись в БД), клиент определяет уровень доступа пользователя, и в зависимости от этого отклоняет запрос или перенаправляет в другой микросервис для получения запрошенного ресурса.
Возможно такое применение вашего примера?
Или он совсем о другом?
И для моего случая достаточно просто REST API авторизации?