Я использую Spring Framework с Spring Security 5.7. Это относительно старый проект, написанный до весенней загрузки, поэтому я не использую какие-либо библиотеки или конфигурацию весенней загрузки.
У меня уже есть несколько способов аутентификации пользователя на моем сервере, через имя пользователя/пароль, SSO через Google, Microsoft и т. д.
Я пытаюсь использовать клиент Spring Security OAuth2 для аутентификации уже вошедшего в систему пользователя с помощью сторонней службы, поэтому я, в свою очередь, могу выполнять API-вызовы этой службы от имени пользователя.
Приложение также достаточно старое, поэтому я использую конфигурацию XML для своей весенней конфигурации безопасности, и у меня есть несколько тегов области, настроенных для разных целей безопасности/аутентификации/авторизации. Тем не менее, мы постепенно переводим нашу конфигурацию с xml на java и предпочли бы настроить как можно больше в java, если это возможно.
На данный момент, вот моя конфигурация Java:
@Configuration
public class OAuthConfig {
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
List<ClientRegistration> registrations = new ArrayList<>(1);
ClientRegistration client = ClientRegistration.withRegistrationId("blarg")
/* omitted client details here */
.redirectUri("https://example.com/oauth/blarg")
.build();
registrations.add(client);
return new InMemoryClientRegistrationRepository(registrations);
}
@Bean
public OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository repository) {
return new InMemoryOAuth2AuthorizedClientService(repository);
}
@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService service) {
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(service);
}
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider provider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.build();
DefaultOAuth2AuthorizedClientManager manager = new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
manager.setAuthorizedClientProvider(provider);
return manager;
}
@Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
return new HttpSessionOAuth2AuthorizationRequestRepository();
}
Кроме того, я добавил фильтр в свою основную область безопасности в xml:
applicationContext-web-security.xml:
...
<bean id = "oAuth2AuthorizationRequestRedirectFilter"
class = "org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter">
<constructor-arg ref = "clientRegistrationRepository"/>
<constructor-arg value = "/oauth/authorization"/>
</bean>
<security:http auto-config = "false" use-expressions = "true" disable-url-rewriting = "true">
...
<security:custom-filter ref = "oAuth2AuthorizationRequestRedirectFilter" position = "OAUTH2_AUTHORIZATION_REQUEST_FILTER"/>
...
</security:http>
Я, очевидно, опускаю большую часть своей конфигурации, но это новые вещи, связанные конкретно с клиентом oauth2.
На данный момент я перенаправляю своего клиента на /oauth/authorization/blaRG, чтобы запустить поток OAuth 2. Это правильно обрабатывается RedirectFilter для перенаправления третьей стороны для входа и авторизации. У меня есть проблема: как мне обработать ответ, который будет отправлен на https://example.com:9000/oauth/blarg? Он должен содержать код авторизации, который я должен преобразовать в accessToken и сохранить результат в authorClientRepository. Я знаю, как использовать репозиторий с этого момента, но я не знаю, как перейти от получения обратного вызова с кодом авторизации к получению токена доступа. В документации упоминается OAuth2AccessTokenResponseClient, но на самом деле не говорится, как его использовать.
Я даже не уверен, что мое ручное перенаправление на /oauth/authorization/blarg является правильным способом запуска потока.
Многое из того, что я нахожу в Интернете, связано со старым материалом Spring Security OAuth или связано с использованием oauth для входа пользователя через SSO.
Пожалуйста, не просто дайте мне ссылку на документацию Spring Security OAuth2 Client или javadocs, так как я просматриваю их снова и снова в течение достаточно долгого времени.
Спасибо за любую помощь, которую вы можете предоставить!
Это то, что я наконец придумал. Все еще используя конфигурацию Java из приведенного выше, вот как выглядит моя конфигурация XML. Я знаю, что могу переместить некоторые из этих bean-компонентов в конфигурацию Java, но части все еще работают.
В основном я создаю и RedirectFilter, и AuthorizationCodeGrantFilter, но GrantFilter нужен диспетчер аутентификации с провайдером, который знает, как обменять код авторизации на токен доступа, что и делает провайдер аутентификации.
<bean id = "authorizationCodeTokenResponseClient"
class = "org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient"/>
<bean id = "oAuth2AuthorizationCodeAuthenticationProvider"
class = "org.springframework.security.oauth2.client.authentication.OAuth2AuthorizationCodeAuthenticationProvider">
<constructor-arg ref = "authorizationCodeTokenResponseClient"/>
</bean>
<bean id = "oAuthAuthenticationManager" class = "org.springframework.security.authentication.ProviderManager">
<constructor-arg name = "providers">
<list>
<ref bean = "oAuth2AuthorizationCodeAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>
<bean id = "oAuth2AuthorizationRequestRedirectFilter"
class = "org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter">
<constructor-arg ref = "clientRegistrationRepository"/>
<constructor-arg value = "/oauth/authorization"/>
</bean>
<bean id = "oAuth2AuthorizationCodeGrantFilter"
class = "org.springframework.security.oauth2.client.web.BulbGrantFilter">
<constructor-arg ref = "clientRegistrationRepository"/>
<constructor-arg ref = "authorizedClientRepository"/>
<constructor-arg ref = "oAuthAuthenticationManager"/>
</bean>
Затем в моем теге http я добавляю оба фильтра в стандартную цепочку:
<secuirty:http ...>
...
<security:custom-filter ref = "oAuth2AuthorizationRequestRedirectFilter"
position = "OAUTH2_AUTHORIZATION_REQUEST_FILTER"/>
<security:custom-filter ref = "oAuth2AuthorizationCodeGrantFilter"
position = "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER"/>
...
</security:http>
Когда я хочу, чтобы пользователь авторизовал стороннюю службу, я перенаправляю их на /oauth/authorization/blaRG, который перехватывается requestFilter, который использует настроенную информацию о клиенте blarg для перенаправления пользователя третьей стороне для входа/авторизации. мое приложение. Сторонняя сторона перенаправляет обратно в мое приложение, и GrantFilter достаточно умен, чтобы сказать, что это ответ кода авторизации. Этот фильтр принимает код аутентификации и использует поставщика аутентификации для его проверки и обмена на маркер доступа и маркер обновления, а затем сохраняет их в authorClientRepository.