spring oauth2, unable to retrieve user info - spring

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.

Related

Spring Boot Resource Server Invalid Access Token

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))
)
);
}
}

Unauthorized error while passing access_token to the REST Call

I have obtained the access token using appropriate endpoint using okta. using the obtained access token i am trying to make a REST call by passing access token as Authorization Header type Bearer. but getting 401 unauthorized error with the following error message
"Full authentication is required to access this resource"
AuthorizationServerConfig.java
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
static final String CLIENT_SECRET = "fXMuUOUo31nNlbnnjn64019h3JP-s6VZEOV4VGW1";
static final String CLIENT_ID = "0oaz4m4njwGDMqXB1356";
#Autowired
private TokenStore tokenStore;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer.inMemory()
.withClient(CLIENT_ID)
.secret(CLIENT_SECRET)
.authorizedGrantTypes(new String[] { "password", "refresh_token", "authorization_code" })
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(3600);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("as466gf");
return converter;
}
/**
* Bean for Token Servers Primary is added as there are three token services in the classpath
*
* #return DefaultTokenServices Default Token Service
*/
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
ResourceServerConfig.java
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/authenticate/**").permitAll()
.antMatchers("/user/greet/**").permitAll()
.antMatchers("/user/getRefreshedTokens/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("ResourceId");
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* OAuth ignores the configuration below
*
* #See ResourceServerConfig to control Authorization
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/authenticate/**").permitAll()
.antMatchers("/user/greet/**").permitAll()
.antMatchers("/user/getRefreshedTokens/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}

Spring OAuth security - Implicit flow

Is it possible to implement OAuth implicit flow with spring security? I want to create both auth and resource server in the same application. I need standard auth endpoints for authentication and authorization and some custom endpoints for handling with users (create/update/list...).
Requirements:
implicit flow
custom login page (/my_login_page)
silent mode for obtaining token (/oauth/authorize?...&prompt=none)
secured custom endpoints with OAuth (/users)
I'm stuck with configuration. Whatever I do, the requirements above never work together.
Spring WebSecurityConfig
#Configuration
#Order(-10)
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private MyAuthenticationProvider authenticationProvider;
private MyAuthenticationDetailsSource authenticationDetailsSource;
#Autowired
public SecurityConfig(MyAuthenticationProvider authenticationProvider, MyAuthenticationDetailsSource authenticationDetailsSource) {
this.authenticationProvider = authenticationProvider;
this.authenticationDetailsSource = authenticationDetailsSource;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.sessionFixation().newSession()
.and()
.authorizeRequests()
.antMatchers("/assets/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**", "/v2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/my_login_page")
.loginProcessingUrl("/my_process_login")
.usernameParameter("my_username")
.passwordParameter("pmy_assword")
.authenticationDetailsSource(authenticationDetailsSource)
.permitAll();
}
}
Spring AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private ResourceLoader resourceLoader;
private AuthProps authProps;
#Autowired
public OAuth2AuthorizationServerConfig(ResourceLoader resourceLoader, AuthProps authProps) {
this.resourceLoader = resourceLoader;
this.authProps = authProps;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
#Qualifier("jwtAccessTokenConverter")
public JwtAccessTokenConverter accessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resourceLoader.getResource(authProps.getAuthServerPrivateCertPath()), authProps.getAuthServerPrivateCertKey().toCharArray());
JwtAccessTokenConverter converter = new MYJwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory
.getKeyPair(authProps.getAuthServerPrivateCertAlias()));
final Resource resource = resourceLoader.getResource(authProps.getAuthServerPublicCertPath());
String publicKey;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-secured-client")
.secret("foo")
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.resourceIds("my-resource")
.authorities("CLIENT")
.redirectUris(
"http://localhost:4200"
)
.accessTokenValiditySeconds(300)
.autoApprove(true);
}
}
Spring ResourceServerConfig
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private AuthProps authProps;
private TokenStore tokenStore;
private DefaultTokenServices tokenServices;
#Autowired
public OAuth2ResourceServerConfig(AuthProps authProps, TokenStore tokenStore, DefaultTokenServices tokenServices) {
this.authProps = authProps;
this.tokenStore = tokenStore;
this.tokenServices = tokenServices;
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config
.resourceId("my-resource")
.tokenStore(tokenStore)
.tokenServices(tokenServices);
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/**").authenticated()
.and()
.csrf().disable();
}
}
I placed WebSecurityConfig before ResourceServerConfig otherwise login page doesn't work. But now I can't access my custom endpoint for users (I'm redirected to the login page). If I place ResourceServerConfig before WebSecurityConfig login page stop working. I get 404 not found response when I submit login page form.
I also have an issue with silent mode to obtain a new access token. When calling /oauth/authorize with still valid access_token I'm redirected to the login page.
Finally I found a solution:
ResourceServerConfig have to be before WebSecurityConfig
loginProcessingUrl should be /oauth/authorize
Silent refresh works by default until session is valid (login form)
Custom endpoint for logout where invalidate current session
EDITED:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private MyAuthenticationProvider authenticationProvider;
private MyAuthenticationDetailsSource authenticationDetailsSource;
#Autowired
public SecurityConfig(MyAuthenticationProvider authenticationProvider, MyAuthenticationDetailsSource authenticationDetailsSource) {
this.authenticationProvider = authenticationProvider;
this.authenticationDetailsSource = authenticationDetailsSource;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.authenticationProvider(authenticationProvider);
}
#Override
public void configure(WebSecurity web) {
web
.debug(true)
.ignoring()
.antMatchers(HttpMethod.OPTIONS)
.antMatchers("/my-custom-login-page", "/my-custom-logout-page")
.antMatchers("/assets/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**", "/v2/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/my-custom-login-page")
.loginProcessingUrl("/oauth/authorize")
.usernameParameter("myUsernameParam")
.passwordParameter("myPasswordParam")
.authenticationDetailsSource(authenticationDetailsSource)
.permitAll()
.and()
.csrf().disable();
}
}
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private ResourceLoader resourceLoader;
private AuthProps authProps;
#Autowired
public OAuth2AuthorizationServerConfig(ResourceLoader resourceLoader, AuthProps authProps) {
this.resourceLoader = resourceLoader;
this.authProps = authProps;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
#Qualifier("jwtAccessTokenConverter")
public JwtAccessTokenConverter accessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resourceLoader.getResource(authProps.getAuthServerPrivateCertPath()), authProps.getAuthServerPrivateCertKey().toCharArray());
JwtAccessTokenConverter converter = new MyJwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory.getKeyPair(authProps.getAuthServerPrivateCertAlias()));
final Resource resource = resourceLoader.getResource(authProps.getAuthServerPublicCertPath());
String publicKey;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(authProps.getAuthServerClientId())
.secret(authProps.getAuthServerClientSecret())
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.resourceIds(authProps.getAuthServerResourceId())
.authorities("CLIENT")
.redirectUris(
"http://localhost:4200/#/login",
"http://localhost:4200/assets/silent-refresh.html",
"http://localhost:8080/my-api/webjars/springfox-swagger-ui/oauth2-redirect.html"
)
.accessTokenValiditySeconds(authProps.getAuthServerAccessTokenValiditySeconds())
.autoApprove(true);
}
}
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private AuthProps authProps;
private TokenStore tokenStore;
private DefaultTokenServices tokenServices;
#Autowired
public OAuth2ResourceServerConfig(AuthProps authProps, TokenStore tokenStore, DefaultTokenServices tokenServices) {
this.authProps = authProps;
this.tokenStore = tokenStore;
this.tokenServices = tokenServices;
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.resourceId(authProps.getAuthServerResourceId()).tokenStore(tokenStore);
config.resourceId(authProps.getAuthServerResourceId()).tokenServices(tokenServices);
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().hasRole(AppRole.ROLE_APP_USER.split("ROLE_")[1])
.and()
.csrf().disable();
}
}
#Controller
public class MainController {
#Autowired
public MainController() {
...
}
#GetMapping("/my-custom-login-page")
public ModelAndView loginPage(HttpServletRequest request, HttpServletResponse response) {
ModelAndView mv = new ModelAndView("login-page");
return mv;
}
#GetMapping("/my-custom-logout-page")
public ModelAndView logoutPage(HttpServletRequest request) {
ModelAndView mv = new ModelAndView("logout-page");
HttpSession session = request.getSession(false);
if (Objects.isNull(session)) {
mv.addObject("msg", "NO SESSION");
return mv;
}
session.invalidate();
mv.addObject("msg", "SUCCEEDED");
return mv;
}
}
In addition to #user3714967 answer, I add some tips maybe It helps someone. The problem is that we are defining multiple HttpSecurity (The resourceServer is a WebSecurityConfigurerAdapter with order 3). The solution is to use HttpSecurity.requestMatchers() with the specific value.
Example
First Class:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("url1", "url2", ...).and()
.authorizeRequests()
.antMatchers(...).and()...
}
}
Second Class:
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("url3", "url4", ...)
.and()
.authorizeRequests()
.antMatchers(...).and()...
}
}
}
This will be useful when we have more than flow (password && implicit flows for my case).

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.

Spring Security Custom Authfilter doesnt work

i am working in a personal project and i using spring web mvc and spring security 4, all annotation based configs, and my custom UsernamePasswordAuthenticationFilter is never reached, i am losing it, i already search but i can get it solved, so if anyone could help, i 'd be very grateful, So here is my code
Spring Initialization
#Order(1)
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{AppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Security Initialization
#Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
Spring beans declarations and context stuff
#EnableWebMvc
#Configuration
#ComponentScan({"app","server"})
#Import({ SecurityContext.class })
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/META-INF/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setSuffix(".jsp");
resolver.setPrefix("/WEB-INF/views/");
resolver.setContentType("text/html; charset=UTF-8");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean
public DriverManagerDataSource dataSource(){
DriverManagerDataSource driver = new DriverManagerDataSource();
driver.setDriverClassName("com.mysql.jdbc.Driver");
driver.setUrl("jdbc:mysql://localhost:3306/dberp-1");
driver.setUsername("root");
driver.setPassword("123456");
return driver;
}
#Bean
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean session = new LocalSessionFactoryBean();
session.setDataSource(dataSource());
String[] pakages = {"model"};
session.setPackagesToScan(pakages);
Properties prop = new Properties();
prop.put("dialect", MySQLDialect.class);
session.setHibernateProperties(prop);
return session;
}
}
I am almost sure i am doing something wrong in this SecurityContext class....
#Configuration
#EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint())
.and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login","/resources/**").anonymous()
.antMatchers("/users").hasAuthority("admin")
.antMatchers("/**").hasAnyAuthority("employee","admin")
.and()
.logout()
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.and()
.csrf().disable();
}
#Bean
public AuthenticationEntryPoint authenticationEntryPoint(){
AuthenticationEntryPoint entryAuth = new LoginUrlAuthenticationEntryPoint("/login");
return entryAuth;
}
#Bean(name="customAuthenticationManager")
#Override
protected AuthenticationManager authenticationManager() throws Exception {
AuthenticationManager authManager = new CustomAuthenticationManager();
return authManager;
};
#Bean
public UsernamePasswordAuthenticationFilter authenticationFilter() throws Exception{
/*UsernamePasswordAuthenticationFilter authFilter = new UsernamePasswordAuthenticationFilter();
authFilter.setAuthenticationManager(authenticationManager());
authFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/home"));
authFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));*/
UsernamePasswordAuthenticationFilter authFilter = new AuthFilter();
authFilter.setAuthenticationManager(authenticationManager());
authFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/home"));
authFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));
authFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
return authFilter;
}
}

Resources