Basic auth returns 403 in postman but works fine in browser - spring-boot

I've defined securityConfig as following:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(passwordEncoder())
.usersByUsernameQuery(\\some code\\)
.authoritiesByUsernameQuery(\\some code\\)
.getUserDetailsService();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(entryPoint);
}
When I am entering the credentials in the form in my browser it works fine,
but when I try to send the request in postman using basic auth form
I get 403 error. What am I doing wrong?

This is most likely caused by CSRF protection.
From the docs:
Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.
CSRF protection can be disabled as follows:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(entryPoint)
.and()
.csrf().csrf().disable()
}

Related

Spring Security: don't redirect to login page in case unauthorised

I have Spring Security with oAuth2 authorisation.
I use it for REST API.
My configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.authorizeRequests()
.antMatchers("/health").permitAll()
.antMatchers("/**").authenticated()
.and()
.oauth2Login()
.and()
.httpBasic();
}
}
I need to make all requests return me 401 when I didn't authorise.
But now when I'm not authorised I got redirect to /login page.
I need to use it like usual REST API: if I did authorise then get content, otherwise get 401 Unauthorised.
How I can make it?
Thanks in addition for help.
Basically you need to configure an AuthenticationEntryPoint which is invoked when Spring Security detects a non-authenticated request. Spring also gives you a handy implementation which enables you to return whatever HttpStatus you need:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
//rest of your config...
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
}

Oauth2 security configuration antmatchers request filtering not working as expected

I am working on a simple spring boot project along with spring security oauth2 to use google authentication for a specified endpoint which is /google/login.
With following security configurations everything is working perfectly.
#Configuration
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/**")
.and()
.authorizeRequests().antMatchers("/ldap/login").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}
}
But I need to specify only /google/login endpoint to authenticate with oauth2. Therefore I specified it like this.
#Configuration
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/google/**")
.and()
.authorizeRequests().antMatchers("/ldap/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}
}
with this security configuration http://localhost:8080/google/login endpoint call redirects to another endpoint called http://localhost:8081/oauth2/authorization/google which is I haven't defined.
Please help me to overcome this problem. Thank you.
This configuration works for me. I had to allow all endpoints that were redirecting while Google's authentication process was running. 
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.requestMatchers().antMatchers("/google/**","/oauth2/authorization/google","/login/oauth2/code/google")
.and()
.authorizeRequests().antMatchers("/ldap/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}

Spring Security (with Spring Boot) returns login form as a response for POST, EDIT, DELETE operation

I am making a meme sharing app where I have secured some REST endpoints like POST, DELETE and EDIT. And removed authentication for GET operations.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/xmeme/delete/**").hasAuthority("ADMIN")
.antMatchers("/xmeme/edit/**").hasAnyAuthority("ADMIN")
.antMatchers("/xmeme/post").hasAnyAuthority("ADMIN", "USER")
.antMatchers("/user/register").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll().defaultSuccessUrl("/xmeme/memes", true)
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
#Override public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/xmeme");
web.ignoring().antMatchers("/xmeme/memes");
web.ignoring().antMatchers("/xmeme/meme/**");
}
Now the issue is when I am trying to POST a meme and use the Authorization > Type > Basic Auth option in POSTMAN, I am getting the login form as response. And same happens with the EDIT and DELETE operations.
I couldn't find a solution. Can someone please suggest some workaround for this issue?
enter image description here
enter image description here
You have enabled Form Login for you application in configure(HttpSecurity http)
http.formLogin()
If you want to enable HTTP Basic authentication, you need to configure it in configure(HttpSecurity http)
http.httpBasic()
If you have configured both formLogin and httpBasic, Spring Security will use content-negotiation to determine how it should behave towards an unauthenticated user based on the content type being requested.
you should specify the authority with the ROLE_ prefix such as ROLE_ADMIN and ROLE_USER in configure(HttpSecurity http) method.
configure(WebSecurity web) method should be placed before the configure(HttpSecurity http) check detailed usage
Disable the CSRF token using http.csrf().disable()
Verify that user om has the correct authority assigned
#Override public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/xmeme");
web.ignoring().antMatchers("/xmeme/memes");
web.ignoring().antMatchers("/xmeme/meme/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/xmeme/delete/**").hasAuthority("ROLE_ADMIN")
.antMatchers("/xmeme/edit/**").hasAnyAuthority("ROLE_ADMIN")
.antMatchers("/xmeme/post").hasAnyAuthority("ROLE_ADMIN", "ROLE_USER")
.antMatchers("/user/register").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll().defaultSuccessUrl("/xmeme/memes", true)
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/403");
}

Spring security antMatcher not working as expected

I have my custom controller "/my-endpoint" and spring app with the following configuration:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/my-endpoint", "/health")
.permitAll()
.antMatchers(DENY_RESOURCE_PATTERNS)
.denyAll()
.anyRequest()
.authenticated()
}
It seems that for a unanimous user it working fine. But if I already authorized (using oauth2) and my session(or token) is expired -> spring trying to redirect me to the login page.
I don't want this, I want to allow any user to connect to "/my-endpoint" endpoint.
What I forgot to configure?
The interesting thing, that built-in endpoint "/health" working as expected, even if session is expired.
you can use configure(WebSecurity web). It will bypass the Spring Security Filters and will allow any user to access the endpoint. see HttpSecurity vs WebSecurity
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.yourMethod, "/health")
.antMatchers(HttpMethod.yourMethod, "/my-endpoint");
}

Spring Security Authentication Success With Wrong Password

My WebSecurity Config is like below;
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication().withUser("hellouser")
.password("hellopass").roles("USER");
}
}
When i give wrong username, Authentication fails as expected. But, if i get success in authentication once, all other requests after that with wrong password but correct username gets authenticated successfully....
Is it getting cached somewhere?
Can i disable this feature?
Isn't it suppose to give authentication failure with wrong password?
NOTE: I am learning spring-security. I dont have any html pages in this app and testing from PostMan.
use http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); in the configure method.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//HTTP Basic authentication
.httpBasic()
.and()
....
.csrf().disable()
.formLogin().disable();
//to check password in each request
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
I was able to access the URL from below configuration using basic auth from Postman even with wrong credential, which was happening because once you provide the right credentials the credentials get stored in session and even if you repeats the same request the same session will be used to access the URL.
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/secure/admin/**").hasRole("ADMIN")
.antMatchers("/api/**","/secure/getUserByName/**").hasAnyRole("USER","ADMIN")
.anyRequest().fullyAuthenticated();
Solution:
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Just add the above code. So this configuration assures that only a single instance of a user is authenticated at a time. And if the same user tries to access the URL then it's previous session is terminated and then the user has to provide login credentials again for which new session is created.

Resources