Order
This article will talk about the certification of several endpoint of spring security oauth2.
endpoint
spring-security-oauth2-2.0.14.RELEASE-sources.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 void init() {
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() {
return new WhitelabelErrorEndpoint();
}
//......
}
The following configurations are shown here
- /oauth/authorize
- /oauth/token
- /oauth/check_token
- /oauth/confirm_access
- /oauth/error
Endpoint certification
/oauth/authorize
This need to protect the user account password authentication protection, otherwise it will be reported
curl -i http://localhost:8080/oauth/authorize\?response_type\=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"}
/oauth/token
- If the configuration supports allowformationforclients, and the url has client_id and client_secret, clientcredentialstokendpointfilter will be used to protect it.
- If there is no support for AllowFormationForClients or if there is support but there is no client_id and client_secret in the url, go to basic authentication protection.
/oauth/check_token
This is protected by basic authentication.
/oauth/confirm_access
This requires authentication protection, otherwise report 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"}
/oauth/error
This can be protected without authentication
Basic Certified Source Code for Protection
spring-security-oauth2-2.0.14.RELEASE-sources.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);
}
Among them, you can specify the authentication level of check_token yourself, while /oauth/token requires fullyAuthenticated
Token_key This is unique to jwt and is ignored here.
The difference between isAuthenticated () and isFullyAuthenticated
One is authenticated and the other is fullyAuthenticated. The former excludes anonymous, while the latter excludes anonymous and remember-me-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
To sum up, it is necessary to protect the two endpoints of /oauth/authorize and /oauth/confirm_access, and of course the main endpoint is /oauth/authorize.
Since the authentication priority of the other authentication endpoint configurations starting with /oauth/, is higher than the default WebSecurityConfigurerAdapter configuration (order=100), the default configuration can be this way
@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(); //新增login form支持用户登录及授权
}
}
Protect the whole /oauth/** in