How configure Spring boot CORS for Restful API? - spring

I've used thi s guide (https://medium.com/emblatech/secure-your-spring-restful-apis-with-jwt-a-real-world-example-bfdd2679db5f) to secure RestFull API.
But now I've a CORS problem when I try to connect from a REACT JS app.
This is my configuration:
AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Value("${security.jwt.client-id}")
private String clientId;
#Value("${security.jwt.client-secret}")
private String clientSecret;
#Value("${security.jwt.grant-type}")
private String grantType;
#Value("${security.jwt.grant-type-refresh}")
private String grantTypeRefresh;
#Value("${security.jwt.scope-read}")
private String scopeRead;
#Value("${security.jwt.scope-write}")
private String scopeWrite = "write";
#Value("${security.jwt.resource-ids}")
private String resourceIds;
#Autowired
private JwtAccessTokenConverter accessTokenConverter;
#Autowired
private AuthenticationManager authenticationManager;
#Qualifier("userDetailsServiceImpl")
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private DefaultTokenServices defaultTokenServices;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(clientId)
.secret("{noop}"+clientSecret)
.authorizedGrantTypes(grantType, grantTypeRefresh)
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenServices(defaultTokenServices).authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter).userDetailsService(userDetailsService);
}
}
ResourceServerConfig
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
ResourceServerTokenServices tokenServices;
#Value("${security.jwt.resource-ids}")
private String resourceIds;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceIds).tokenServices(tokenServices);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.and()
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/oauth/**").authenticated();
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${security.signing-key}")
private String signingKey;
#Value("${security.security-realm}")
private String securityRealm;
#Value("${security.jwt.token-validity-seconds}")
private int accessTokenValiditySeconds;
#Qualifier("userDetailsServiceImpl")
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName(securityRealm)
.and()
.csrf().disable();
}
#Override
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public TokenEnhancerChain tokenEnhancerChain() {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(new MyTokenEnhancer(), accessTokenConverter()));
return tokenEnhancerChain;
}
#Bean
#Primary
public DefaultTokenServices defaultTokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setTokenEnhancer(tokenEnhancerChain());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
return defaultTokenServices;
}
private static class MyTokenEnhancer implements TokenEnhancer {
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
// TODO Auto-generated method stub
return accessToken;
}
}
}
In every call i do i receive this error:
GET http://localhost:8080/test 401
Access to XMLHttpRequest at 'http://localhost:8080/test' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've also already tride some solution explained here for example: How to configure CORS in a Spring Boot + Spring Security application?
But nothing works for me.
Any help?

You need to add Cors Configuration to your application, so that it can accept AJAX requests from a different domain. Whether such requests are sent by react or angular or jquery, the server will still behave the same way.
The easiest way to accept CORS in your Spring Boot application is to add the following annotation to your Controller classes :
#CrossOrigin(origins="*")
Please beware, however, that when you use the wildcard (*), your service will accept Ajax requests from any domain, which is not secure. You might want to replace the wildcard by the specific domains that you want to accept requests from.
Repeating the annotation in all your controllers might be annoying and error-prone. Instead, you may use one the configuration solutions described in How to configure CORS in a Spring Boot + Spring Security application? or follow Spring documentation about CORS configuration

Related

Spring ouath2Authserver oauth/token returns internal server Error for grant client_credentials

Im trying to implement Authorisation server with password and client_credentials grant
#Configuration
#EnableAuthorizationServer
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
public PasswordEncoder passwordEncoder;
#Autowired
private DataSource dataSource;
#Autowired
private TokenStore jwtTokenStore;
#Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
#Autowired
private TokenEnhancer jwtTokenEnhancer;
#Bean
public TokenEnhancer jwtTokenEnhancer(){
return new JWTokenEnhancer();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer(), jwtAccessTokenConverter));
endpoints
.authenticationManager(authenticationManager)
.tokenStore(jwtTokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
.tokenEnhancer(enhancerChain);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
JdbcClientDetailsServiceBuilder jcsb = clients.jdbc(dataSource);
jcsb.passwordEncoder(passwordEncoder);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(passwordEncoder)
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");
}
}
web config file
Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Resource(name = "userService")
private UserDetailsService userDetailsService;
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api-docs/**").permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
// Allow eureka client to be accessed without authentication
web.ignoring().antMatchers("/*/")//
.antMatchers("/eureka/**")//
.antMatchers(HttpMethod.OPTIONS, "/**"); // Request type options should be allowed.
}
}
#Configuration
public class JwtTokenConfig {
#Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
#Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
accessTokenConverter.setSigningKey("dev");
return accessTokenConverter;
}
}
i have configured client details to pick up from database -
When i try to get access token based on password grant im able to get the access token
but when i try to get access token based on grnat_type client credentials - im getting internal server error .
Please help to check on what is wrong with my implementation.
enter image description here
In your class OAuthConfiguration, check client configuration present in configure(ClientDetailsServiceConfigurer clients) method. It appears that the JDBC client details service is not able to find any client details.
JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
jdbcClientDetailsService.listClientDetails(); // This probably would be empty.
If so, configure JDBC client details service something like this:
clients.jdbc(dataSource).withClient(CLIEN_ID)
.secret(encoder.encode(CLIENT_SECRET))
.authorizedGrantTypes("password", "refresh_token", "client_credentials")
.scopes("read", "write")
.resourceIds(RESOURCE_ID).and().build();
Found the Issue .
public class JWTokenEnhancer implements TokenEnhancer{
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> info = new HashMap<>();
info.put("user-info", "user additional information...");
// User user = (User) authentication.getPrincipal();
// info.put("isAdmin", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()).contains("ROLE_ADMIN"));
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
return accessToken;
}
The commented line was causing the issue as there was no user in case of client_credentials

invalid_token:Cannot convert access token to JSON

I get error while refreshing the token(grant_type=refresh_token). It seems that user did not use the application for long time and both access token as well as refresh token expired. When app now tried to refresh token, it gets the error
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}
I saw many posts on this issue but I am still facing this error. I tried to use setVerifierKey. But no luck. Here is the code:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${security.signing-key}")
private String signingKey;
#Value("${security.encoding-strength}")
private Integer encodingStrength;
#Value("${security.security-realm}")
private String securityRealm;
#Autowired
private UserDetailsService userDetailsService;
#Bean
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
// .passwordEncoder(new ShaPasswordEncoder(encodingStrength));
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName(securityRealm)
.and()
.csrf()
.disable();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
#Primary //Making this primary to avoid any accidental duplication with another token service instance of the same name
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
//AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Value("${security.jwt.client-id}")
private String clientId;
#Value("${security.jwt.client-secret}")
private String clientSecret;
#Value("${security.jwt.grant-type}")
private String grantType;
#Value("${security.jwt.scope-read}")
private String scopeRead;
#Value("${security.jwt.scope-write}")
private String scopeWrite = "write";
#Value("${security.jwt.resource-ids}")
private String resourceIds;
#Autowired
private TokenStore tokenStore;
#Autowired
private JwtAccessTokenConverter accessTokenConverter;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(clientId)
.secret(clientSecret)
.authorizedGrantTypes("client_credentials", "password", "refresh_token", "authorization_code")
.scopes(scopeRead, scopeWrite)
// .accessTokenValiditySeconds(60)
// .refreshTokenValiditySeconds(2000)
.resourceIds(resourceIds);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
endpoints.tokenStore(tokenStore)
.accessTokenConverter(accessTokenConverter)
.tokenEnhancer(enhancerChain).userDetailsService(userDetailsService)
.authenticationManager(authenticationManager);
}
}
I expect that token will be refreshed but I get the error as mentioned above. my config properties are:
security.oauth2.resource.filter-order=3
security.signing-key=ZMaasazkSjmaasw
security.encoding-strength=256
security.security-realm=Spring Boot JWT Example Realm
security.jwt.grant-type=password security.jwt.scope-read=read
security.jwt.scope-write=write
security.jwt.resource-ids=testjwtresourceid
Any Help appreciated!!

Spring Boot OAuth doesn't return a refresh token for clients

I have an API that I've developed in Spring Boot, and I've just noticed that it's not returning a refresh token when you request an access token.
The response from the API looks like this;
{
"access_token": "ed0bdc62-dccf-4f58-933c-e28ad9598843",
"token_type": "bearer",
"expires_in": 2589494,
"scope": "read write"
}
My configuration looks like this;
#Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "myapi";
#Autowired
DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
TokenStore tokenStore;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/**", "/view/**").permitAll()
.anyRequest().authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
#Autowired
private DataSource dataSource;
#Autowired
private TokenStore tokenStore;
#Autowired
private CustomUserDetailsService userDetailsService;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.jdbc(dataSource);
}
}
}
I previously had the project setup to use JWT for access tokens and that did return a refresh token, however I had to remove JWT as it wasn't compatible with using the token store.
To confirm, it returns a refresh token when the grant_type = password, but not when it's set to 'client_credentials'.
Does anyone have any suggestions why my configuration doesn't return a refresh token?
4.3.3. Access Token Response in RFC 6749 (The OAuth 2.0 Authorization Framework) says "A refresh token SHOULD NOT be included." Therefore, most implementations of OAuth 2.0 authorization servers do not generate a refresh token in Client Credentials flow.
I got the same issue, then I changed in this method, I added REFRESH_TOKEN then in the response I am getting refresh_token value.
static final String REFRESH_TOKEN = "refresh_token";
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(CLIENT_ID)
.secret(messageDigestPasswordEncoder.encode(CLIENT_SECRET))
.authorizedGrantTypes(GRANT_TYPE,REFRESH_TOKEN)
.scopes(SCOPE_READ, SCOPE_WRITE ,TRUST)
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS).
refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS);
}

How to make requests to an endpoint to be authorised by client id and secret in Spring?

By default when OAuth2 authorisation is enabled in Spring framework (see the configuration below) and we make a call to /oauth/token to issue an access token, the following request is being sent:
POST /oauth/token
Authorization: Basic Y34tcF9ib3VpOg==
POST data:
grant_type=password&username=myuser&password=mypass
The basic authorisation above is client-id and client's secret in the following form:
myclient:secret123
I can then send this request to Spring's /oauth/check_token:
POST /oauth/check_token
Authorization: Basic Y34tcF9ib3VpOg==
POST data:
token=the_token_retrieved_from_last_request
This works fine and it does basic authorisation before serving my request.
Note that the basic authorisation here goes to Spring's JdbcClientDetailsService in which it looks up a table named oauth_client_details, this is fine too.
Now for some reason I need to have a customised endpoint instead of Spring's /token/check_access. So I have created a controller similar to the Spring's CheckTokenEndpoint.java and named it TokenIntrospectionEndpoint. The URL pattern for my endpoint is set to be /oauth/introspect:
#Controller
#RequestMapping("/oauth")
public class TokenIntrospectionEndpointImpl {
private RestTemplate restTemplate;
#RequestMapping(value = "/introspect")
#ResponseBody
#Override
public Map<String, ?> introspect(#RequestParam("token") String token) {
// return data
}
}
Now the problem is, the request to this endpoint is being served without considering basic authorisation. So I've added this line in the configuration:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/oauth/introspect").access("isAuthenticated()");
}
Now Spring security kicks in but it doesn't treat this request the same way it does for /oauth/check_token and by that I mean it doesn't look up table oauth_client_details automatically just like the same way it does for other oauth related requests. As such, I get 401 http error code.
I think I am missing something here to tell Spring that this is oauth2 request so that it considers client-id/secret and authenticate it automatically. Any hint would be appreciated.
My configurations:
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorisationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private MySecuritySettings securitySetting;
#Autowired
private DataSource dataSource;
#Autowired
private JdbcTemplate jdbcTemplate;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//TODO I'd rather not to override Spring's endpoint URL but had issues with authentication.
.pathMapping("/oauth/check_token", "/oauth/introspect").tokenStore(this.tokenStore())
.authenticationManager(authenticationManager)
.tokenServices(tokenServices())
.accessTokenConverter(tokenConverter())
.requestValidator(createOAuth2RequestValidator());
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(myClientDetailsService());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.checkTokenAccess("isAuthenticated()")
.tokenKeyAccess("permitAll()")
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Bean
public MyClientDetailsService myClientDetailsService(){
MyClientDetailsService myClientDetailsService = new MyClientDetailsService(dataSource);
myClientDetailsService.setPasswordEncoder(passwordEncoder());
return myClientDetailsService;
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(tokenConverter());
}
#Bean
public JwtAccessTokenConverter tokenConverter() {
final JwtAccessTokenConverter jwtAccessTokenConverter = new CompJwtAccessTokenConverter();
DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
defaultAccessTokenConverter.setUserTokenConverter(new CompPrincipalExtractor());
jwtAccessTokenConverter.setAccessTokenConverter(defaultAccessTokenConverter);
KeyPair keyPair = new KeyStoreKeyFactory(
new ClassPathResource(securitySetting.getKeystoreFileName()),
securitySetting.getStorepass().toCharArray())
.getKeyPair(securitySetting.getKeyAlias(),
securitySetting.getKeypass().toCharArray());
jwtAccessTokenConverter.setKeyPair(keyPair);
return jwtAccessTokenConverter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(securitySetting.isRefreshAccessToken());
tokenServices.setReuseRefreshToken(securitySetting.isReuseRefreshToken());
tokenServices.setTokenEnhancer(tokenConverter());
tokenServices.setAccessTokenValiditySeconds(securitySetting.getAccessTokenValiditySeconds());
return tokenServices;
}
#Bean
#Primary
public OAuth2RequestValidator createOAuth2RequestValidator() {
return new ExpressionBasedOAuth2RequestValidator();
}
}
AND this:
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "auth_serv";
#Autowired
TokenStore tokenStore;
#Autowired
MySecuritySettings mySecuritySettings;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/oauth/introspect").access("isAuthenticated()")
.and()
.authorizeRequests()
.antMatchers("/api/**/*").access("#oauth2.hasScope('" + mySecuritySettings.getAuthserverScopenameAllAccess() + "')");
}
}

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.

Resources