Spring Basic Auth not working using BCrypt Encoding - I am getting redirected to login popup again even after entering correct credentials - spring

Below is my PasswordEncoder Class
package com.example.springsecuritybasic.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
public class PasswordConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Below is my ApplicationSecurityConfig Class
package com.example.springsecuritybasic.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter{
private final PasswordEncoder passwordEncoder;
#Autowired
public ApplicationSecurityConfig(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","index","/css/*","/js/*")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
#Override
protected UserDetailsService userDetailsService() {
UserDetails annasmithUser = User.builder()
.username("anna")
.password(passwordEncoder.encode("password"))
.roles("STUDENT")
.build();
return new InMemoryUserDetailsManager(
annasmithUser
);
}
}
Below is my Main Class -
package com.example.springsecuritybasic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringsecuritybasicApplication {
public static void main(String[] args) {
SpringApplication.run(SpringsecuritybasicApplication.class, args);
}
}

From the WebSecurityConfigurerAdapter#userDetailsService Javadoc:
Allows modifying and accessing the UserDetailsService from userDetailsServiceBean() without interacting with the ApplicationContext. Developers should override this method when changing the instance of userDetailsServiceBean().
To configure a custom user, you can register a UserDetailsService bean rather than overriding the method
#Bean
protected UserDetailsService userDetailsService() {
UserDetails annasmithUser = User.builder()
.username("anna")
.password(this.passwordEncoder.encode("password"))
.roles("STUDENT")
.build();
return new InMemoryUserDetailsManager(
annasmithUser
);
}

Related

Spring Security -The dependencies of some of the beans in the application context form a cycle

I got error while running this code, there is an injection cycle in the code but I cannot find it. btw, I'm new with Spring.
How can I solve this problem? And any good documentation about it ?
Here is my code;
WebSecurityConfiguration class:
package com.trendyol.app;
import com.trendyol.app.auth.JwtTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true) //Tüm methodlarımızdan önce security devreye girer
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
///////////////////
#Autowired
private JwtTokenFilter jwtTokenFilter;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configurePasswordEncoder(AuthenticationManagerBuilder builder ) throws Exception{
builder.userDetailsService(userDetailsService).passwordEncoder(getBCryptPasswordEncoder());
}
///////////////////
#Bean
public BCryptPasswordEncoder getBCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
#Bean
public AuthenticationManager getAuthenticationManager() throws Exception{
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login") //bu adress hariç
.authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
UserDetailsService:
package com.trendyol.app.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
#Service
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
private Map<String,String > users=new HashMap<>();
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#PostConstruct
public void init(){
users.put("temelt", passwordEncoder.encode("123"));
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(users.containsKey(username)){
return new User(username,users.get(username),new ArrayList<>());
}
throw new UsernameNotFoundException(username);
}
}
LOGs:
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| webSecurityConfiguration (field private org.springframework.security.core.userdetails.UserDetailsService com.trendyol.app.WebSecurityConfiguration.userDetailsService)
↑ ↓
| userDetailsService (field private org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder com.trendyol.app.auth.UserDetailsService.passwordEncoder)
└─────┘

AuthorizationServerConfigurerAdapter cannot be resolved to a type

I have a Spring boot application v 1.5.10 with oauth version 2.0.14
I want to create a configuration file to implement AuthorizationServerConfigurerAdapter interface to generate access token from
package com.razzanati.oauth2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("client")
.secret(passwordEncoder().encode("password"))
.scopes("all")
.authorizedGrantTypes("client_credentials")
.and()
.withClient("client_b")
.secret(passwordEncoder().encode("password_b"));
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(4);
}
}
This is what I've got:
The import org.springframework.security.oauth2 cannot be resolved
AuthorizationServerConfigurerAdapter cannot be resolved to a type
Any idea?

Spring can't load css before login, but after login everything is ok

When I run the app my login page is without images, but when I log in and log out, the login page is styled as it should be.
Can problem be the Security file or something else?
All answers i found are related to the problem where spring won't load CSS at all (.antMatchers(" resources/", "/static/", "/css/", "/js/", "/images/**")) but I don't think this is the same. I couldn't find solution for this.
This is my security file:
package com.example.dnevnikjartest.configuration;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
private AuthenticationSuccessHandler authenticationSuccessHandler;
#Autowired
public SecurityConfiguration(AuthenticationSuccessHandler authenticationSuccessHandler) {
this.authenticationSuccessHandler = authenticationSuccessHandler;
}
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String korisniciQuery;
#Value("${spring.queries.roles-query}")
private String ulogeQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(korisniciQuery).authoritiesByUsernameQuery(ulogeQuery)
.passwordEncoder(bCryptPasswordEncoder).dataSource(dataSource);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/resource/**").permitAll()
.antMatchers("/roditelj/**").hasAuthority("roditelj")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/ucitelj/**").hasAuthority("ucitelj")
.antMatchers("/direktor/**").hasAuthority("direktor")
.anyRequest()
.authenticated().and().csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=true")
.successHandler(authenticationSuccessHandler)
.usernameParameter("username")
.passwordParameter("password").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
}
}
I found a solution to my own question.
I insert this code in the class I mentioned in the question and I created folder images in resource -> static. Previously I have all files images files and .css mixed directly in static without folders.
String[] staticResources = {
"/css/**",
"/images/**",
"/fonts/**",
"/scripts/**",};
This is how whole class looks now
package com.example.dnevnikjartest.configuration;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
private AuthenticationSuccessHandler authenticationSuccessHandler;
#Autowired
public SecurityConfiguration(AuthenticationSuccessHandler authenticationSuccessHandler) {
this.authenticationSuccessHandler = authenticationSuccessHandler;
}
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String korisniciQuery;
#Value("${spring.queries.roles-query}")
private String ulogeQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(korisniciQuery).authoritiesByUsernameQuery(ulogeQuery)
.passwordEncoder(bCryptPasswordEncoder).dataSource(dataSource);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
String[] staticResources = {
"/css/**",
"/images/**",
"/fonts/**",
"/scripts/**",};
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/resource/**").permitAll()
.antMatchers("/roditelj/**").hasAuthority("roditelj")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/ucitelj/**").hasAuthority("ucitelj")
.antMatchers(staticResources).permitAll()
.anyRequest()
.authenticated().and().formLogin().loginPage("/login").failureUrl("/login?error=true")
.successHandler(authenticationSuccessHandler)
.usernameParameter("username")
.passwordParameter("password").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
}

How to make spring-boot 1.5.0 support this oauth2 solution?

I am using spring boot 1.5.0 with java 7 and am using following classes for implementation of Oauth for securing REST API
1) AuthorizationServerConfiguration.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static String REALM="MY_OAUTH_REALM";
#Autowired
private TokenStore tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
int accessTokenMinutesValidity = 60;
int refreshTokenMinutesValidity = 24 * 60;
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "client_credentials", "refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.secret("{noop}secret")
.accessTokenValiditySeconds(60 * accessTokenMinutesValidity ).//Access token is only valid for 60 minutes.
refreshTokenValiditySeconds(60 * refreshTokenMinutesValidity);//Refresh token is only valid for 24 hours
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.allowFormAuthenticationForClients()
.realm(REALM+"/client");
}
}
2) MethodSecurityConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Autowired
private OAuth2SecurityConfiguration securityConfig;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
3) OAuth2SecurityConfiguration.java
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#SuppressWarnings("deprecation")
#Configuration
#EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private DataSource dataSource;
#Primary
#Bean
public DataSource customDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//dataSource properties set here
return dataSource;
}
#Bean
#ConfigurationProperties("spring.datasource")
public DataSource ds() {
return customDataSource();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
PasswordEncoder encoder = NoOpPasswordEncoder.getInstance();
BCryptPasswordEncoder enc;
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select USERNAME, ENC_PASSWD as PASSWORD, IS_ACTIVE AS ENABLED FROM USER_MSTR WHERE USERNAME=?")
.authoritiesByUsernameQuery("select USERNAME, 'ROLE_CLIENT' as ROLE from USER_MSTR where USERNAME=?")
.passwordEncoder(NoOpPasswordEncoder.getInstance())
;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
4) ResourceServerConfiguration.java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.and().authorizeRequests()
.antMatchers("/category_mstr/**", "/equipment/**", "/param_mstr/**", "/chklist_txn/**", "/settings/**", "/user/**")
.access("hasRole('ROLE_CLIENT')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
However when accessing /oauth/token , I am getting error message saying "bad credentials" even when provided proper credentials
However if I use java 8 and spring boot 2.1.5 for same issue, then it runs fine and works as expected.
The old versions it was not necessary to add {noop} then remove it, since the latest versions work by using the password encoder {noop}.

Upgrading to spring-boot 1.4.1 - OAuth2 Security integration tests pass but client apps cannot log in

I have just upgraded an app from spring-boot 1.3.5 to spring-boot 1.4.1
For some reason, all my integration tests pass using oauth2. The test client can register users and perform operations with them during the maven integration test phase.
However when I start up my API server (which also contains the resource and authorization servers currently) clients can no longer get a bearer token.
My ClientDetailsService is never called on client login - but is registered with
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
on application startup.
Any ideas anyone?
Here is the relevant code:
Authorization Server Config:
import javax.inject.Inject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import blablabla.api.security.ClientDetailsServiceImpl;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Inject
private AuthenticationManager authenticationManager;
#Inject
private ClientDetailsServiceImpl clientDetailsService;
#Inject
private UserDetailsService userDetailsService;
public AuthorizationServerConfiguration() {
System.out.println("loaded");
}
// beans
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
// FIXME: Include a more secure key in the java token store
accessTokenConverter.setSigningKey("3434343434");
return accessTokenConverter;
}
#Bean
public TokenStore tokenStore() {
//return new InMemoryTokenStore();
return new JwtTokenStore(accessTokenConverter());
}
// config
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter());
endpoints.userDetailsService(userDetailsService);
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
}
Resource Server Config:
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import blablabla.security_lib.config.UserDetailsServiceImpl;
#Configuration
#EnableResourceServer
#EnableWebSecurity
#ComponentScan("blablabla.api.security")
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Inject
private UserDetailsServiceImpl userDetailsService;
#Inject
private TokenStore tokenStore;
// Beans
#Bean
public TokenStore tokenStore() {
//return new InMemoryTokenStore();
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
accessTokenConverter.setSigningKey("3434343434");
return accessTokenConverter;
}
// global security concerns
#Bean
public AuthenticationProvider authProvider() {
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
return authProvider;
}
#Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authProvider());
}
#Primary
#Bean
public ResourceServerTokenServices getTokenServices () {
DefaultTokenServices services = new DefaultTokenServices();
services.setSupportRefreshToken(true);
services.setTokenStore(tokenStore);
return services;
}
// http security concerns
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().csrf().disable();
/*http
.authorizeRequests().regexMatchers("^/members").anonymous()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable();*/
}
}
A few things I've also noticed - this all might mean something to somebody.
When login does not work (starting up the api and using a client)
The org.springframework.security.web.access.expression.WebExpressionVoter is passed a Collection containing one attribute of type org.springframework.security.web.access.expression.WebExpressionConfigAttribute with the value of
"#oauth2.throwOnError(authenticated)"
When login does work (running an acceptance test)
The org.springframework.security.web.access.expression.WebExpressionVoter is passed a Collection containing one attribute of type org.springframework.security.web.access.expression.WebExpressionConfigAttribute with the value of
"[fullyAuthenticated]"
So this turned out to not be a spring-boot issue at all, but instead some kind of issue that was caused in our gateway server when upgrading from spring-cloud Brixton.M2 release train to Brixton.RELEASE. This is sort of an unhelpful answer to an unhelpful question, so - happy to see this removed from SO.

Resources