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
Related
I have gone through many posts and articles but didn't find a straightforward solution for the case below which I have to implement.
Platform: Spring Boot 2.x.x (Spring Security 5.x.x) with embed Tomcat
Solution: REST service that consume many client apps and many end users.
I have to implement a REST end point /api/search which accessible for many client application. As an example, web application APP-X (Angular), web application APP-Y(Jquery/Bootstrap) and mobile application APP-Z (IOS). All three clients are separate entities (both technical perspective and business perspective).
So I have to authenticate above application using onetime token. Therefore I planned to go for Spring OAuth2 by enabling #EnableAuthorizationServer and #EnableResourceServer. For each app client I’ll generate a token and they can use it when they connect with my REST service. Is this approach correct?
Apart from the app clients system has capability to register and login functionality for end users. Also my end point (/api/search) can access both anonymous users and users who registered under ROLE_REGUSER role. And through the security context, I need to access the user details as usual user authentication.
This is the place I got stuck. How can I handle the following points together using Spring Security 5.x.x (Spring Boot 2.x.x).
I. Both client apps and end users authentications.
II. Allow access for anonymous users and registered users for same end point.
I have attached small diagram to elaborate the above scenario.
Thanks
I found a solution when I upgraded my spring security version to 5.2. In version 5.2, they have depreciated #EnableAuthorizationServer and #EnableResourceServer. So I had to move with an external authorization provider who supports auth2. I chose AWS Cognito, and fulfill the above requirement, using the user pool option.
In AWS Cognito
I created a user pool.
Then created two app clients in the same user pool.
One app client configured as support to the client credentials flow.
The second app client configured as support to the user authentication flow.
In client applications
Retrieve access token directly from AWS Cognito using client credentials and used to secure all API calls.
If a user login at any stage, retrieve access token directly from AWS Cognito using the authorization code and replace any existing access token.
The advantage is, the resources server can validate any access token that generated related to the same user pool.
In resources server (backend API/Spring Boot)
Validate access token.
I am fairly new in microservices architecture. I've been trying to build a microservices stack using Spring Boot, Spring Cloud and Netflix OSS libraries.
I want to know what is the correct way and place to store session.
Here is an overview of the infrastructure that I created:
OAuth2 backed Authorization/Authentication Server
UI Service (Spring Boot, Front end service)
Backend Service-1
Backend Service-2
Redis Server to store session and other cachable data
Discovery Server (eureka)
Currently, I'm trying to store session in Redis by configuring UI service to perform it. It seems to be working fine, although I haven't had the chance to try it for multiple service instances. However, I'm already having serialization/deserialization issues while developing.
By the way, trying to store the session on front end app is the correct place to do or it should be done in Authorization/Authentication service as authentication is processed in that service?
Here is my Session config in UI service (front end service)
#Configuration
#EnableRedisHttpSession
public class SessionConfig extends
AbstractHttpSessionApplicationInitializer {
public SessionConfig() {
super(RedisConfig.class);
}
}
To sum up, I'm expecting to achieve and use best practices on this project. Your kind assistance would be appreciated.
The idea of a general server side user session and a microservices style architecture don't go together well. The reason being that you are likely to break the separation of concern that you use separate the domain boundaries of your services.
Remember, every service is supposed to service a specific domain problem autonomously - including all required data persistence. So for example if there is anything to remember for a users connected devices you would do that in the one service that is responsible for those device connections and nowhere else. The service would be responsible for processing those request and persisting any status that the devices require. Similarly when there is anything to remember about he users authorization you would do that in the authorization service.
And regarding the question to use Redis or not - In a microservices architecture the choice of storage system would be up to the service architect. Maybe one service stores its data in a relational database, maybe another uses a key-value-store and yet another may use an event queue system or a time series database.
So in summary you have to ask yourself what your session really is used for and make the corresponding services responsible to persist that information in a domain specific way. (If you give some more details in your question about this, I can give you my opinion).
I am working on a Spring boot application and have received a requirement where a certain endpoint must be accessible only by authorized users that too the user must be present physically at the system serving the app. An optional case is the user could also be able to access the endpoint if the user has SSH access to the server. This makes me think that some sort of key (a file or a program) can be used to unlock the endpoint. Not being a person proficient in security, this has put me at a loss on how to implement such a feature using Spring Boot. Any help is appreciated.
Spring boot doesn't have built in support for this scenario, but what you actually need is PAM (Linux Pluggable Authentication Modules) port for java (JPam can be a good solution).
You can write your own AuthenticationProvider for spring security which will do something like this in it's validation method:
Pam pam = new Pam();
boolean authenticated = pam.authenticateSuccessful(username, password));
This library is good enough documented (pdf)
Another PAM for java solution can be found here libpam4j
I am developing a RESTful web service as a back-end layer for mobile application. This service receives combination of device id (as user id) an a pin (as password), and passes to another back-end service, that validates and returns the status of successful login along the user information, in case, the user is authorized. My service is not validating the user. And mobile sends sub sequent requests to my RESTful service.
So, please suggest, how can I make all this system(especially the RESTful) secured, using Spring security.
I am using a Tomcat server, Spring and Jersey
I recently implemented a method to secure my existing RESTful APIs in Spring. I have used a token based authentication model using OAuth2. In my project, I wanted to secure my API's in a way that every request is individually authenticated and authorised based on the token present in the header. If this is something you are looking for, then I would highly recommend you to take a look at the documentation here. If there is anything you are stuck at while implementing it. Please do let me know.
Also, you can find multiple projects for Spring and OAuth here
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)
...
}
...
}