I have a simple-as-possible OAuth2 JWT Spring Boot 2.7.3 project that works perfectly. It's easy to setup and run as described in the README from Github repository.
Besides Spring Security, the project uses spring-security-oauth2:
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
Then defines some beans:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Value("${jwt.secret}")
private String jwtSecret;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
tokenConverter.setSigningKey(jwtSecret);
return tokenConverter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
And an Authorization Server:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String clientSecret;
@Value("${jwt.duration}")
private Integer jwtDuration;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Autowired
private JwtTokenStore tokenStore;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(clientId)
.secret(passwordEncoder.encode(clientSecret))
.scopes("read", "write")
.authorizedGrantTypes("password")
.accessTokenValiditySeconds(jwtDuration);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.accessTokenConverter(accessTokenConverter);
}
}
And a Resource Server:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${cors.origins}")
private String corsOrigins;
@Autowired
private Environment env;
@Autowired
private JwtTokenStore tokenStore;
private static final String[] PUBLIC = { "/oauth/token", "/h2-console/**" };
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// H2
if (Arrays.asList(env.getActiveProfiles()).contains("test")) {
http.headers().frameOptions().disable();
}
http.authorizeRequests()
.antMatchers(PUBLIC).permitAll()
.anyRequest().authenticated();
http.cors().configurationSource(corsConfigurationSource());
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
String[] origins = corsOrigins.split(",");
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOriginPatterns(Arrays.asList(origins));
corsConfig.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "DELETE", "PATCH"));
corsConfig.setAllowCredentials(true);
corsConfig.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return source;
}
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> bean
= new FilterRegistrationBean<>(new CorsFilter(corsConfigurationSource()));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
Now I'm trying to upgrade it to Spring Boot 3.0.0-SNAPSHOT, but the project is throwing BeanCreationException: Error creating bean with name 'authorizationEndpoint'. The stack trace shows it's caused by ClassNotFoundException: javax.servlet.ServletException.
How to fix that?