I am building a RESTful Spring Boot and React/Alt application. I want to add spring security to make sure that there could be no unauthenticated requests to the API.
I am using Auth0 for an authentication provider so users can log in to the application and more specifically the spring-security-auth0 library to handle the server side security side of things.
https://github.com/auth0/spring-security-auth0
After following the basic tutorial on Auth0, I have configured the security config in my spring application so that requests to the API will not work without a JSON web token. This works, but there are some endpoints (those that need a POST) in the controllers that don't. I get this error in Chrome devtools -
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'
I understand that there are no CSRF headers present and that is why it isn't working. But the main reason I am confused is because I have disabled CSRF and it still happens. As the spring docs instruct, I've done this -
#Configuration
#EnableWebSecurity
#ComponentScan("com.auth0")
#ImportResource("classpath:auth0-security-context.xml")
#PropertySource("classpath:auth0.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
I don't need CSRF in this case as the app will only ever be used in a dev environment. Why does this still happen even though I have disabled CSRF completely?
The CsrfFilter that is responsible for the Exception is definetly enabled.
This can have various reasons. Can it be you have another instance of WebSecurityConfigurerAdapter configured somewhere ?
You can try the following :
Set a breakpoint in line 'http.csrf().disable();' to see if its really executed.
Set breakpoints in the constructor(s) of WebSecurityConfigurerAdapter to see whether many instances are created.
This should show you whats going wrong..
Related
I was experimenting with spring boot 3 and spring security 6.
I configured my spring security to use LDAP authentication via AD, which works fine, but spring boot still doesn't detect a custom 'AuthenticationManager' and generates its own password.
This is how I set up my LDAP authentication:
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication().userSearchBase(userSearchBase).userSearchFilter(userSearchFilter).contextSource()
.url(url).managerDn(managerDn).managerPassword(ldapPassword);
}
Even after configuring ldap, this is what I get.
You can exclude the use the
#SpringBootApplication(exclude= {UserDetailsServiceAutoConfiguration.class}) to stop the default password generation.
For any different ways if you want you can follow this thread.
Click here
I am new to Spring Security. We are using Spring Security 5.4.5 with Spring Boot in one of my sample examples.
I have below config class in which am trying to apply the Spring Security authentication/authorization in /user and /admin endpoints of the REST API.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
PasswordEncoder bcryptPasswordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().principal("guest").authorities("GUEST_ROLE")//Provide the name and role to the annonymous user
.and()
.authorizeRequests()
.antMatchers("/register").anonymous()//allows registration page to be accessed by annonymous users only
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/admin").hasAnyRole("ADMIN_ROLE")
.antMatchers(HttpMethod.GET,"/user").hasAnyRole("STUDENT_ROLE", "ADMIN_ROLE")
.and()
.httpBasic();
}
#Override
#Bean
protected UserDetailsService userDetailsService() {
UserDetails annaSmithUserDetails = User.builder()
.username("annasmith")
.password(bcryptPasswordEncoder.encode("password"))//default password enoder is bcrypt
.roles("STUDENT_ROLE", "ADMIN_ROLE") //role of the user
.authorities("STUDENT_READ","STUDENT_WRITE","COURSE_READ","COURSE_WRITE") //authorities or we can say permission assigned to the user
.build();
return new InMemoryUserDetailsManager(annaSmithUserDetails);//can configure different
}
}
As per the above Spring configuration /user will be accessible to both the USER and ADMIN role and /admin will be accessible to the ADMIN role.
When am trying to access /user in the browser it displays the username and password popup and once I enter the correct credentials of the configured user it is not working and gives the 403 error.
I have below three questions
Am not seeing any error in the console log and is there a way I can see why Spring Security is showing the 403 error?
What is the issue with the above Spring Security configuration as I am not able to access the REST API endpoints?
Am not seeing any error in the console log and is there a way I can see why spring security is showing the 403 error?
By enabling spring debug logs, how to do this can be done with a simple google search or found in the spring documentation. Learn to debug your application (debugging your application should always be the first thing you learn and should be done before asking on stack overflow).
What is the issue with the above spring security configuration as I am not able to access the REST API endpoints?
Could be several issues since you have not disclosed how you are accessing the application. By curl, web browser, another webclient using fetch in a react application etc. etc. Should also be included when you ask on stack overflow so that people can be able to reproduce the issue at hand.
But listing some of the things that can be wrong:
Your request is done improperly
Your password might not be correct, because i see you are encrypting your password incorrectly (see the documentation of how to actually do it)
ensure your password is stored with the correct prefix, or use UserBuilder users = User.withDefaultPasswordEncoder(); when building your user as in the docs.
Roles should be defined without prefixes or suffixes (_ROLE) if to follow any standard
after you are logged in are you redirected to something you are not allowed to access?
As you can see there are several things that can be wrong, but you have provided too little information to be able to answer, and there is a lot of things you can do before asking on stack overflow.
The answer is vague since the question is vague.
I am working on an application which requires an integration of a proprietary SSO with spring security. The application uses spring boot, and the requirement is that we use the authentication from internal proprietary SSO module and authorization from the existing application. The existing application's authentication system has to be replaced with internal proprietary SSO's authentication module. I went through a few documents and understood that it is possible as the spring is module based.
While working on the application I noticed that we are using FilterRegistrationBean to initialize one filter, and another filter is added to the chain via WebSecurityConfigurerAdapter's configure(HttpSecurity http) method.
Can someone please let me know if this will be treated as two different chains? If so, how are the chains checked for filtering out the details?
Can I just remove the filter we are adding via WebSecurityConfigurerAdapter's configure(HttpSecurity http) method and replace the existing filter that is registered via FilterRegistrationBean with the filter (with highest precedence) from internal proprietary SSO?
OK so we do exactly what you're asking for in one of our systems. We have this working in Spring boot 1 and 2. These are the steps to take.
Create a bean extending AbstractPreAuthenticatedProcessingFilter. Implement getPreAuthenticatedPrincipal and getPreAuthenticatedCredentials to extract the authenticated user and optional credentials (e.g. a certificate) from your SSO system. Create a FilterRegistrationBean for this filter bean otherwise thanks to spring boot's component scanning it'll end up in the main filter chain as well as the security filter chain.
Create a user details (authorization) service bean implementing AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>. Override loadUserDetails to take your authenticated token and use it to add permissions in the form of GrantedAuthority lists.
In your WebSecurityConfigurerAdapter bean subclass do the following:
Inject your subclass of AbstractPreAuthenticatedProcessingFilter and also your subclass of AuthenticationUserDetailsService.
Add a class member of type PreAuthenticatedAuthenticationProvider and initialise it with new (it's not a bean).
In configure(HttpSecurity) initialise your filter bean with an authentication manager: yourBean.setAuthenticationManager(authenticationManager()) then ensure your filter is included:
http.addFilter(yourBean)
.authorizeRequests()
.requestMatchers(...)
Override configure(AuthenticationManagerBuilder) and initialise the PreAuthenticatedAuthenticationProvider you created in step (2) with your implementation of the authentication and authorization beans.
this.preAuthProvider.setPreAuthenticatedUserDetailsService(this.userDetailsService);
this.preAuthProvider.setThrowExceptionWhenTokenRejected(true);
authBuilder.authenticationProvider(this.preAuthProvider);
That should be all. Hope that helps.
I have a REST service, built using Java, Spring-boot and using Spring Security with Basic Access Authentication. There are no Views, no JSP etc, no 'login', just stateless services which can be called from a React app hosted separately.
I've read a variety of documentation about CSRF protection, but can't decide whether I should be using spring-security CSRF config, or just disabling it? If I disable the csrf protection I can call the service with curl using my basic auth like this:
curl -H "authorization:Basic c35sdfsdfjpzYzB0dDFzaHA=" -H "content-type:application/json" -d '{"username":"user","password":"password","roles":"USER"}' localhost:8081/api/v1/user
If I enable the csrf protection and provide a x-csrf-token header, then the spring CsrfFilter attempts to cross check this against a value from (I think) a session cookie in the HttpServletRequest. However since its a stateless REST service I don't have a session, and haven't 'logged in'.
I have a config class which looks like this:
#EnableWebSecurity
#Configuration
public class ServiceSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic();
if (!serviceProperties.isCsrfEnabled()) {
http.csrf().disable();
}
}
The more I think about it, the more it seems that I will just need to disable CSRF protection. Is there another way to configure spring security so it will work?
thanks
To answer your first question, in the context that you describe, you do not need CSRF protection. The background of CSRF protection is to ensure that the user is not tricked into doing some unwanted action.
For example, in pure theory, you could have logged into a bank's website (and thus established a session) and then went to some shady website. This site could have a form making a POST request to the bank's APIs. Because you have a session there, if the endpoint is not CSRF protected, then the request may go through.
As such, CSRF mostly acts as a protection against browser + session based attacks. If you expose a pure REST API with e.g. OAuth protection, then I don't see any reason for CSRF.
As you use spring boot, you could also disable CSRF using the application.properties / application.yaml configuration file.
security.enable-csrf=false
You can check out the Common Application Properties documentation page for more out-of-the-box configuration options.
If you want to disable csrf in more proper way you can call it like this(if using java configuration)
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic();
.and()
.csrf()
.disable()
I am trying to implement OAuth security and met a problem that for me is not clear enough configuration class.
While implementing AuthorizationServerConfigurer i have three configurers:
ClientDetailsServiceConfigurer used to provide the way how and from where to get client details. As an example, it can be service which provides registered clients from the database.
When it comes to AuthorizationServerSecurityConfigurer and AuthorizationServerEndpointsConfigurer I am not sure what they do or how they should be configured. In the documentation it said only:
AuthorizationServerEndpointsConfigurer: defines the authorization and
token endpoints and the token services.
Maybe someone can explain in simple words what these two configurers do, or what they are used for.
AuthorizationServerConfigurer's javadoc is more informative than the linked documentation. AuthorizationServerSecurityConfigurer, as its name suggests, configures the security of the Authorization Server itself. For example you can override the OAuth endpoints security such as /oauth/token, provide an access denied handler or restrict to SSL access. Here are what the documentation says about it:
Configure the security of the Authorization Server, which means in
practical terms the /oauth/token endpoint. The /oauth/authorize
endpoint also needs to be secure, but that is a normal user-facing
endpoint and should be secured the same way as the rest of your UI, so
is not covered here. The default settings cover the most common
requirements, following recommendations from the OAuth2 spec, so you
don't need to do anything here to get a basic server up and running.
As for AuthorizationServerEndpointsConfigurer:
Configure the non-security features of the Authorization Server
endpoints, like token store, token customizations, user approvals and
grant types. You shouldn't need to do anything by default, unless you
need password grants, in which case you need to provide an
AuthenticationManager.
Here is a sample from one of my projects:
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(jwtTokenStore())
.tokenEnhancer(tokenEnhancer());
}
Here I provided a JwtTokenStore as my TokenStore and a AuthenticationManager since I was using Password Grants.
I am using spring-security-oauth, there is a helpful documentation maybe help you :
projects.spring.io/spring-security-oauth/docs/oauth2.html