Securing app with Spring Security doesn't work - java

I wrote a simple backend software and I wanted to secure it with Spring Security and LDAP. It is obvious that LDAP part of the project works fine. the problem is that when I use the formLogin() for entring, that doesn't work and when I use postman it shows the result without asking user name and password! I think something in mywebSecurityConfig is wrong. this is my webSecurityConfig code:
#Configuration public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().fullyAuthenticated();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=people")
.contextSource()
.url("ldap://localhost:10389/dc=example,dc=com")
.and()
.passwordCompare()
.passwordEncoder(new LdapShaPasswordEncoder() {
})
.passwordAttribute("userPassword");
} }

Use #EnableWebSecurity to enable Spring Security.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
and remove .antMatchers("/**").permitAll() from your configuration as it matches all the requests. This construct is normally used to specify specific whitelisted endpoints like static documentation that does not require security:
.antMatchers("/docs/**").permitAll()

Related

How can I use roles in Spring?

In my application I have these roles:
Guest, User, Owner and Admin
I would like to use some kind of authorization where Admin can use all of the endpoints, while Owner can use all the functions that a User have. How should I achive this? What are good pratices?
If you have your securityConfig file setup and everything then all you need to do is permit access to different pages by different user roles, you do it as follow in your SecurityConfig class:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
As you can see, home page is accessed by any user with ROLE_ADMIN or normal user (USER_ROLE) roles...
If you see the adminPage can only be accessed by users with ROLE_ADMIN roles...
You can use methods security. First of all, you need to enable method security, you can do this:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true) //THIS IS THE KEY
public class SecurityConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
}
}
After enable, you can easily use security by method and user, like this:
#GetMapping("/ativas")
#PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_USER') and #oauth2.hasScope('read')")
public List<YourObject> findAll(){
return service.findAll();
}
This is a short answer.
First add Spring Security dependency to your pom.xml. Now use a class to configure Spring security by extending webSecurityConfigurerAdapter. Make sure you add #Configuration and #EnableWebSecurity annotations. Have a look at code below. This should help.
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(id).password("{noop}" + pwd).roles("USER").and().withUser(admin_id).password("{noop}" + admin_pwd).roles("ADMIN", "USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
csrf().disable().authorizeRequests().antMatchers("/**").hasRole("ADMIN").
and().httpBasic();
}

Spring Boot 2.0 / OAuth2 / JWT / Zuul / Microservices

I'm trying to build a microservice architecture. But i'm struggling since two days with OAuth2 and Zuul. I managed to run a Auth/Resource-Server on the same service, but not with Zuul. At the moment i'm swichting to another service, the authorization doesn't work anymore. I tried many guides (as an example Baeldung) but no one works for me. Probably because i'm using Spring Boot 2.0.3? Most guides using Spring Boot 1.5.x.
I think it's a problem of configuration. I'm using Eureka for service discovering, Zuul as Gateway and entry point. When the user request a protected service, he should be redirectet to my auth-service (OAuth2/JWT). The token he gets after login should be stored by Zuul (right ?). Actually Zuul doesn't get the token or doesn't store it. Do I have to do this by my own or should Zuul and OAuth manage this and I just have bad configurations? Could someone show me, how you configure this architecture or a new/working guide for Spring Boot 2.0.3? I'm actually really frustrated, need help. I'm new to Spring, but have to learn it for work. But at the moment i'm just overstrained.
Additional infos:
I didnt create any views now. I just defined some default controller which return Strings and are secured by #PreAuthorize.
Gateway-Service:
GatewayServiceApplication.java
#SpringBootApplication
#EnableZuulProxy
#EnableDiscoveryClient
#Configuration
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
}
SecurityConfig.java
#Configuration
#EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.httpBasic().disable()
.authorizeRequests()
.antMatchers("/", "/core/", "/core/login**", "/oauth/authorize",
"/core/oauth/authorize", "/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin().permitAll();
}
}
Here I had a lot of different antMatchers.
application.properties
server.port=8000
spring.application.name=gateway-service
eureka.client.service-url.defaultZone=http://localhost:8001/eureka/
security.oauth2.sso.login-path=http://localhost:8000/core/login
security.oauth2.client.client-id=zuul
security.oauth2.client.client-secret=zuul
security.oauth2.client.access-token-uri=http://localhost:8000/core/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8000/core/oauth/authorize
#security.oauth2.resource.user-info-uri=http://localhost:8000/core/user/me
security.oauth2.resource.user-info-uri=http://localhost:8000/core/secured
spring.thymeleaf.cache=false
I think here's a failure.
Core-Service
CoreApplication.java
#SpringBootApplication
#EnableDiscoveryClient
#EnableResourceServer
public class CoreApplication {
public static void main(String[] args) {
SpringApplication.run(CoreApplication.class, args);
}
}
AuthServerConfig
#Configuration
#EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Override
public void configure(
AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("zuul")
.secret(passwordEncoder.encode("zuul"))
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true)
.redirectUris("http://localhost:8000/core/secured");
}
}
SecurityConfig
#Configuration
#Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john")
.password(passwordEncoder().encode("123"))
.roles("USER");
}
#Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
application.properties
server.port=8003
spring.application.name=core
eureka.client.service-url.defaultZone=http://localhost:8001/eureka
Ok, especially here I changed many things. So probably I destroyed much from older guides. (Sorry my english is bad!)

Spring Security with JWT

I am trying to develop Spring Security project with JWT.
I want access Login api with out Spring Security (without JWT token). But with below configuration, every time (for login api as well) it is checking for JWT token giving me 403 error.
Below is my WebSecurityConfig.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthFilter jwtAuthFilter;
#Autowired
private TokenAuthenticationService jwtAuthenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/api/v1/login");
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/api/v1/login")
.permitAll()
.and()
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Thanks in advance
For login path configuration something like this can be used:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
.usernameParameter("username") // default is username
.passwordParameter("password") // default is password
.loginPage("/authentication/login") // default is /login with an HTTP get
.failureUrl("/authentication/login?failed") // default is /login?error
.loginProcessingUrl("/authentication/login/process"); // default is /login
// with an HTTP
// post
}
If some paths need to be ignored configure(WebSecurity web) can be overridden:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/somepath").antMatchers("/static/**");
}
There is filter class named JwtAuthFilter that is being executed before every service you call.
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
this code provides to be executed filter before every request, but its okay, you have to see this FilterClass there must be some check if token doesnt exist filter class must be returned and request will directly go to the login service. if you can show that Filter class and I will help you.

Spring REST security - Secure different URLs differently

I have working REST API under Spring 4 using Basic authentication. These REST services are under /api/v1/** URL. However, I want to add another set of REST endpoints under different url /api/v2/**, but protected with token-based authentication.
Is it possible to do this with one servlet ? How to configure Spring Security to use different forms of authentication for different URLs ?
Thank you.
Here's a code sample in Java config that uses UserDetailsService and has different security configurations for different URL endpoints:
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/v1/**")
.httpBasic()
.realmName("API")
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/**").authenticated();
}
}
#Configuration
#Order(2)
public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/v2/**")
/* other config options go here... */
}
}
}

spring-security login?logout redirects to login

I am using spring-security 3.2.0.RC2 with java config and two HttpSecurity configurations. One for REST API and one for UI.
When I post to /logout it redirects to /login?logout but then (incorrectly) redirects to /login.
When i enter username and password successfully I get redirected to login?logout and have to enter credentials a second time to get to the main page.
So it seems like the permitAll for login is not being honored for login?logout.
My security config looks like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Resource
private MyUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
StandardPasswordEncoder encoder = new StandardPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
#Configuration
#Order(1)
public static class RestSecurityConfig
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/v1/**").authorizeRequests()
.antMatchers("/v1/admin/**").hasRole("admin")
.antMatchers("/v1/account/**").hasRole("admin")
.antMatchers("/v1/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/**").authenticated()
.and().httpBasic();
}
}
#Configuration
#Order(2)
public static class UiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/**").hasRole("admin")
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
}
}
Can anyone explain why this is happening or what is wrong with my configuration?
A secondary problem that I see with this configuration is that the jsp tag sec:authorize url=... does not work although sec:authorize access=... does work.
In the url=... case it always shows the content even if the user is not authorized.
I know the user is not authorized becuase hitting the link that should have been hidden by the sec:authorize tag results in a 403 Forbidden.
Any help on this greatly appreciated!
I found a workaround for this apparent bug.
I added permitAll() on /login/** as follows:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
Answering my own question in case it helps anyone else who runs into this bug.
Instead of this:
.antMatchers("/login/**").permitAll()
I think the better solution would be this:
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.*antMatchers("/login").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll().
.and().logout().logoutSuccessUrl("/login?logout").permitAll();
The reason being, url pattern for permitAll(), in this case has limited scope when compared to "/login/**"

Categories