'Spring security - How to whitelist localhost?
I am trying to set set an OAuth2 security system with client_credentials and a JWT token for a Spring boot api. I am using postman to test its functionality. So, there is a controller that does some basic things like GET Status request or GET tables of an entity request. The API works as intented when there is no security at all. It works perfectly when I am using a GET request with OAuth2 authentication through Postman as well.
Now, I am trying to whitelist some IPs so when I am using the API from the localhost IP there is no need for authentication and all the resources are public but when somebody with a different IP tries to access it, then he needs to authenticate. The problem is, no matter what I do in the WebSecurityConfiguration.java on HttpSecurity configuration, Postman returns that I am unauthorized unless I authenticate with client_credentials.
What I have tried:
- http.authorizeRequests().antMatchers("/**").permitAll();
- http.authorizeRequests().antMatchers("/**").hasIpAddress("::1").anyRequest().permitAll();
- http.authorizeRequests().antMatchers("/**").hasIpAddress("127.0.0.1").anyRequest().permitAll();
- http.authorizeRequests().anyRequest().access("hasIpAddress('127.0.0.1') or isAuthenticated()");
- http.authorizeRequests().anyRequest().permitAll();
and some more combinations. Nothing works of the above. What do I do wrong and how can I grant public access to localhost but make other/external IPs to require authentication? Maybe I am testing it wrong from Postman?(I am changing Authentication from OAuth2 to NoAuth or Inherit from parent).
I would like to note that web.ignoring().antMatchers("/**"); on WebSecurity configuration works fine and removes authentication from all my resources.
WebSecurityConfiguration.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UsersService usersService;
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usersService).passwordEncoder(encoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**")
.hasIpAddress("127.0.0.1")
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
ConfigOAuth2.java
@Configuration
public class ConfigOAuth2 extends AuthorizationServerConfigurerAdapter{
@Value("test")
private String clientId;
@Value("test-key")
private String clientSecret;
private String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
"MIIEogIBAAKCAQEArOyEna4QGVfHs2uLkspnvg990DoG8LsTRVWUln6PNnzHdciU\n" +
"wbTWa3Mmvnas3fH+ryAB+w3hgcRHH5D0SQzZG8JgcSnUDi4nxdjhcrdxeAMeeEKP\n" +
"mWZPhUzmuNS5j1ZjRoLo/ih4PNssXdjy1w35h5qtrBTI3JrEkBMBQMkfHuWeK1EV\n" +
"CCdP5krHl2Nf0vKG0MQVnU+FKbLzZtM3hryHTFMWHUAAijJ///nlimfU3Xdju4Nw\n" +
"TIktaP1FWhUhSoNy0xVGYQVx3XlT2AG9mQeZWTmC8Vbw2X5BMXg1A0H/Rt55Vpf0\n" +
"+HB4ZsMxRzvYWe6Xgf1+SCWH8O0mIS5DFohgfQIDAQABAoIBAENGjV2vL5I8hXQ3\n" +
"XgjQ+EWIT2FogfS8Q4YRAor+WAdRymP3knA+Q8Fv/l3RW/XJRVWqtTqQLvDGhQkx\n" +
"4uhcuEbFe7HrHRYbPNwLQcLYvat8Qyl0c9uxYzSwM38rO7oZWOxA2Baxdf3vIzar\n" +
"xeaHCFKKihDN0UuKZvjKfA1RcesZtH9U4kZFJGZsAOvFkqvXKDA5G0CGqJJbDHuA\n" +
"uBNIk7ggy+wsyLaGEWkj49IdYZhhMbkWaNKbYPi5zK7Wz54N/qi+HQl0tVQKXw4e\n" +
"oJl24ua1IIhoHIS+ipX1pJVy4MKGh6gZizzl+9MvOzgp81APVPa6obpE2oT5XPAe\n" +
"ovIRMh0CgYEA2WPwRSiHv0Sc/9g9dpK4M7tk+njoqdcn5oYMikWtMcqlGNhZbh2s\n" +
"sQmB03354BArE5KQ4KA8tGzWVNXnf2k+8klNdlz+Q/GxS0G1E4aqkl4Dq/EfVif+\n" +
"mb2gUccpXQ4ygFDmjP5tx7cqHNytYMYJ6rKPOA0GfqWS5XkPTMIZDB8CgYEAy6LT\n" +
"yd4py19MNtsgLwR4F8A+/ffvCy9TRHnpAlYgzeTVW3LHN4j/3DQ25g/AOFsrx/1A\n" +
"GBTq6g8SDSe4qDoRmaRPPVmVtwuVE9uH/F83vlz5LvMJqQCbOMMcJZc/lApP9fGM\n" +
"yRKlvSyrrjialMFHiFU5HasyRArdQCE48jTJP+MCgYAuSHHCN6PXHAOVEPPdB9XB\n" +
"5dbU4OMgLden48hNtBHwtOU7iexYXmcC9jQ20+5cPvT84MqJmHP0Mevb+gKkhMLL\n" +
"EMI2PgxAaPfHPwEPXC96pBuCAv8Z97/j+ZRldNKgpkIoQZEkWZMD30JPDMi4/tDj\n" +
"sAp/8337fsLsqj6QqA5vHwKBgHAUW6sk+y3zcrhSnQEj3ZF8/267Urd+Qb9TthrS\n" +
"GtYYGBJwNxPq9KBXoMu5aZvbGlrFmcxnXvCagN36udjltSAyXmau8wc/ebrnPo56\n" +
"Pe0psQDVRcDeE5EHWmuaNqUdk+sTGuDkwZJAjvGiN/qd8ugnt/sLaewnaqVMY9Jz\n" +
"mTzvAoGAUKMucO57do5xYFezmCvrzaLhlQZi+3fBHlrribUEkdmJNC4Q4FGPcysS\n" +
"TkcgVs0m7xgbubkn+yjuEVFsojWAPeJBIUnCbpDTIUDRARpbOCxgdVTdzIl3ACxc\n" +
"r9q0DV3XIQ4SKYIUmgc2sFSrTEjEaisDLpZVMLZZaJQldXQfeFM=\n" +
"-----END RSA PRIVATE KEY-----";
private String publicKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArOyEna4QGVfHs2uLkspn\n" +
"vg990DoG8LsTRVWUln6PNnzHdciUwbTWa3Mmvnas3fH+ryAB+w3hgcRHH5D0SQzZ\n" +
"G8JgcSnUDi4nxdjhcrdxeAMeeEKPmWZPhUzmuNS5j1ZjRoLo/ih4PNssXdjy1w35\n" +
"h5qtrBTI3JrEkBMBQMkfHuWeK1EVCCdP5krHl2Nf0vKG0MQVnU+FKbLzZtM3hryH\n" +
"TFMWHUAAijJ///nlimfU3Xdju4NwTIktaP1FWhUhSoNy0xVGYQVx3XlT2AG9mQeZ\n" +
"WTmC8Vbw2X5BMXg1A0H/Rt55Vpf0+HB4ZsMxRzvYWe6Xgf1+SCWH8O0mIS5DFohg\n" +
"fQIDAQAB\n" +
"-----END PUBLIC KEY-----";
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
PasswordEncoder passwordEncoder;
@Bean
public JwtAccessTokenConverter tokenEnhancer() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
converter.setVerifierKey(publicKey);
return converter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(tokenEnhancer());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore())
.accessTokenConverter(tokenEnhancer());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(clientId)
.secret(passwordEncoder.encode(clientSecret))
.scopes("read", "write")
.authorizedGrantTypes("client_credentials")
.accessTokenValiditySeconds(2000)
.refreshTokenValiditySeconds(200000);
}
}
DEBUG logs
13:57:13.024 INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn() @132 - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
13:57:13.034 INFO org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn() @201 - Finished Spring Data repository scanning in 7 ms. Found 0 JPA repository interfaces.
13:57:13.523 INFO org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize() @108 - Tomcat initialized with port(s): 9090 (http)
13:57:13.618 INFO org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext() @290 - Root WebApplicationContext: initialization completed in 1195 ms
13:57:13.958 INFO org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources() @89 - H2 console available at '/h2-console'. Database available at 'jdbc:mysql://172.16.69.19:3306/SpringRestApi'
13:57:14.568 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.buildNativeEntityManagerFactory() @437 - Initialized JPA EntityManagerFactory for persistence unit 'default'
13:57:14.668 WARN org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration$JpaWebConfiguration.openEntityManagerInViewInterceptor() @219 - spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
13:57:14.883 INFO org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.setSigningKey() @178 - Configured with RSA signing key
13:57:14.893 INFO org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.afterPropertiesSet() @309 - Signing and verification RSA keys match
13:57:15.003 DEBUG org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$2.performBuild() @225 - No authenticationProviders and no parentAuthenticationManager defined. Returning null.
13:57:15.083 DEBUG org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping.handlerMethodsInitialized() @367 - 8 mappings in 'oauth2EndpointHandlerMapping'
13:57:15.155 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [fullyAuthenticated] for Ant [pattern='/oauth/token']
13:57:15.155 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [permitAll()] for Ant [pattern='/oauth/token_key']
13:57:15.155 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [isAuthenticated()] for Ant [pattern='/oauth/check_token']
13:57:15.165 INFO org.springframework.security.web.DefaultSecurityFilterChain.<init>() @55 - Will secure Or [Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']] with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1715471a, org.springframework.security.web.context.SecurityContextPersistenceFilter@39c4ff6a, org.springframework.security.web.header.HeaderWriterFilter@1dd2b124, org.springframework.security.web.authentication.logout.LogoutFilter@276931c8, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@25ac2e09, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5b3977b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7a22601a, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4d9e81ea, org.springframework.security.web.session.SessionManagementFilter@65b44c8, org.springframework.security.web.access.ExceptionTranslationFilter@1202c487, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1884a702]
13:57:15.175 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [authenticated] for any request
13:57:15.175 INFO org.springframework.security.web.DefaultSecurityFilterChain.<init>() @55 - Will secure org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration$NotOAuthRequestMatcher@4405cf2c with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@47946ba1, org.springframework.security.web.context.SecurityContextPersistenceFilter@5f1bd95b, org.springframework.security.web.header.HeaderWriterFilter@c603be5, org.springframework.security.web.authentication.logout.LogoutFilter@21acfb59, org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter@a2e077c, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@3bdde833, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@36ef43be, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6a642abc, org.springframework.security.web.session.SessionManagementFilter@79fdff10, org.springframework.security.web.access.ExceptionTranslationFilter@54a61083, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3f9718de]
13:57:15.195 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [hasIpAddress('127.0.0.1') or hasIpAddress('::1') or isAuthenticated()] for Ant [pattern='/**']
13:57:15.195 DEBUG org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource.process() @72 - Adding web access control expression [authenticated] for any request
13:57:15.195 INFO org.springframework.security.web.DefaultSecurityFilterChain.<init>() @55 - Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2d8aabe8, org.springframework.security.web.context.SecurityContextPersistenceFilter@f20d544, org.springframework.security.web.header.HeaderWriterFilter@5cbdfc31, org.springframework.security.web.csrf.CsrfFilter@7e8a74cc, org.springframework.security.web.authentication.logout.LogoutFilter@cf83769, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1d584e6b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@2eb77585, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@20e8f0e6, org.springframework.security.web.session.SessionManagementFilter@6b5817fb, org.springframework.security.web.access.ExceptionTranslationFilter@4fabb82b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@facdff6]
13:57:15.195 WARN org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild() @322 -
********************************************************************
********** Security debugging is enabled. *************
********** This may include sensitive information. *************
********** Do not use in a production system! *************
********************************************************************
13:57:16.196 INFO org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer() @58 - LiveReload server is running on port 35729
13:57:16.206 INFO org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.<init>() @58 - Exposing 1 endpoint(s) beneath base path '/actuator'
13:57:16.282 INFO org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start() @220 - Tomcat started on port(s): 9090 (http) with context path '/api/v1.0'
13:57:16.292 INFO gr.daem.springrestgeneric.SpringRestGenericApplication.logStarted() @61 - Started SpringRestGenericApplication in 4.092 seconds (JVM running for 4.675)
13:57:16.411 INFO org.springframework.web.servlet.DispatcherServlet.initServletBean() @525 - Initializing Servlet 'dispatcherServlet'
13:57:16.411 INFO org.springframework.web.servlet.DispatcherServlet.initServletBean() @547 - Completed initialization in 0 ms
13:57:18.390 INFO Spring Security Debugger.info() @56 -
************************************************************
Request received for GET '/generic/status':
org.apache.catalina.connector.RequestFacade@57ece8c5
servletPath:/generic/status
pathInfo:null
headers:
user-agent: PostmanRuntime/7.29.0
accept: */*
cache-control: no-cache
postman-token: 5cf5e7b5-a4fe-4fb7-b420-91bec32d580c
host: localhost:9090
accept-encoding: gzip, deflate, br
connection: keep-alive
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
OAuth2AuthenticationProcessingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
13:57:18.393 DEBUG org.springframework.security.web.FilterChainProxy.doFilterInternal() @208 - Securing GET /generic/status
13:57:18.394 DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter() @102 - Set SecurityContextHolder to empty SecurityContext
13:57:18.395 DEBUG org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor.extractToken() @54 - Token not found in headers. Trying request parameters.
13:57:18.395 DEBUG org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor.extractToken() @57 - Token not found in request parameters. Not an OAuth2 request.
13:57:18.395 DEBUG org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter() @141 - No token in request, will continue chain.
13:57:18.396 DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter() @100 - Set SecurityContextHolder to anonymous SecurityContext
13:57:18.398 DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor.attemptAuthorization() @247 - Failed to authorize filter invocation [GET /generic/status] with attributes [#oauth2.throwOnError(authenticated)]
13:57:18.414 DEBUG org.springframework.security.oauth2.provider.error.DefaultOAuth2ExceptionRenderer.writeWithMessageConverters() @101 - Written [error="unauthorized", error_description="Full authentication is required to access this resource"] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7b42bf94]
13:57:18.415 DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter() @118 - Cleared SecurityContextHolder to complete request
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
