Securing microservices behind a entrypoint with Spring Security - spring

Anyone know what the simples way to secure a microservice architecture that is behind a entrypoint?
The case is, we need a server that takes a TCP socket connection. The implementation to authenticate a user on this application is already implemented and it basically uses Spring Security with UserDetailsService and assigns the socket connection with the specific TCP connection.
But now we are considering going for a more microservices architecture, but we are having problems finding a good way to propagate the user to the different services.
E.g.:
User connects to TCP Socket server, authenticates.
User sends a request through the socket, the server propagates the call to another backing service (e.g. a Spring Data REST repository), but the call the client makes (e.g. a change request for a set of data) needs a specific user role. How can this role be checked?
So basically, the TCP server is issuing a service request on behalf of the user.

It depends on the authentication procedure. If you already use a Single Sign On capable authentication such as CAS 2, you can add Spring Security on your micro services using the proxy feature of CAS.
If you micro services are hidden behind your front end application, that is if no user can directly contact them, you can simply pass the user id in the request between front end and micro service. As the micro service can only be hit from a trusted application, you can directly use the user id.
If you want to make use of advanced spring-security features (#PreAuthorize, #PostFilter, ...) in the micro services, you can use a custom PreAuthenticatedAuthenticationFilter in the spring security configuration of the micro services, whatever the authentication procedure is. That filter would simply use the user id passed in the request to set the user authentication token.
All those solution allows not to cache the password in the front-end application, which is allways possible (in a session attribute) but looks as a bad security practice.
Anyway, you can use stateless security for the micro services part, since the frontend will always send a user id. According to Spring Security Reference Manual, it is as simple as adding an attribute to the http config : < http create-session=stateless> (this parameter exists since version 3.0)
If you use java configuration, you can do the same from a WebSecurityConfigurerAdapter :
class SecurityConf extends WebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity http) {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
...
}
...
}

Related

How to propagate User's authentication (and authorization) to other microservices

I've created a microservice (using Spring boot) for landing page. User provides the credentials and upon successful login, he can see the dashboard. I've used RestTemplate in-order to traverse to other microservice from the dashboard. Below is the code snippets:
#Autowired
private RestTemplate restTemplate;
#GetMapping("/employeeCenter")
public String openEmployeeCenterApp() {
logger.info("Invoking EmployeeCenter micro-service");
return restTemplate.getForEntity("http://EMPLOYEE-SERVICE/empCenter/", String.class).getBody();
}
Which is working fine. But I would like to propagate the User's authentication (and authorization) to any other microservices; so that based on the user's privilage, I can show/hide stuffs. What would be the suitable way to do that?
There are many concerns here.
When a "landing page" service (let's call it "A") shows the dashboard for user with identity "Foo" and tries to contact an another service "B" which is an another process via Rest template, you should implement the identity propagation of "Foo", its not the job for the spring security. Spring security will help you in authentication / authorization of user "Foo" inside the service "A", but it has nothing to do with identity propagation.
After all, service "B" can be something not written with spring or java at all, or even some external system.
There are many approaches here depending on requirements that usually boil down to:
Rely on the fact that only landing page (service A) is your "gateway" to the outer world and hence on this service requires security
Protect all the services (like putting spring security or any other security component in each service)
Like "1" but differentiate between security gateway and landing page - have two microservices, so that gateway will be protected and will be "opened" to the end users but also to internal communication. The difference is that if you need to call service "B" from service "A" you can do it through the gateway and it will check the security
Another concern here is what exactly means the "act" of calling the service B from service A.
One thing is to tell "I'm user Foo (currently in a Service A) and I'm calling B as Foo.
Another thing is telling "I'm service A (that has its own identity) and I'm calling service B on behalf of user Foo".
All these question are in domain of security related architecture and many solutions can be adopted. If you have to do such an analysis (although its kind of out of scope for this question) make sure that you understand that performance implications of each approach:
- HTTP hops can be expensive
- DB hops (in case you have to turn to the database) are expensive
Apply caching wherever possible
Now, technically speaking, you should provide some Filter that will add Identity Headers taken from the Thread Local or similar solution if you run reactive stack.
So in the most simple situation you can put an identity object on some thread local and get it in the filter to add requests.
So that bottom line when you construct a request in a RestTemplate (that in turn relies on okHttp, Apache Http Client or whatever) it will have additional headers that will provide the identity information (and again its up to you to decide what exactly is an "identity" here).
The service "B" in turn should parse this object again in some kind of filter (ideally before it hits the rest controller if "B" is in spring as well) or even with spring security if you have it installed on Service B, and make its "protection decisions" based on that identity, then again, put it on thread local if B will query other services and so forth.
You can try using WebSecurityConfigurerAdapter and override the configuration of AuthenticationManagerBuilder bean which will let you set roles.
This article has a good example: https://www.journaldev.com/8748/spring-security-role-based-access-authorization-example

Do I need to do authentication during the message transfer

I need to use activemq to communicate between micro-service and the system has access control to limit the user action. I already check the user from restful endpoint by spring security. After authentication, I send message to queue. Do I need to verify the user again? If yes, how can I pass the user credential by activemq.
If it is microservices architecture already. And as what you said you have an authentication/Authorization micro-service then there is no point duplicating the checks all over again.
The best approach is to let the Gateway-Service do the authentication/authorization thing.
Usually it is bound to the Zuul implementing service. So that all calls to specific service URL got intercepted by that gateway and apply whatever security policies you have

How to use spring remoting with hessian and spring security?

We have a three tier architecture and we are using spring remoting in combination with hessian. Currently we have a client app and the business app is running on two different tomcats.
Tomcat 1 Tomcat 2
---------- ------------
| client | -> | business |
---------- ------------
exposing services for clients
But we came across a security problem. Our exposed services (business app) requires a logged in user with special rights, for example ROLE_SUPERVISOR. The client application has a login form and the credential validation is done by the business app (the client app has no database connection). This means that the user is only logged in on the client application, the business app knows nothing about it (and this is maybe the main problem).
We thought it is possible with spring security remoting to send all needed information from the client to the business app (i.e. the authentication object). But unfortunately this can not be done. So, we have to find another solution.
One solution could be to send the authentication object along with every request. But this may have another security issue. The authentication object which is sent by the client, can be faked by an attacker. In this case we have to check the users' credential for every request and load his roles (granted authorities) to be sure, that he is authorized.
The second solution is that both apps are aware of the logged in users, which means, when a user logged in with the client app, he is also logged in in the business app. But, nevertheless, the user (or authorization) object must be sent with every request.
Maybe we are missing something. Isn't there a better / easier way to do this with spring security and spring remoting. A three tier architecture isn't unusual and there must be a way to secure the exposed services.
Update
spring remoting with hessian: client side configuration (java config)
#Bean
public HessianProxyFactoryBean xyService() {
HessianProxyFactoryBean xyService = new HessianProxyFactoryBean();
xyService.setServiceUrl(remotingUrl + remotingContextPath + "/XyService");
xyService.setServiceInterface(XyService.class);
return xyService;
}
business side:
#Bean(name = "/XyService")
public HessianServiceExporter xyService() {
HessianServiceExporter hessianServiceExporter = new HessianServiceExporter();
hessianServiceExporter.setServiceInterface(XyService.class);
hessianServiceExporter.setService(xyServiceImpl);
return hessianServiceExporter;
}
I appreciate your help!
Thanks, Daniel

Spring security Filters and Authentication in Spring Web Services

I had recently been able to secure my web application and authenticate the user by using basic authentication. An added requirement was to check against user's ip address from request parameter and I leveraged use of Custom authentication details source and override of BASIC_AUTH_FILTER. (see:http://stackoverflow.com/questions/9854592/accessing-httpservletrequest-during-daoauthenticationprovider-authenticate-in-sp)
Now I have a Spring Web Service that uses SimplePasswordValidationCallbackHandler and the same AuthenticationManager / Provider configuration as above (except for the http namespace configuration which has all my custom filter logic).
I would like to do a similar activity to authenticate a user completely only if their ip addresses match when authenticating in a Web Service.
I pass the username and password in the SOAP headers and authentication happens without any issues.
Any thoughts if i can reuse my existing configuration here for the AuthenticationDetailsSource and Custom filter. Is this even achievable or am I on a completely different track here?
Thanks.
I added a RequestContext Listener to my web.xml and got access to the HttpServletRequest using a RequestContextHolder during my authentication process in a custom DAOProvider.
Anyone with a better solution, let me know !

Spring Security - is Role and ACL security overkill?

I have a 3 tier application that requires security authorizations be placed on various domain objects.
Whether I use Spring's ACL implementation or roll my own, it seems to me that ACL based security can only be used to authorize (service) methods and cannot be used to authorize URL or web service invocations. I think this because how could a web service call check the ACL before it has hydrated the XML payload? Also, all the examples for web access security in the Spring documentation are securing URL's based on Role.
Is it typical to use Spring's roles to secure web presentation and web service calls, while at the same time using ACL's to secure the business methods? Is this overkill?
Is it typical to use Spring's roles to
secure web presentation and web
service calls, while at the same time
using ACL's to secure the business
methods?
Yes.
This is simple to do in your controller by combining the request mapping and secured annotations:
#RequestMapping("/some/url")
#Secured( {"ROLE_GET_THE_DATA"} )
public ModelAndView getTheData(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// get the data
// return it in your mav
}
Adding secured annotations to you data access objects (DAO) will complete the security design.
Is this overkill?
That depends on your application. Minimally you should secure your controller. Not securing your DAOs may introduce security holes in the future.
We are working on adding this type of security to our applications.

Resources