sequence
This article will discuss authentication for several endpoints of Spring Security OAuth2
endpoint
Spring ws-security – oauth2-2.0.14. RELEASE – sources. The jar! /org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java
@Configuration @Import(TokenKeyEndpointRegistrar.class) public class AuthorizationServerEndpointsConfiguration { private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer(); @Autowired private ClientDetailsService clientDetailsService; @Autowired private List<AuthorizationServerConfigurer> configurers = Collections.emptyList(); @PostConstruct public voidinit() {
for (AuthorizationServerConfigurer configurer : configurers) {
try {
configurer.configure(endpoints);
} catch (Exception e) {
throw new IllegalStateException("Cannot configure enpdoints", e);
}
}
endpoints.setClientDetailsService(clientDetailsService);
}
@Bean
public AuthorizationEndpoint authorizationEndpoint() throws Exception {
AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
authorizationEndpoint.setTokenGranter(tokenGranter());
authorizationEndpoint.setClientDetailsService(clientDetailsService);
authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
return authorizationEndpoint;
}
@Bean
public TokenEndpoint tokenEndpoint() throws Exception {
TokenEndpoint tokenEndpoint = new TokenEndpoint();
tokenEndpoint.setClientDetailsService(clientDetailsService);
tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
tokenEndpoint.setTokenGranter(tokenGranter());
tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
return tokenEndpoint;
}
@Bean
public CheckTokenEndpoint checkTokenEndpoint() {
CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices());
endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter());
endpoint.setExceptionTranslator(exceptionTranslator());
return endpoint;
}
@Bean
public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() {
return new WhitelabelApprovalEndpoint();
}
@Bean
public WhitelabelErrorEndpoint whitelabelErrorEndpoint() {
returnnew WhitelabelErrorEndpoint(); } / /... }Copy the code
The following configurations are displayed
- /oauth/authorize
- /oauth/token
- /oauth/check_token
- /oauth/confirm_access
- /oauth/error
The endpoint of the certification
/oauth/authorize
This need to protect user account password authentication protection, otherwise will report
curl -i http://localhost:8080/oauth/authorize\? The payload \ = code \ & client_id \ = demoApp \ & redirect_uri \ = http://localhost:8081/callback HTTP / 1.1 500 X-Application-Context: application Content-Type: application/json; charset=UTF-8 Transfer-Encoding: chunked Date: Sun, 10 Dec 2017 07:12:50 GMT Connection: close {"timestamp": 1512889970484,"status": 500,"error":"Internal Server Error"."exception":"org.springframework.security.authentication.InsufficientAuthenticationException"."message":"User must be authenticated with Spring Security before authorization can be completed."."path":"/oauth/authorize"}
Copy the code
/oauth/token
- This if the configuration support allowFormAuthenticationForClients and url client_id and client_secret will go ClientCredentialsTokenEndpointFilter to protect
- If there is no support allowFormAuthenticationForClients or support but not in the url client_id and client_secret, basic authentication protection
/oauth/check_token
This goes with BASIC authentication protection
/oauth/confirm_access
This requires authentication protection, otherwise bid 500
Curl -i http://localhost:8080/oauth/confirm_access HTTP / 1.1 500 X - Application - Context: Application cache-control: no-store Content-Type: application/json; charset=UTF-8 Content-Language: zh-CN Transfer-Encoding: chunked Date: Sun, 10 Dec 2017 07:13:55 GMT Connection: close {"timestamp": 1512890035907,"status": 500,"error":"Internal Server Error"."exception":"org.springframework.expression.spel.SpelEvaluationException"."message":"EL1008E: Property or field 'authorizationRequest' cannot be found on object of type 'java.util.HashMap' - maybe not public?"."path":"/oauth/confirm_access"}
Copy the code
/oauth/error
This can be protected without authentication
Basic certification protection of the source
Spring ws-security – oauth2-2.0.14. RELEASE – sources. The jar! /org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerSecurityConfiguration.java
@Override
protected void configure(HttpSecurity http) throws Exception {
AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer();
FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping();
http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping);
configure(configurer);
http.apply(configurer);
String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");
String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");
String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");
if(! endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) { UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class); endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService); } // @formatter:off http .authorizeRequests() .antMatchers(tokenEndpointPath).fullyAuthenticated() .antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess()) .antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess()) .and() .requestMatchers() .antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER); // @formatter:on http.setSharedObject(ClientDetailsService.class, clientDetailsService); }Copy the code
You can specify check_token’s authentication level, while /oauth/token requires fullyAuthenticated
Token_key is JWT specific, so I’m going to ignore it
The difference between isAuthenticated() and isFullyAuthenticated
One is authenticated and one is fullyAuthenticated, the former excluding anonymous, the latter excluding anonymous and remember-me
- isAuthenticated()
Returns true if the user is not anonymous
- isFullyAuthenticated()
Returns true if the user is not an anonymous or a remember-me user
summary
In conclusion, we need to protect the /oauth/authorize and /oauth/confirm_access endpoint, of course, the main /oauth/authorize this.
Due to several other/request/certification. The endpoint configuration is higher than the priority of the beginning of the default WebSecurityConfigurerAdapter configuration (order = 100), so it can be configured by default
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.requestMatchers().antMatchers("/oauth/**"."/login/**"."/logout/**")
.and()
.authorizeRequests()
.antMatchers("/oauth/**").authenticated() .and() .formLogin().permitAll(); // Add login form support for user login and authorization}}Copy the code
Protect the whole /oauth/*
doc
- Difference between isAuthenticated and isFullyAuthenticated