Spring security login except whitelisted IP - spring-boot

I have a Spring boot application and added Spring security. I would like that some ip ranges by pass the security while all other requests need to log in before. I have extended the WebSecurityConfigurerAdapteras follows however it does not work as I would expect, The whitelisted IP can use the application without login while other requests get an HTTP 403 instead of getting the log in form. What I am doing wrong here?
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure (HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().access("hasIpAddress('192.168.1.0/24') or isAuthenticated()");
}
}

Related

spring cloud secured gateway ratelimiting not allowing permitall urls

I was trying to apply rate limiting on my spring cloud gateway which is secured through oauth2 and keycloak. the gateway sits in front of 3 microservices. each microservice exposes openapi3 config. in both gateway and microservices made the url to openapi3 config as public. but when i followed instruction to apply rate limiting using redis the public urls are not public anymore and getting 403 forbidden.
gateway security -->
#Configuration
#EnableWebFluxSecurity
public class WebFluxSecurityConfig {
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity serverHttpSecurity) {
serverHttpSecurity.authorizeExchange(exchange -> exchange
.pathMatchers("/v3/api-docs/**",
"/employee/v3/api-docs/**",
"/department/v3/api-docs/**",
"/organization/v3/api-docs/**",
"/webjars/swagger-ui/**",
"/swagger-ui/**", "/swagger-ui.html").permitAll()
.anyExchange().authenticated())
.oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt);
serverHttpSecurity.csrf().disable();
serverHttpSecurity.formLogin().disable();
serverHttpSecurity.httpBasic().disable();
return serverHttpSecurity.build();
}
}
Rate limiting config -->
#Configuration
public class RateLimitingConfig {
/*
* NOTE: this stops all unauthenticated access :(
* need a way to allow public permitted urls from this. but how!
*/
#Bean
KeyResolver userKeyResolver() {
return exchange -> ReactiveSecurityContextHolder.getContext()
.map(ctx -> ctx.getAuthentication().getPrincipal().toString());
}
}
microservice security config -->
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
//NOTE: this is to configure authorization
http.authorizeRequests(authorize -> authorize
.antMatchers("/v3/api-docs/**").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
http.csrf().disable();
http.formLogin().disable();
http.httpBasic().disable();
}
}
the rate limiting is working properly for authenticated user but my permit all methods are not permitted by the gateway anymore.
how can i enforce rate limiting for private urls and also expose public urls to unauthenticated users?
here is the full code base -
https://github.com/tareqmy/springcloudexamples

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");
}

How do I use IPwhitelisting and OAuth2 in spring boot? [duplicate]

This question already has answers here:
Single role multiple IP addresses in Spring Security configuration
(2 answers)
Closed 1 year ago.
I am using OAuth2 in my spring boot application and I want to use IP whitelisting for range of IP addresses. i.e I want to give whitelisted user to access particular resource without providing token.
I have large number of whitelisted IPs and I am using Oauth2 token validation so that I have one resource server. I want to use IP whitelisting at first place and if it fails user should have valid token to have access to resource. Can you please give me any idea how can I do that.
In Spring Security you can configure your particular end point and whitelist using the method hasIpAddress in security config class.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").hasIpAddress("11.11.11.11")
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
}
If you have multiple IP addresses then you can use in this way
http
.authorizeRequests()
.antMatchers("/api/**").access(
"hasIpAddress('10.0.0.0/16') or hasIpAddress('127.0.0.1/32')")
For Resource Server you can do it in the #EnableResourceServer class & the same configure method you can setup Ipwhitelisting as shared below
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OAuthRequestedMatcher())
.anonymous().disable().authorizeRequests();
http
.authorizeRequests()
.antMatchers("/api/**").access("hasIpAddress('10.0.0.0/16') or hasIpAddress('127.0.0.1/32')");
}
}
Now since you have mentioned that you have many IP addresses you can make a list in the property file (application.properties) & at the application startup, you can loop through those to build the argument string that has to be passed in the access method.

how do I enable the /refresh Actuator endpoint and get around CSRF restrictions?

In the WebSecurityConfig.java in our project
public class WebSecurityConfig extends WebSecurityConfigurererAdapter {
#Override
p void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasAnyAuthority("USER", "ADMIN")
.and.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
I have installed the #RefreshScope on my pojo:
#Configuration
#Data
#RefreshScope
public class MyProperties {
private String myName;
private String myAddress;
private String myCity;
.....
}
Spring Boot Actuator is installed. Spring Security is providing https and SSL. I can get to all of the GET actuator endpoints, but when I try to do a call to http://localhost:8080/actuator/refresh (a POST), I get a 403 Refused.
In looking around, I saw that the default stuff doesn't allow POSTs. This works if I disable csrf(), but not if it is enabled (which is a requirement for the product).
Could someone help me understand what is going on? Has anyone else done this? Can this be done without disabling CSRF entirely?
Thanks,
Winona
Just specify what endpoints on which you want to disable CSRF. For example: csrf().ignoringAntMatchers("/actuator/**"). Doing so disables CSRF prorection for any request that starts with /actuator/.

Spring Security OAuth2 check_token endpoint

I'm trying to setup a resource server to work with separate authorization server using spring security oauth. I'm using RemoteTokenServices which requires /check_token endpoint.
I could see that /oauth/check_token endpoint is enabled by default when #EnableAuthorizationServer is used. However the endpoint is not accessible by default.
Should the following entry be added manually to whitelist this endpoint?
http.authorizeRequests().antMatchers("/oauth/check_token").permitAll();
This will make this endpoint accessible to all, is this the desired behavior? Or am I missing something.
Thanks in advance,
You have to
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
{
oauthServer.checkTokenAccess("permitAll()");
}
For more information on this ::
How to use RemoteTokenService?
Just to clarify a couple of points, and to add some more information to the answer provided by Pratik Shah (and by Alex in the related thread):
1- The configure method mentioned is overridden by creating a class that extends AuthorizationServerConfigurerAdapter:
#EnableAuthorizationServer
#Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("ger-client-id")
.secret("ger-secret")
.authorizedGrantTypes("password")
.scopes("read", "write");
}
}
2- I suggest reading this Spring guide explaining the automatic configuration carried out by Spring Boot when we include the #EnableAuthorizationServer annotation, including an AuthorizationServerConfigurer bean. If you create a configuration bean extending the AuthorizationServerConfigurerAdapter as I did above, then that whole automatic configuration is disabled.
3- If the automatic configuration suits you just well, and you JUST want to manipulate the access to the /oauth/check_token endpoint, you can still do so without creating an AuthorizationServerConfigurer bean (and therefore without having to configure everything programmatically).
You'll have to add the security.oauth2.authorization.check-token-access property to the application.properties file, for example:
security.oauth2.client.client-id=ger-client-id
security.oauth2.client.client-secret=ger-secret
security.oauth2.client.scope=read,write
security.oauth2.authorization.check-token-access=permitAll()
Of course, you can give it an isAuthenticated() value if you prefer.
You can set the log level to DEBUG to check that everything is being configured as expected:
16:16:42.763 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll()', for Ant [pattern='/oauth/check_token']
There is no much documentation about these properties, but you can figure them out from this autoconfiguration class.
One last thing worth mentioning, even though it seems to be fixed in latest Spring versions, I just submitted an issue in the spring-security-oauth project; it seems that the token_check functionality is enabled by default if you add a trailing slash to the request:
$ curl localhost:8080/oauth/check_token/?token=fc9e4ad4-d6e8-4f57-b67e-c0285dcdeb58
{"scope":["read","write"],"active":true,"exp":1544940147,"authorities":["ROLE_USER"],"client_id":"ger-client-id"}
There are three POST parameters, namely client_id (user name), client_secret (password corresponding to the user name), token (token applied for), client_id, client_secret are different from the parameters in the /oauth/token interface
enter image description here
First, config token access expression:
#Override
public void configure(AuthorizationServerSecurityConfigurer securityConfigurer) throws Exception {
securityConfigurer
.allowFormAuthenticationForClients()
.checkTokenAccess("isAuthenticated()")
.addTokenEndpointAuthenticationFilter(checkTokenEndpointFilter());
}
Then, we need define a filter to process client authentication:
#Bean
public ClientCredentialsTokenEndpointFilter checkTokenEndpointFilter() {
ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter("/oauth/check_token");
filter.setAuthenticationManager(authenticationManager);
filter.setAllowOnlyPost(true);
return filter;
}

Resources