Adding spring security to Zuul service in spring boot micro service - spring

I am new to micro service architecture.
We have few services like zuul service (api gateway), security service (connect to db check access) and xyz service.
I would like to know, how we can add spring security to the routes defined in the zuul service. ?
On defining authorizeRequests like below on zuul service, it should call security service internally and authenticate the requests.
Example:
.authorizeRequests()
.antMatchers("/user/count").permitAll()
.antMatchers("/user/**").authenticated()
Note: /user End point is defined in the security service.
Please help me with this.

Our Zuul proxy is supporting OAuth2 security. An example of the security config is this:
#Configuration
#EnableResourceServer
public class JwtSecurityConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.antMatchers("/**").hasAuthority("ROLE_API_ACCESS")
.and()
.csrf().disable();
}
}
I would assume if you are doing basic auth you could do something similar using the appropriate class. Maybe something like this.
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
BasicAuthenticationEntryPoint authenticationEntryPoint = new BasicAuthenticationEntryPoint();
authenticationEntryPoint
.setRealmName("EnterpriseDeviceAuthentication");
http
.authorizeRequests()
.antMatchers("/health").permitAll() // allow access to health page
.antMatchers("/somepath").permitAll()
.antMatchers("/somepath2").permitAll()
.antMatchers("/bootstrap.min.css").permitAll()
.anyRequest().hasAnyAuthority(SecurityRoles.ALL_SECURITY_ROLES)
.and().httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}
}

Related

Spring boot how to have Thymeleaf web page and REST API with different authentications Schemes

Like the question said, how we can configure Spring Security to have form authentication for the Thymeleaf web page part of the project, and JWT authentication for the REST API part of the project?, because we like to have both projects on the same container and not to have to resource to external Tomcat Application Server to have the same Security Config (SSL, Ciphers, Certificates, ETC.).
So far we don't found how to do it, but if you can have a Thymeleaf and REST API on the same project i think it is possible to configure Spring Security to have to ways of authentication on the project.
You can have this behavior by adding two WebSecurityConfigurerAdapter beans as follows:
#Order(1) - /api/** protected by basic auth, in your case JWT
authentication.
#Order(2) - /website/** protected by form login, in your case
Thymeleaf login.
View docs for Spring Boot and sample code here.
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole("API_USER")
.and()
.httpBasic();
}
}
#Configuration
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/website/**").hasRole("ADMIN")
.and()
.formLogin()
.and()
.logout().permitAll()
;
}
}
}

How to support basic authentication and bearer authentication for the REST API project

I am new to Spring Security & still learning it so my question can be naive please bear with it.
I have Sprint Boot Rest API project which exposes certain APIs. I have already implemented the bearer token based authentication for all the APIs.
e.g /user , /resource, /appointment
Now for few apis for a particular controller I would like to have the basic authentication implemented. These Apis will be consumed by another service which is not exposed to public.
In order to have the security for the APIs I would like to have basic authentication in place for these apis.
e.g /internal/api1 , internal/api2 .. and so on
I am not able to distinguished between urls in the ResourceServerConfigurerAdapter & WebSecurityConfigurerAdapter. Also not sure which should be used for adding basicAuth() using the antmatchers
What you want, by reading your problem, is to have two authentication types (token and httpBasic) for two diffetent endpoints. It can be achieved by creating two different WebSecurityConfigurerAdapter beans. Spring Boot enables this and can be done like bellow:
#Order(1) - /resource|user|appointment/** protected by bearer token authentication.
#Order(2) - /internal/** protected by basic auth.
View docs for Spring Boot and sample code here.
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/resource/**")
.antMatcher("/user/**")
.antMatcher("/appointment/**")
.authorizeRequests()
.anyRequest().authenticated()
.and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
#Configuration
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/internal/**")
.and()
.httpBasic();
}
}
}

how to IP white list /oauth/check_token endpoint in spring security

I have two applications (war), one acting as a Resource Server and other is my Auth Server running on two different servers. I am using client_credentials grant_type. I need to white list the IP of my resource server so that nobody else can access the "/oauth/check_token" end point directly using post-man or browser or any other user-agent. Here is the code snippet from auth server :
#EnableAuthorizationServer
#Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isFullyAuthenticated()")
.allowFormAuthenticationForClients().realm(REALM + "/client");
}
...
some other configuration code related to ClientDetails and tokenStore.
...
}
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers(HttpMethod.GET,"/oauth/check_token").access("isFullyAuthenticated() and hasIpAddress('0.0.0.0/0')").accessDecisionManager(accessDecisionManager)
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
I found a way to whitelist IP in spring :
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.anyRequest().access("hasIpAddress('0.0.0.0/0')");
}
But this is not helping in my situation because it is only checking for fullyAuthenticated(). I want all the resource server should be authenticated and authorized before accessing "/oauth/check_token"
Edited
I have referred to a similar kind of problem : How to find users' IPs in Spring Security? but it wasn't helping me because in that question they were trying to authorize a resource server Api, but in my case i want to authorize spring-security default endpoint i.e; /oauth/check_token
On further debuggin I found that if I remove .antMatchers(HttpMethod.GET,"/oauth/check_token").access("hasIpAddress('0.0.0.0/0')").accessDecisionManager(accessDecisionManager)
i am still able to use /oauth/check_token endpoint.
Then I tried to change fullyAuthenticated to permitAll() in AuthorizationServerSecurityConfigurer.checkTokenAccess("permittAll()"); it started allowing everybody to access check_token endpoint. Which implies it isn't even reading the configuration from .antMatchers(HttpMethod.GET,"/oauth/check_token")
Now I am confused how to configure hasIpAddress() and do we need to explicitly mention antMatcher("/oauth/check_token") or it is provided by default.
You can model it like this, which keeps both requirements - IP whitelisting and all requests are authenticated. You can remove the localhost access rule if not needed:
http
.authorizeRequests()
.antMatchers(GET, "/oauth/check_token")
.access("isFullyAuthenticated() and
(hasIpAddress('IP_OR_NETWORK_OF_RESOURCE_SERVER')
or hasIpAddress('127.0.0.1/32'))")
.antMatchers("/**").fullyAuthenticated();

Spring Boot - How to secured the dashboards like Hystrix for admin users

I have spring boot REST service with a basic authentication already existing. I have Hystrix integrated to short circuit external services and a dashboard to monitor the same. But how to secure Hystrix dashboard for an admin user?
Thanks,
Arun.
Configure Spring Security to enforce basic auth on /hystrix endpoint. For example:
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/hystrix")
.authenticated();
}
}

Spring Boot Management security works differently with port set

I'm trying to configure a Spring Boot application (1.2.3, but this also fails with the 1.2.4.BUILD-SNAPSHOT version) with Actuator support. I want to use the Actuator security config for controlling access to the management endpoints, and our own authentication for the rest of the application.
Here is my security config:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
#Autowired
private CustomAuthenticationProvider customAuthProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(customAuthProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.regexMatchers(API_DOC_REGEX).permitAll()
.regexMatchers(String.format(PATH_REGEX, PUBLIC_ACCESS)).permitAll()
.regexMatchers(String.format(PATH_REGEX, INTERNAL_ACCESS)).access("isAuthenticated() && authentication.hasOrigin('INTERNAL')")
.regexMatchers(String.format(PATH_REGEX, EXTERNAL_AUTHENTICATED_ACCESS)).authenticated()
.antMatchers("/**").denyAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.addFilterAfter(customAuthProcessingFilter(), BasicAuthenticationFilter.class)
.csrf().disable();
}
}
This works correctly when I don't set a management port, but when I set the management port, the management URLs return 401 responses. If I comment out the line .antMatchers("/**").denyAll(), then everything goes through without requiring authentication at all. So it looks like it is using my application's security config for the Actuator endpoints when I set a custom port, but I'm not sure why.
How do I get it to use it's own security when running on a custom port?
Expanding on the comment from #M. Deinum, adding another adapter for the Management stuff (even though it already has one) seems to have fixed it. This is the class I ended up with:
#Order(0)
#Configuration
public class ManagementSecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
ManagementServerProperties managementProperties;
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.requestMatchers()
.requestMatchers(new RequestMatcher()
{
#Override
public boolean matches(HttpServletRequest request)
{
return managementProperties.getContextPath().equals(request.getContextPath());
}
})
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}

Resources