I am using Spring Security for basic authentication to secure my REST APIs.
Below is the configuration code:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("admin");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated();
}
}
I am getting forbidden (403) error on authenticating myself using the correct username and password.
Please suggest the modifications to get it working.
You haven't enabled HTTP Basic Authentication you have to use HttpSecurity.httpBasic()
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication().withUser("user").password("password").roles("admin");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
Updated
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().httpBasic().and().authorizeRequests().anyRequest().authenticated();
}
Related
I'm using OAuth2 for authorization and I don't find usage of the configure(HttpSecurity http) override in WebSecurityConfigurerAdapter, since it's not executed at all, because ResourceServerConfigurerAdapter has priority over it.
The order of execution is: AuthorizationServerConfigurerAdapter -> ResourceServerConfigurerAdapter -> WebSecurityConfigurerAdapter. It can manually be changed by #Order but it somehow breaks the tokens, so I would rather not to.
Let's say I comment everything in ResourceServerConfigurerAdapter and then try to access /api/topics. In that case I'm going to get the following message:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
It means that the rules I have in WebSecurityConfigurerAdapter, are not executed at all, even tho I have .antMatchers("/api/topics/**").permitAll(). What's the point? What's the proper way of allowing /api/** and authorizing anything else?
By the way, I'm using spring-security-oauth2-autoconfigure#2.2.6.RELEASE.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
private UserDetailsServiceImpl userDetailsService;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/topics/**").permitAll()
.antMatchers("/api/users/**").permitAll()
.antMatchers("/oauth/token**", "/oauth/authorize**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated();
}
}
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Value("${oauth.clientId}")
private String clientId;
#Value("${oauth.clientSecret}")
private String clientSecret;
#Value("${oauth.accessTokenValidity}")
private int accessTokenValidity;
#Value("${oauth.refreshTokenValidity}")
private int refreshTokenValidity;
#Autowired
private TokenStore tokenStore;
#Autowired
#Qualifier("userDetailsService")
private UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(clientId)
.secret(bCryptPasswordEncoder.encode(clientSecret))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.autoApprove(true)
.scopes("read", "write", "trust")
.accessTokenValiditySeconds(accessTokenValidity)
.refreshTokenValiditySeconds(refreshTokenValidity);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.userDetailsService(userDetailsService)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer auth) throws Exception {
auth
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
I found the answer myself. WebSecurityConfigurerAdapter.configure is supposed to have the configuration for authentication like login page, error page, etc. As for ResourceServerConfigurerAdapter.configure, it applies rules about to the REST API.
The reason that WebSecurityConfigurerAdapter was not working for me, is because WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter configurations are chained. Remember their order? Authentication Server -> Resource Server -> Web Security. In my case, I had .anyRequest().authenticated() in ResourceServerConfigurerAdapter.configure which basically authenticated all requests after that, so it couldn't reach WebSecurityConfigurerAdapter at all.
I also added .antMatcher("/api/users**") in ResourceServerConfigurerAdapter.configure to restrict that rule only to /api/users.
Here is the "broken code":
// WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/topics/**").permitAll()
.antMatchers("/api/users/**").permitAll()
.antMatchers("/oauth/token**", "/oauth/authorize**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
// ResourceServerConfigurerAdapter
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.anyRequest().authenticated();
}
Here is a working example:
// WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/oauth2/keys").permitAll()
.anyRequest().authenticated();
}
// ResourceServerConfigurerAdapter
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/users**") // that particular line applies the rule only for /api/users
.authorizeRequests()
.antMatchers("/api/users**").permitAll();
}
Since you registring many SecurityFilterChain(Interceptors) by the configuration of AuthorizationServer and ResourceServer the priority of execution that WebSecurityConfigurerAdapter had was lost in order to achieve everything working properly you have to set on your SecurityConfig:
#Order(1)
#Override
protected void configure(HttpSecurity http) throws Exception {
//... custom code
}
In ResourceServerConfiguration is very important to write http.requestMatchers().antMatchers rather than just http.authorizeRequests().antMatchers cause this allow the filters can work properly each other, having ResourceServerConfiguration priority over SecurityConf respect to endpoints "/api/**"
private static final String ANT_MATCHER_API = "/api/**";
#Order(2)
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers(ANT_MATCHER_API).and()
.authorizeRequests().antMatchers(ANT_MATCHER_API).access("#oauth2.hasScope('read')").and()
.authorizeRequests().antMatchers(ANT_MATCHER_API).access("#oauth2.hasScope('write')")
.and()
.exceptionHandling()
//... custom code
}
BTW the error:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
is an error of the Oauth2 filter chain
I use Oauth and want to create user but have error
POST http://localhost:4200/proxy/user/createUser 401 (Unauthorized)
In spring i have some configuration
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/createUser", "/user/**", "/user/createUser", "proxy/user/createUser").permitAll();
http.csrf().disable();
http.formLogin().disable();
http.authorizeRequests().anyRequest().authenticated();
}
}
and
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/createUser", "/register", "/token", "/token/createUser", "proxy/user/createUser").permitAll();
http.requestMatchers()
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
What configuration changes are required to enable access to ../createUser?
looks like http.authorizeRequests().anyRequest().authenticated() this is creating problem in code. just change in WebSecurity as
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/createUser", "/user/**", "/user/createUser", "proxy/user/createUser")
.permitAll()
.formLogin().disable();
}}`
AND
change in ResourceServerConfig as
http.authorizeRequests()
.antMatchers("/createUser", "/register", "/token", "/token/createUser",
"proxy/user/createUser")
.permitAll();
for details checkout Security-config.
This is the JSON that I returned after logging in:
{
"access_token":"41208e01a-f26c-4167-9fc9-d16730022056",
"token_type": "bearer",
"refresh_token": "3808e00a-896c-8067-18c9-736730022032",
"expires_in": 25348,
"scope": "read write",
"jti": "6f08e00a-d26c-4067-8fc9-c16730022028"
}
I want to get current user information by using this url:https://localhost:8080/user/getuserinfo?access_token=41208e01a-f26c-4167-9fc9-d16730022056 from android client,i meant that how to implement requirement on server and this is my Configuration:how can i use spring security & oauth2 to realize the purpose about redirecting to different login pages when user use different terminal browser?
I change my spring SecurityConfig,here is used to processing some authorizeUrls:
#Configuration
#Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends GlobalAuthenticationConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
//doing jdbc Authentication
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
#Configuration
#Order(1)
public static class ClientSecurityConfigurationAdapter extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/mobile/**")
.formLogin().loginPage("/client/login")
.loginProcessingUrl("/oauth/login")
.successHandler(clientLoginSuccessHandler).permitAll()
.and()
.logout()
.logoutSuccessHandler(clientLogoutSuccessHandler)
.logoutUrl("/client/logout")
.logoutSuccessUrl("/client/login")
.invalidateHttpSession(true);
}
}
#Configuration
#Order(2)
public static class WebSecurityConfigurerAdapter extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.regexMatcher("/((?!api).)*")
.formLogin()
.loginPage("/web/login")
.loginProcessingUrl("/oauth/login")
.successHandler(loginSuccessHandler)
.permitAll()
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
.logoutUrl("/web/logout")
.logoutSuccessUrl("/web/login")
.invalidateHttpSession(true);
}
}
}
and add ResourceServerConfig for handle token validation issues:
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
TokenStore tokenStore;
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/api/**").//
and().authorizeRequests().antMatchers("/api/**",).authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("openid").tokenStore(tokenStore);
}
}
finally,build a request with a request header
"Authorization:Bearer <access_token>"
If I am using spring security to connect to ldap when I connect lets say to the url: www.serverAdress/myapp/
I should be redirected to
www.serverAdress/myapp/login
but instead I am redirected to
www.serverAddress/myappmyapp/login
I am not sure how the extra myapp is added it is also obtained if a redirect is used within the return of the views.
Edit added the configuration
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider authenticationProvider = new ActiveDirectoryLdapAuthenticationProvider("domain", "ldap://url", "rootDN custom");
authenticationProvider.setSearchFilter("customfilter");
authenticationProvider.setConvertSubErrorCodesToExceptions(true);
authenticationProvider.setUseAuthenticationRequestCredentials(true);
return authenticationProvider;
}
}
I have a Spring-Boot app with the actuator and security starter dependencies.
I want to secure the actuator-endpoints with HTTP-basic-auth.
The following code works as intended, IF the mangagment.port is the default one.
But I want to set this property to mangagment.port=9000.
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").fullyAuthenticated()
.and()
.httpBasic()
.and()
.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("4321").roles("USER", "ADMIN");
}
}
How can I secure differnt ports?
Do I have to use a port-mapper as following and if so, does that have any security concerns?
.portMapper()
.http(9090).mapsTo(9443)
.http(80).mapsTo(443);