Chat Application using Spring boot RSocket - spring

I am using Spring boot 2.5.0 with the react front end.
Trying to use RSocket for building a chat application.
Came across the following links. But, still not clear on sending message to a particular user.
RSocket doc -->
https://docs.spring.io/spring-framework/docs/5.3.8-SNAPSHOT/reference/pdf/rsocket.pdf
Medium -->
https://medium.com/swlh/building-a-chat-application-with-angular-and-spring-rsocket-3cd8013f2f55
RSocket Demo ->
https://github.com/benwilcock/spring-rsocket-demo/blob/master/rsocket-server/src/main/java/io/pivotal/rsocketserver/RSocketController.java
My application is a multi tenant application. Each tenant might have 3 to 10 users.
Use cases, For any given tenant,
Store messages in the server
Should be able to list the users online
Send message to all users belongs to a particular tenant
Send message to a particular user from a tenant
I have the following config.
In build.gradle,
implementation 'org.springframework.boot:spring-boot-starter-rsocket'
application.properties,
spring.rsocket.server.mapping-path= /rsocket
spring.rsocket.server.transport= websocket
RSocketController.java
#MessageMapping("fire-and-forget")
public Mono<Void> fireAndForget(final Message request, #AuthenticationPrincipal UserDetails user) {
return Mono.empty();
}
Here, I am able to get the user message and need to route this to a particular user/users. How can I find all users online and route message to a particular user/users?

Related

How can i secure web sockets using spring security?

I'm trying to implement a notification service for my final project. therefore I want to know how to send data to specific users through a socket.

Spring Boot, Spring Security - Pass current logged in user details from one micro-service to another micro-service

I am using 2 microservices. One is for UI (Web + API) and another one for the backend service(REST API). And using Feign Client to connect from UI to the backend API.
Now I need to pass the current logged in user details from the Web service to the backend API service.
I am getting the user details using SecurityContextHolder.getContext().getAuthentication().getDetails().
What is a good way to pass the user details? I need user details in all the API endpoints for auditing.
Is it good to pass user details using #RequestParam?

Accessing Tenant Information with Spring OAuth2

I have an application that needs to pull tenant information on a per method basis. I am using Cloud Foundry's UAA server for my Authentication and Authorization needs. I have tried to access tenant information by doing the following:
#RequestMapping("/")
#PreAuthorize("#oauth2.hasScope('project.retrieveItems')")
public List<ItemDto> retrieveAll(OAuth2Authentication token) {
... Code here to retrieve Identity Zone and use it to filter results.
}
The OAuth2Authentication object doesn't have any information about the Tenant, only the scopes and authorizations. Is there anyway to get this information from a method?
Thanks for any assistance.
IdentityZoneHolder.get()
will return the current tenant that is being accessed within the UAA (if you're coding within the UAA itself)
But I take it that you are asking about your application, the core Spring Security Oauth2 implementation has no idea about tenants
It only has awareness of a token url and a check token url.

Securing microservices behind a entrypoint with Spring Security

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)
...
}
...
}

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

Resources