How to enable CSRF for all request in Spring Security - spring

As spring disables CSRF token for certain methods like GET, how we can enable CSRF token validation for all requests including GET using spring security.

#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(AnyRequestMatcher.INSTANCE);
}
}
Note this configuration means csrf token is required for any request ,that's unnecessary and hard to achieve

Related

How to access endpoint without token in spring boot?

I am using an actuator for getting server health, also I am doing validation on the token on each request, now I need to put a token to access actuator health but I want to access actuator health without using the token and without affecting API endpoint with token!
Note: My Actuator working fine with the token.
also, I implement the OncePerRequestFilter class for validating the firebase token for each request.
You can create a custom SecurityConfiguration where you permit access to actuator requests:
#Configuration
#EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.requestMatchers("/actuator/**").permitAll()
.anyRequest().authenticated();
}
}
You may want to read the spring-boot-docs for more information.
EDIT:
When using OncePerRequestFilter you could implement the shouldNotFilter method and check for actuator paths there:
#Override
protected boolean shouldNotFilter(HttpServletRequest request)
throws ServletException {
String path = request.getRequestURI();
return path.startsWith("/actuator");
}

Authorization doesn't work when using Spring boot rest api using oauth2 , Keycloak

I am trying to use oauth2 to do authentication and authorization for rest api.
with the rest api url as "/users" and the role "userrole" is defined in keycloak.
I have used used keycloak for jwt access token. Authentication is working fine but Authorization is not working.
If I specify hasRole I always get forbidden error.
But if I will remove hasRole authentication works as expected.
#Configuration
#EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwtSetUri;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.cors().and()
.csrf()
.disable()
.authorizeRequests().
antMatchers("/users").hasRole("userrole").antMatchers("/users").authenticated()
.and().oauth2ResourceServer().jwt() ;
}
}

Spring Boot Security + Spring Boot REST Repository config issue

I have Spring boot application as below
And the Web Security Config as
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().formLogin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// #formatter:off
auth.inMemoryAuthentication().withUser("chiru").password("{noop}chiru").roles("ADMIN").and().withUser("user")
.password("{noop}user").roles("USER");
// #formatter:on
}
}
And the i have Repository as below
public interface IssuesRepository extends CrudRepository<Issues, Integer> {
}
when i try to add data through REST Using Postman with Basic Authentication, its failing
Use httpBasic() instead of formLogin(), like http.authorizeRequests().anyRequest().authenticated().and().httpBasic();.
formLogin() is used when you want to have login page to authenticate the user (so you have), but in your example you are using http basic to do that. Spring security doesn't recognizes your http basic header and returns login page.
PS. You can use both methods http.httpBasic().and().formLogin()

Spring Boot 1.3.3 #EnableResourceServer and #EnableOAuth2Sso at the same time

I want my server be a ResourceServer, which can accept a Bearer Access token
However, If such token doesn't exist, I want to use the OAuth2Server to authenticate my user.
I try to do like:
#Configuration
#EnableOAuth2Sso
#EnableResourceServer
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
However, in this case, only the #EnableResourceServer annotation works. It returns
Full authentication is required to access this resource
And do not redirect me to the login page
I mentioned that the #Order is important, if I add the #Order(0) annotation,
I will be redirect to the login page, however, I cannot access my resource with the access_token in Http header:
Authorization : Bearer 142042b2-342f-4f19-8f53-bea0bae061fc
How can I achieve my goal? I want it use Access token and SSO at the same time.
Thanks~
Using both configuration on same request would be ambiguous. There could be some solution for that, but more clear to define separate request groups:
OAuth2Sso: for users coming from a browser, we want to redirect them to the authentication provider for the token
ResourceServer: usually for api requests, coming with a token they got from somewhere (most probably from same authentication provider)
For achieving this, separate the configurations with request matcher:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Bean("resourceServerRequestMatcher")
public RequestMatcher resources() {
return new AntPathRequestMatcher("/resources/**");
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.requestMatcher(resources()).authorizeRequests()
.anyRequest().authenticated();
}
}
And exclude these from the sso filter chain:
#Configuration
#EnableOAuth2Sso
public class SsoSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("resourceServerRequestMatcher")
private RequestMatcher resources;
#Override
protected void configure(final HttpSecurity http) throws Exception {
RequestMatcher nonResoures = new NegatedRequestMatcher(resources);
http
.requestMatcher(nonResoures).authorizeRequests()
.anyRequest().authenticated();
}
}
And put all your resources under /resources/**
Of course in this case both will use the same oauth2 configuration (accessTokenUri, jwt.key-value, etc.)
UPDATE1:
Actually you can achieve your original goal by using this request matcher for the above configuration:
new RequestHeaderRequestMatcher("Authorization")
UPDATE2:
(Explanation of #sid-morad's comment)
Spring Security creates a filter chain for each configuration. The request matcher for each filter chain is evaluated in the order of the configurations.
WebSecurityConfigurerAdapter has default order 100, and ResourceServerConfiguration is ordered 3 by default. Which means ResourceServerConfiguration's request matcher evaluated first. This order can be overridden for these configurations like:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration configuration;
#PostConstruct
public void setSecurityConfigurerOrder() {
configuration.setOrder(3);
}
...
}
#Configuration
#EnableOAuth2Sso
#Order(100)
public class SsoSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
So yes, request matcher is not needed for SsoSecurityConfiguration in the above sample. But good to know the reasons behind :)

spring security permitAll still considering token passed in Authorization header and returns 401 if token is invalid

I am using spring security oauth in my project. I am excluding some urls from authentication by configuring in spring security ResourceServerConfigurerAdapter. I added http.authorizeRequests().antMatchers(url).permitAll().
Now, what I am seeing is that, if I don't pass the Authorization header to these urls, it is not authenticated. And the API is called properly.
If the call is made with an Authorization header, then it validates the token and fails the call if the token is not validated.
My question is what do I need to do so that the token is ignored in the request for which I have permitAll.
Spring OAuth2 will intercept all url with header: Authorization Bearer xxx.
To avoid Spring OAuth2 from intercept the url. I have created a SecurityConfiguration which has higher order than Spring OAuth2 configuration.
#Configuration
#EnableWebSecurity
#Order(1) // this is important to run this before Spring OAuth2
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
List<RequestMatcher> requestMatchers = new ArrayList<RequestMatcher>();
// allow /api/public/product/** and /api/public/content/** not intercepted by Spring OAuth2
requestMatchers.add(new AntPathRequestMatcher("/api/public/product/**"));
requestMatchers.add(new AntPathRequestMatcher("/api/public/content/**"));
http
.requestMatcher(new OrRequestMatcher(requestMatchers))
.authorizeRequests()
.antMatchers("/api/public/product/**", "/api/public/content/**").permitAll()
}
}
The above configuration allows /api/public/product/** and /api/public/content/** to be handled by this configuration, not by Spring OAuth2 because this configuration has higher #Order.
Therefore, even setting invalid token to above api call will not result in invalid access token.
As per spring-oauth2 docs https://projects.spring.io/spring-security-oauth/docs/oauth2.html
Note: if your Authorization Server is also a Resource Server then there is another security filter chain with lower priority controlling the API resources. Fo those requests to be protected by access tokens you need their paths not to be matched by the ones in the main user-facing filter chain, so be sure to include a request matcher that picks out only non-API resources in the WebSecurityConfigurer above.
So define WebSecurityConfigurer implementation with higher order than ResourceServerConfig.
In case you are dealing with Reactive Spring webflux, from SooCheng Koh's answer.
#Configuration
#EnableWebFluxSecurity
#EnableReactiveMethodSecurity
#Order(1) // this is important to run this before Spring OAuth2
public class PublicSecurityConfiguration {
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/api/public/**").permitAll();
return http.build();
}
}
It's not a bug it's a feature :)
As already mentioned by other people, even if you have permitAll, Spring Security will still check the token if there is a header "Authorization".
I don't like the workaround on the backend with Order(1) so I did a change on the frontend simply removing the header "Authorization" for the specific request.
Angular example with interceptor:
#Injectable()
export class PermitAllInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(req.url.includes('permitAllUrl')){
req = req.clone({ headers: req.headers.delete('Authorization') });
}
return next.handle(req);
}
}
and then just register the interceptor in app.module.ts:
{
provide: HTTP_INTERCEPTORS,
useClass: PermitAllInterceptor ,
multi: true
}

Resources