SpringBoot security server2server Oauth
Background
There is handful samples about SpringBoot Server2Server ClientCredential type oauth, but sometimes we need password grant type oauth. e.g. When connecting to salesforce for restful request.
Here I provide the sample code based on some references and experiments.
References:
https://davidagood.com/oauth-client-credentials-auto-refresh-spring/
https://github.com/helloworldless/spring-oauth2-client-credentials-webclient
https://www.javaer101.com/en/article/4829693.html
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
Application.properties
spring.security.oauth2.client.registration.eric.client_id=
spring.security.oauth2.client.registration.eric.client_secret=
spring.security.oauth2.client.registration.eric.client-authentication-method=post
spring.security.oauth2.client.registration.eric.authorization-grant-type=password
spring.security.oauth2.client.provider.eric.token-uri=
3. public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizationContext;
import org.springframework.security.oauth2.client.OAuth2AuthorizationFailureHandler;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.RemoveAuthorizedClientOAuth2AuthorizationFailureHandler;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
@EnableWebSecurity
public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${eric.username}")
private String username;
@Value("${eric.password}")
private String password;
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/getab").permitAll().anyRequest().authenticated().and().httpBasic().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable();
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.password().build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
private Function<OAuth2AuthorizeRequest, Map<String, Object>> contextAttributesMapper() {
return authorizeRequest -> {
Map<String, Object> contextAttributes = Collections.emptyMap();
// HttpServletRequest servletRequest = authorizeRequest.getAttribute(HttpServletRequest.class.getName());
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = new HashMap<>();
// `PasswordOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
return contextAttributes;
@Bean("authenticatedWebClient")
WebClient webClient(WebClient.Builder webClientBuilder, OAuth2AuthorizedClientManager authorizedClientManager,
@Qualifier("resourceServerAuthorizationFailureHandler") OAuth2AuthorizationFailureHandler failureHandler) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
authorizedClientManager);
oauth2Client.setAuthorizationFailureHandler(failureHandler);
// @formatter:off
return webClientBuilder.apply(oauth2Client.oauth2Configuration()).build();
// @formatter:on
@Bean("resourceServerAuthorizationFailureHandler")
OAuth2AuthorizationFailureHandler resourceServerAuthorizationFailureHandler(
OAuth2AuthorizedClientService authorizedClientService) {
return new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(
(clientRegistrationId, principal, attributes) -> {
System.out.println("----resourceServerAuthorizationFailureHandler ----");
authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName());
@Bean("authorizationServerAuthorizationFailureHandler")
OAuth2AuthorizationFailureHandler authorizationFailureHandler(
OAuth2AuthorizedClientService authorizedClientService) {
return new RemoveAuthorizedClientOAuth2AuthorizationFailureHandler(
(clientRegistrationId, principal, attributes) -> {
System.out.println("----resourceServerAuthorizationFailureHandler ----");
authorizedClientService.removeAuthorizedClient(clientRegistrationId, principal.getName());
4. WebClient Usage:
@Autowired
private WebClient webClient;
JsonNode res = webClient.method(HttpMethod.GET).
uri("url")