Java – upgrade spring security oauth2
I'm trying to change the spring security oauth2 configuration from 2.0 Upgrade from 0.rc1 to 2.0 3.RELEASE. I copied the configuration from the sprklr example and made it work So it is based on the working example of XML based spring security oauth2 configuration
Now I've upgraded to the latest version of spring security (2.0.3 at the time of writing) and tried to convert it to a Java configuration I published the XML configuration and the following Java configuration
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd"> <!-- Authentication manager. --> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider> <security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select a.username,a.password,a.enabled,a.email from account a where a.username = ?" authorities-by-username-query="select a.username,r.role_name from account a,role r,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?" /> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled" /> <security:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"> <security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" /> <security:anonymous enabled="false" /> <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" /> <!-- include this only if you need to authenticate clients via request parameters --> <security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> </security:http> <security:http pattern="/api/.*/accounts" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true"> <security:intercept-url pattern="/api/.*/accounts" method="POST" requires-channel="https" access="#oauth2.clientHasRole('ROLE_CLIENT') or hasRole('ROLE_ANONYMOUS')"/> <security:intercept-url pattern="/.*" access="denyAll()" /> <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> <security:expression-handler ref="oauthWebExpressionHandler" /> </security:http> <security:http pattern="/api/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager"> <security:anonymous enabled="false" /> <security:intercept-url pattern="/api/**" access="ROLE_USER,SCOPE_TRUST,SCOPE_PLAY"/> <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" /> <security:access-denied-handler ref="oauthAccessDeniedHandler" /> </security:http> <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="*****" /> </bean> <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> <property name="realmName" value="*****/client" /> <property name="typeName" value="Basic" /> </bean> <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" /> <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter"> <property name="authenticationManager" ref="clientAuthenticationManager" /> </bean> <bean id="accessDecisionManager" class="org.springframework.security.access.Vote.UnanimousBased"> <constructor-arg> <list> <bean class="org.springframework.security.oauth2.provider.Vote.ScopeVoter" /> <bean class="org.springframework.security.access.Vote.RoleVoter" /> <bean class="org.springframework.security.access.Vote.AuthenticatedVoter" /> </list> </constructor-arg> </bean> <security:authentication-manager id="clientAuthenticationManager"> <security:authentication-provider user-service-ref="clientDetailsUserService" /> </security:authentication-manager> <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService"> <constructor-arg ref="clientDetails" /> </bean> <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" /> <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices"> <property name="tokenStore" ref="tokenStore" /> <property name="tokenEnhancer" ref="tokenEnhancer" /> <property name="supportRefreshToken" value="true" /> <property name="clientDetailsService" ref="clientDetails" /> <property name="accessTokenValiditySeconds" value="6000" /> </bean> <bean id="tokenEnhancer" class="com.****.*****.config.*****TokenEnhancer" /> <bean id="requestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory"> <constructor-arg name="clientDetailsService" ref="clientDetails" /> </bean> <bean id="userApprovalHandler" class="com.****.*****.config.*****UserApprovalHandler"> <property name="approvalStore" ref="approvalStore" /> <property name="clientDetailsService" ref="clientDetails" /> <property name="requestFactory" ref="requestFactory" /> </bean> <bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore"> <property name="tokenStore" ref="tokenStore" /> </bean> <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler"> <oauth:authorization-code /> <oauth:implicit /> <oauth:refresh-token /> <oauth:client-credentials /> <oauth:password /> </oauth:authorization-server> <oauth:resource-server id="resourceServerFilter" resource-id="*****" token-services-ref="tokenServices" /> <oauth:client-details-service id="clientDetails"> <oauth:client client-id="*****-PHP-demo" secret="??????????" authorized-grant-types="password,authorization_code,refresh_token,client_credentials" authorities="ROLE_USER,ROLE_CLIENT" scope="play,trust" access-token-validity="6000"/> <oauth:client client-id="*****-swagger-ui" authorized-grant-types="implicit" authorities="ROLE_USER,ROLE_CLIENT,ROLE_TRUSTED_CLIENT" scope="play,trust" redirect-uri="${baseUrl}/o2c.html" autoapprove="true" access-token-validity="6000"/> <oauth:client client-id="*****-runscope" secret="???????????????????????????????" authorized-grant-types="password,refresh_token" authorities="ROLE_USER,trust" redirect-uri="https://www.runscope.com/oauth_tool/callback" autoapprove="true" access-token-validity="6000"/> </oauth:client-details-service> <oauth:expression-handler id="oauthExpressionHandler" /> <oauth:web-expression-handler id="oauthWebExpressionHandler" />
And Java configuration (so far..)
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Value("${baseUrl}") private String baseUrl; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("*****-????????") .secret("????????????????????") .authorizedGrantTypes("password","authorization_code","refresh_token","client_credentials") .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT") .scopes("play","trust") .and() .withClient("*****-????????") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","ROLE_CLIENT","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("*****-???????") .secret("????????????????????") .authorizedGrantTypes("password","refresh_token") .authorities("ROLE_USER","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(new *****TokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { *****UserApprovalHandler handler = new *****UserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService()); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private ClientDetailsService clientDetailsService; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean protected UserDetailsService clientDetailsUserService() { return new ClientDetailsUserDetailsService(clientDetailsService); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(clientDetailsUserService()); JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?"); jdbcUserDetail.usersByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("oauth2/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/index.html","/resources/**","/swagger/**","/copyright*","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenServices(tokenServices); resources.resourceId("*****"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.clientDetailsService(clientDetailsService) .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler); } } }
Add more information (based on Dave syer's questions)
Do not generate tokens, see more information below
Request:
curl -k -i -H "Accept: application/json" -X POST -d "grant_type=password&client_id=*****-PHP-demo&client_secret=???????&scope=play trust&username=tester&password=121212" https://localhost:8443/*****/oauth/token
Response:
HTTP/1.1 401 Unauthorized Server: Apache-Coyote/1.1 X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache,no-store,max-age=0,must-revalidate Pragma: no-cache Expires: 0 Strict-Transport-Security: max-age=31536000 ; includeSubDomains x-frame-options: DENY Cache-Control: no-store Pragma: no-cache WWW-Authenticate: Basic realm="*****/client",error="unauthorized",error_description="An Authentication object was not found in the SecurityContext" Content-Type: application/json;charset=UTF-8 @R_542_301@: chunked Date: Tue,16 Sep 2014 14:05:19 GMT
{"error": "unauthorized", "error_description": "cannot find authentication object in securitycontext"}
Server log:
Request received for POST '/oauth/token': org.apache.catalina.connector.RequestFacade@344dad0c servletPath: pathInfo:/oauth/token headers: user-agent: curl/7.30.0 host: localhost:8443 accept: application/json content-length: 145 content-type: application/x-www-form-urlencoded Security filter chain: [ WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter logoutFilter BasicAuthenticationFilter RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter SessionManagementFilter ExceptionTranslationFilter FilterSecurityInterceptor ]
(updated on October 14)
Java security configuration;
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Value("${baseUrl}") private String baseUrl; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("abc") .secret("?????") .authorizedGrantTypes("password","client_credentials") .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT") .scopes("play","trust") .and() .withClient("xyz") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("zzz") .secret("?????????????????") .authorizedGrantTypes("password","refresh_token") .authorities("ROLE_USER","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService()); tokenServices.setTokenEnhancer(new MyTokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { MyUserApprovalHandler handler = new MyUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService()); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService())); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private ClientDetailsService clientDetailsService; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean protected UserDetailsService clientDetailsUserService() { return new ClientDetailsUserDetailsService(clientDetailsService); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?"); jdbcUserDetail.usersByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { AuthenticationManager am = super.authenticationManagerBean(); return am; } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("redrum/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/resources/**","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on } @Bean public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception { ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); filter.setAuthenticationEntryPoint(authenticationEntryPoint()); filter.setAuthenticationManager(authenticationManagerBean()); return filter; } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Autowired private AuthenticationManager authenticationManager; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenServices(tokenServices); resources.resourceId("xyz"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.clientDetailsService(clientDetailsService) .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler); } } }
Solution
This is the solution; I hope it will be useful to sb Using the current state of spring oauth2 documentation and examples to determine this solution is not easy
@Configuration public class SecurityConfig { @Autowired private DataSource dataSource; @Autowired private ClientDetailsService clientDetailsService; @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean public DefaultTokenServices tokenServices() throws Exception { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setAccessTokenValiditySeconds(6000); tokenServices.setClientDetailsService(clientDetailsService); tokenServices.setTokenEnhancer(new MyTokenEnhancer()); tokenServices.setSupportRefreshToken(true); tokenServices.setTokenStore(tokenStore()); return tokenServices; } @Bean public UserApprovalHandler userApprovalHandler() throws Exception { MyUserApprovalHandler handler = new MyUserApprovalHandler(); handler.setApprovalStore(approvalStore()); handler.setClientDetailsService(clientDetailsService); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setUseApprovalStore(true); return handler; } @Bean public ApprovalStore approvalStore() { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore()); return store; } @Bean public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) @EnableWebSecurity protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${baseUrl}") private String baseUrl; @Autowired private DataSource dataSource; @Resource private PasswordEncoder passwordEncoder; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Bean public ClientDetailsService clientDetailsService() throws Exception { ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration(); serviceConfig.clientDetailsServiceConfigurer().inMemory() .withClient("***-***-****") .secret("???????????????????????????????") .authorizedGrantTypes("password","trust") .and() .withClient("***-******-**") .authorizedGrantTypes("implicit") .authorities("ROLE_USER","trust") .redirectUris(baseUrl + "/o2c.html") .autoApprove(true) .and() .withClient("******-***********") .secret("???????????????????????????????????") .authorizedGrantTypes("password","trust") .redirectUris("https://www.runscope.com/oauth_tool/callback") .autoApprove(true); return serviceConfig.clientDetailsService(); } @Bean UserDetailsService clientDetailsUserDetailsService() throws Exception { return new ClientDetailsUserDetailsService(clientDetailsService()); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcUserDetail = new JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder>(); jdbcUserDetail.dataSource(dataSource); jdbcUserDetail.passwordEncoder(passwordEncoder); jdbcUserDetail.authoritiesByUsernameQuery("select a.username,a.email from account a where a.username = ?"); auth.apply(jdbcUserDetail); auth.userDetailsService(clientDetailsUserDetailsService()); } @Bean(name="authenticationManager") @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean protected AuthenticationEntryPoint authenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setTypeName("Basic"); entryPoint.setRealmName("app/client"); return entryPoint; } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity .ignoring() .antMatchers("/resources/**","/api-docs/**") .and() .debug(true); } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.anonymous().disable() .antMatcher("/oauth/token") .authorizeRequests().anyRequest().authenticated() .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and() .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable() .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler) .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // @formatter:on ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); filter.setAuthenticationManager(authenticationManagerBean()); filter.afterPropertiesSet(); http.addFilterBefore(filter,BasicAuthenticationFilter.class); } } @Configuration @EnableResourceServer protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private ResourceServerTokenServices tokenServices; @Autowired private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { //resources.tokenServices(tokenServices); resources.resourceId("app"); } @Override public void configure(HttpSecurity http) throws Exception { // @formatter:off http .anonymous() .disable(); // API calls http .authorizeRequests() .regexMatchers(HttpMethod.POST,"/api/.*/accounts") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // API calls http .authorizeRequests() .antMatchers("/api/**") .access("#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))") .and() //.addFilterBefore(clientCredentialsTokenEndpointFilter(),BasicAuthenticationFilter.class) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .exceptionHandling() .accessDeniedHandler(oAuth2AccessDeniedHandler); // @formatter:on } } @Configuration @EnableAuthorizationServer protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private DefaultTokenServices tokenServices; @Autowired private ClientDetailsService clientDetailsService; @Autowired private UserApprovalHandler userApprovalHandler; @Autowired private AuthenticationManager authenticationManager; @Autowired AuthenticationEntryPoint authenticationEntryPoint; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .tokenServices(tokenServices) .userApprovalHandler(userApprovalHandler) .authenticationManager(authenticationManager); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.authenticationEntryPoint(authenticationEntryPoint) .realm("app/clients"); } } }