Spring Boot Resource Server Invalid Access Token - spring-boot

My configuration for the Spring Boot resource server is provided:
#Configuration
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "couponservice";
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/couponapi/coupons/{code:^[A-Z]*$}").hasAnyRole("USER", "ADMIN")
.mvcMatchers(HttpMethod.POST, "/couponapi/coupons").hasRole("ADMIN")
.anyRequest().denyAll().and().csrf().disable();
}
// #Bean
// public TokenStore tokenStore() {
// return new JwtTokenStore(jwtAccessTokenConverter());
// }
//
// #Bean
// public JwtAccessTokenConverter jwtAccessTokenConverter() {
//
// JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
// jwtAccessTokenConverter.setVerifierKey(publicKey);
//
// return jwtAccessTokenConverter;
// }
}
The application.properties file is provided:
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=testuser
spring.datasource.password=testpassword
server.port=9091
spring.thymeleaf.cache=false
spring.main.allow-bean-definition-overriding=true
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:9092/oauth/token_key
# security.oauth2.resource.jwt.key-uri=http://localhost:9092/oauth/token_key
If I keep the JwtAccessTokenConverter and use the correct public key, the code is working. But, I would like to connect using the auth URL provided in the properties files.
Now, when I make the GET request, I see the invalid access toekn. Whats the issue here and how do I resolve it?

Looks like you need to tell Spring WHAT MECHANISM to use to authorize. Maybe compare to this Curity example, which should provide enough clues to overcome your problem:
Code
Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
String issuerUri;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/services").hasAuthority("SCOPE_services:read")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2ResourceServer ->
oauth2ResourceServer
.jwt(jwt ->
jwt.decoder(JwtDecoders.fromIssuerLocation(issuerUri))
)
);
}
}

Related

How to combine two different configuration files in Spring boot?

I have multiproject Spring application.
Project A - responsible for LDAP authentication
Project B - responsible for Database authentication
Project MAIN - can use both of them or one of them.
If we use only Project A - we have LDAP auth
If we use only Project B - we have JDBC auth
If we use both of them - first goes LDAP auth, if it failures, then goes JDBC auth. And if Project B is included, it adds some filters
Project MAIN does not have #Configuration file, but Projects A and B has it.
Project A #Configuration
#Configuration
#EnableWebSecurity
#Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**адрес сервера LDAP*/
#Value("${ldap.server}")
private String ldapServer;
/**номер порта LDAP сервера*/
#Value("${ldap.port}")
private int ldapPort;
/**домен для LDAP*/
#Value("${ldap.suffix}")
private String suffix;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(adAuthProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests().antMatchers("/**").authenticated()
.and()
.csrf().disable();
}
/**провайдер для аутентификации через LDAP*/
#Bean
public ActiveDirectoryLdapAuthenticationProvider adAuthProvider() {
String ldapUrl = String.format("ldap://%s:%s", ldapServer, ldapPort);
ActiveDirectoryLdapAuthenticationProvider adAuthProvider = new
ActiveDirectoryLdapAuthenticationProvider(suffix, ldapUrl);
adAuthProvider.setConvertSubErrorCodesToExceptions(true);
adAuthProvider.setUseAuthenticationRequestCredentials(true);
return adAuthProvider;
}
}
and Project B Configuration file.
#Configuration
#EnableWebSecurity
public class ECommonConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jdbcAuthProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests().antMatchers("/**").authenticated()
.and()
.csrf().disable();
http.addFilterAt(ldapAuthenticationFilter(), LDAPAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/**").access("#requestAuthorization.checkRequestPermissions(authentication, request)");
}
/**провайдер для аутентификации через базу данных*/
#Bean
public DaoAuthenticationProvider jdbcAuthProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
/**бин для шифрования паролей*/
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**бин для фильтра проверки наличия LDAP-пользователя в базе данных*/
#Bean
public LDAPAuthenticationFilter ldapAuthenticationFilter() throws Exception {
return new LDAPAuthenticationFilter(authenticationManager());
}
#Bean
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
/**бин для инициализации базы данных по умолчанию - описание параметров подключения к БД в файле application.yml*/
#Bean
public DataSource dataSource() {
return datasourceConnectionManager().getDataSource("test");
}
/**бин создания менеджера подключения к нескольким базам данных*/
#Bean
public DatasourceConnectionManager datasourceConnectionManager() {
return new DatasourceConnectionManager();
}
}
I need these two configurations works together or only one oh them
To combine this 2 ways of authentication you can create a custom authentication provider ( more details here: https://www.baeldung.com/spring-security-authentication-provider )
The implementation of the auth provider would look something like this:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private ActiveDirectoryLdapAuthenticationProvider ldapAuthenticationProvider;
private DaoAuthenticationProvider daoAuthenticationProvider;
// env variable to help you choose which auth provider should be enabled
#Value("${ldap.enabled}")
private int ldapEnabled;
// env variable to help you choose which auth provider should be enabled
#Value("${daoAuth.enabled}")
private int daoAuthEnabled;
#Autowired
public CustomAuthenticationProvider(ActiveDirectoryLdapAuthenticationProvider ldapAuthenticationProvider, DaoAuthenticationProvider daoAuthenticationProvider) {
this.ldapAuthenticationProvider = ldapAuthenticationProvider;
this.daoAuthenticationProvider = daoAuthenticationProvider;
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication);
// if both enabled then first try with ldap, if not successful try with dao
if (ldapEnabled && daoAuthEnabled ) {
Authentication authenticate = ldapAuthenticationManager.authenticate(authentication);
if(!authenticate.isAuthenticated()) {
authenticate = ldapAuthenticationManager.authenticate(authentication);
}
return authenticate;
}
// if only ldap enabled
if(ldapEnabled) {
return ldapAuthenticationManager.authenticate(authentication);
}
// if only dao enabled
return daoAuthenticationProvider.authenticate(authentication);
}
#Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
You can use Spring profiling for this. Just Add #Profile annotation along with name on the configuration class as shown below.
Configuration for ProjectA
#Profile("ProjectA")
#Configuration
#EnableWebSecurity
#Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
And Configuration for ProjectB
#Profile("ProjectB")
#Configuration
#EnableWebSecurity
public class ECommonConfig extends WebSecurityConfigurerAdapter {
...
Then at the time of execution of application you can specify active profile by passing following parameter to java.
#In case of need of only ProjectA then
-Dspring.profiles.active=ProjectA
#In case of need of only ProjectB then
-Dspring.profiles.active=ProjectB
#In case of need of both projects then
-Dspring.profiles.active=ProjectA,ProjectB
Same thing you can define in application.properties file with required profile
spring.profiles.active=ProjectA,ProjectB
This way you can dynamically decide which Project configuration should be included.

spring oauth2, unable to retrieve user info

couldn't find a doc which illustrates how to use access_token to get user info.
How can I make a such endpoint?
I see when I access the /user endpoint OAuth2AuthenticationProcessingFilter is not included.
I think I messed up something below
#Configuration
#EnableWebSecurity
#Order(2)
// after ResourceServerConfigurerAdapter
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// https://stackoverflow.com/questions/26387003/how-to-make-spring-boot-never-issue-session-cookie
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/", "index", "/login**", "/webjars/**")
.permitAll()
.and().exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(oAuth2FailedHandler)
.and().csrf().disable().authorizeRequests()
.and().addFilterBefore(new CORSFilter(), BasicAuthenticationFilter.class); }
}
I also have..
#Order(3)
#Configuration
#EnableResourceServer
#Slf4j
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices());
}
#Override
public void configure(HttpSecurity http) throws Exception {
// super.configure(http);
log.info("hello OAuth2ResourceServerConfig:configure");
http
.authorizeRequests().anyRequest().authenticated();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
// JDBC token store configuration
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource());
}
}
#Configuration
//#PropertySource({ "classpath:persistence.properties" }) #EnableAuthorizationServer
#Slf4j
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// ....
}
Add a REST controller with something like this:
#RequestMapping("/user")
public #ResponseBody Principal user(Principal user) {
return user;
}
Then you can call it, using your access token in the Authorization header.

Spring OAuth with JWT - authorization to be performed only based on JWT in authorization server

In my system I use JWT tokens so that authorization of requests could be performed based on JWT only, with no need to call database to fetch roles etc. I use OAuth, and my services are Resource servers which works fine and I'm satisfied with that. The problem I have is with my uaa-service, which is both Authorization and Resource server.
I've noticed that when I send requests to uaa-service I can inject #AuthenticatedPrincipal into my controller method and I have access to all user fields, not only those which are present in JWT. It means that Spring somehow maintains session or maybe in the background fetches user data from database. Here are my settings:
#Configuration
#EnableResourceServer
#Slf4j
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
log.info("Configuring resource server");
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/register").permitAll().anyRequest().authenticated();
}
#Autowired
public void setJwtAccessTokenConverter(JwtAccessTokenConverter jwtAccessTokenConverter) {
jwtAccessTokenConverter.setAccessTokenConverter(bitcoinTokenConverter());
}
#Bean
DefaultAccessTokenConverter bitcoinTokenConverter() {
return new CustomTokenConverter();
}
And
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource(keystoreName), keystorePassword.toCharArray())
.getKeyPair(keystoreAlias);
converter.setKeyPair(keyPair);
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Bean
public DefaultAccessTokenConverter accessTokenConverter() {
return new DefaultAccessTokenConverter();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(customUserDetailsService)
.tokenEnhancer(tokenEnhancerChain);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
and
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Bean
FilterRegistrationBean forwardedHeaderFilter() {
FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
filterRegBean.setFilter(new ForwardedHeaderFilter());
filterRegBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegBean;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/register").permitAll().anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
auth.authenticationEventPublisher(new DefaultAuthenticationEventPublisher(applicationEventPublisher));
}
Where did I make a mistake? In my SecurityConfig.java I have
auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
so that the login could be performed by fetchining user from database and validating password but it looks like it may also cause that incoming requests are not handled only based on JWT.

multiple oauth2 services and configurations

I have an existing Spring application which is using configuration A extending
ResourceServerConfigureAdapter to secure APIs against an internal oauth service A.
I am trying to add another configuration B extending WebSecurityConfigurerAdapter which authenticates against an external oauth provider.
The aim is to continue with B determine authentication for /api/ related endpoints while A determines overall login to the web application.
Following is the existing code using ResourceServerConfigureAdapter:-
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Value("${oauth.clientId}")
private String clientId;
#Value("${oauth.clientSecret}")
private String clientSecret;
#Autowired
private RestTemplate restTemplate;
#Bean
public RemoteTokenServices remoteTokenServices() {
RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setRestTemplate(restTemplate);
remoteTokenServices.setClientId(clientId);
remoteTokenServices.setClientSecret(clientSecret);
remoteTokenServices.setCheckTokenEndpointUrl("srvc://myservice/api/v2/oauth/check_token");
return remoteTokenServices;
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(null);
resources.tokenServices(remoteTokenServices());
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.anonymous()
.and().authorizeRequests()
.antMatchers("/api/secured/**").authenticated()
.antMatchers("/api/**").permitAll();
}}
Following is the code using WebSecurityConfigurerAdapter:-
#SpringBootApplication
#EnableOAuth2Client
#EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class DemoService extends WebSecurityConfigurerAdapter {
#Autowired
OAuth2ClientContext oauth2ClientContext;
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
.logoutSuccessUrl("/").permitAll().and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// #formatter:on
}
public static void main(String[] args) {
SpringApplication.run(DemoService.class, args);
}
#Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter(
"/login/google");
OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(google(), oauth2ClientContext);
googleFilter.setRestTemplate(googleTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(googleResource().getUserInfoUri(),
google().getClientId());
tokenServices.setRestTemplate(googleTemplate);
googleFilter.setTokenServices(
new UserInfoTokenServices(googleResource().getUserInfoUri(), google().getClientId()));
return googleFilter;
}
#Bean
#ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google() {
return new AuthorizationCodeResourceDetails();
}
#Bean
#ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
}
Both of them individually run fine but put together in the same project, problems start showing up. Everything compiles and runs fine but when I hit localhost:8080/ following happens -
The page loads fine but when I hit localhost:8080/login/google, it shows me a whitelabel error page like following
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Apr 06 13:22:27 IST 2017
There was an unexpected error (type=Not Found, status=404).
Not Found
I try to read a bit about ResourceServerConfigureAdapter vs WebSecurityConfigurerAdapter and I could only understand that there is some kind of filter-order that determines the priority of each configurer. But that hasn't helped me fix the issue. Any pointers?
Update:
There's another adapter for Swagger integration that is also part of the project.
#EnableSwagger2
#Configuration
public class SwaggerConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/docs", "/swagger-ui.html");
registry.addRedirectViewController("/docs/", "/swagger-ui.html");
registry.addRedirectViewController("/docs.json", "/v2/api-docs");
}
#Bean
public Docket swaggerSpringMvcPlugin() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("Spring Boot Service")
.description("Sample project documentation")
.contact("a#b.com")
.version("1.0")
.license("Apache")
.build())
.forCodeGeneration(true)
.ignoredParameterTypes(Principal.class)
.useDefaultResponseMessages(false)
.select()
.paths(documentedPaths())
.build();
}
private Predicate<String> documentedPaths() {
return or(
regex("/api.*"));
}
}
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
The OAuth2ClientAuthenticationProcessingFilter must after OAuth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter will throw a redirect exception when the request is wrong(no code, etc...),
and the OAuth2ClientContextFilter will catch it and redirect to the userAuthorizationUri;
The BasicAuthenticationFilter is before OAuth2ClientContextFilter normal, , so you should change the order:
#Autowired
private OAuth2ClientContextFilter oAuth2ClientContextFilter;
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(oAuth2ClientContextFilter, ExceptionTranslationFilter.class)
.addFilterAfter(ssoFilter(), OAuth2ClientContextFilter.class);
}
UPDATE:
There is another place need to be updated, if you have multi chains, you should define the request match, the default value is '/**', and the default order of ResourceServerConfiguration is 3, the default order of WebSecurityConfigurerAdapter is 100, ResourceServerConfiguration has high priority.
// only handle the request start with `/api`
http.requestMatcher(new AntPathRequestMatcher("/api/**"))
http.anonymous()
.and().authorizeRequests()
.antMatchers("/api/secured/**").authenticated()
.antMatchers("/api/**").permitAll();
If you put the WebSecurityConfigurerAdapter before ResourceServerConfiguration by change the order, you should also config the WebSecurityConfigurerAdapter not to handler /api/**
// skip the request start with '/api'
http.requestMatcher(new RegexRequestMatcher("^(?!/api).*$", null))
.authorizeRequests().antMatchers("/", "/login/**", "/webjars/**").permitAll().anyRequest()
Update2:
.authorizeRequests().antMatchers("/", "/login**")
This matcher doesn't match /login/google, please update to /login/**, so it should be
.authorizeRequests().antMatchers("/", "/login/**").permitAll()

Can spring have multiple ConfigurerAdapter?

I need to add OAuth2 security using an ldap authentication.
I have first implemented ldap authenication and add a WebSecurityConfigurerAdapter instance.
#Configuration
#EnableWebSecurity
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource().url("ldaps://master:636/dc=domain,dc=com")
.managerDn("cn=readonly,dc=domain,dc=com").managerPassword("123456")
.and()
.userSearchFilter("(uid={0})");
}
}
I need to add OAuth2 resource server adapter ResourceServerConfigurerAdapter
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
I am playing with both configure() method but I can only get an access login through ldap using http://localhost:8080/login on my Rest API, and couldn't using my angular client using oauth http://localhost:8081/login
I have the following error when trying to access the resource:
Failed to find refresh token for token eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJqb2huIiwic2NvcGUiOlsiZm9vIiwicmVhZCIsIndyaXRlIl0sIm9yZ2FuaXphdGlvbiI6ImpvaG5vRnZiIiwiYXRpIjoiNDcyZTJiNDYtZjgxZS00NGJiLWEwNDMtMGYwZmRjMDMzY2U1IiwiZXhwIjoxNDc2NTQ5NjYzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiN2UwNzRkZDktOWI0ZC00MTU0LWJjMzktMDlkY2U4Y2UyZTg2IiwiY2xpZW50X2lkIjoiZm9vQ2xpZW50SWRQYXNzd29yZCJ9.fuarTPL1O00Yg6b3BPibwux1ZtlmrHaPCJkgjsJni_51B3NEHkdB9kqbABK3IkMWMlZdqY8xfR-zMpY9SxFkpRFDfyvosgLcsTZ...
Handling error: InvalidGrantException, Invalid refresh token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVC...
I have the same issue. May be my solution is not graceful, but it works for me.
I had tried OAuth2ResourceServerConfig which extends WebSecurityConfig and implements ResourceServerConfigurer.
Your OAuth2ResourceServerConfig must be like this
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends WebSecurityConfig implements ResourceServerConfigurer {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
According this post, I think you can use the previous version by adding this to you config(yml or properties):
security:
oauth2:
resource:
filter-order: 3
And I tried adding #Order annotation to my source server config as you did, and get the same issue. So, I think #Order annotation doesn't take effect to ResourceServerConfigurerAdapter, but it works fine with WebSecurityConfig. I don't know is it a bug or intended.

Resources