Integrate an IM chat server to existing Spring server - spring

I'm trying to integrate an openFire XMPP server to my current company Spring server but have two major questions I cannot find the answer to -
I'll start with my current architecture first -
1. The xmpp server have a DB-server of it's own seperated from the Spring server DB, This is a dedicated machine to keep the users char history etc
2. The spring server have a DB of it's own where it keeps the user credentials (md5 encrypted) and also client applications data
3. The spring server is dedicated to serve HTTP requests (a dedicated REST server)
All in all I have 2 DB servers once chat server and one Rest server
Now for the questions -
1. Can I forbid registration to the xmpp server (i.e. whitelist the rest server ip and let it be the only one who can create users after a user registers on it)?
2.For security reasons the Rest server switch the session for a logged in user every 2 days the iOS and Android clients deal with session managment locally - How can I use those session with the XMPP server?
To clarify - I want the users to be able use the xmpp server only for chat purposes but only after they logged in to the application itself since the user session may expire the chat client will also have to re-authenticate against the REST server, how can I achieve this?
3. Won't it create an overload on the REST server? (i.e. the Rest server will now have to handle client requests and also XMPP server requests)
4. What is the best architecture to achieve this kind of a system (chat server, db server for chat server, rest server, db server for rest server) so that the system can scale horizontally?
I searched google for an article or something related to describe the general architecture but couldn't find nothing relevant, since I'm not "inveneting the wheel" here I would love to hear a good advice or be directed to an article that explains the How-To's
Thanks in advance.

The standard way in XMPP world for user authentication is SASL.
SASL have a very simple model: server sends to client some "challenge" string to client, and client sends "response" string to server, and they repeat this until server decides client send all required data. What data to send is defined in SASL "mechanism". There are number of well-known SASL mechanisms, e.g. SCRAM, and they are provided by most XMPP servers and clients "out of the box".
Your problem is - you already have authentication system and user database and want to reuse it for chat purposes. There are two ways:
Add your custom REST authentication as SASL module to your server. Google say it is already possible to write and add Openfire SASL plugin. Your SASL REST mechanism will do the same things as for browser, but required urls, tokens, etc. will be wrapped as "challenges" and "responses", e.g. server will send REST auth url as "challenge" for client, and client will open url, post credentials, get a token and send them as "response" back to server. Of course you need to add this SASL REST mechanism in client too.
Adopt your XMPP server to use your authentication database directly. In this case you only need to modify Openfire code to link it with your users/passwords tables (maybe there is already an admin tool for this). In this case clients will continue to use standard SASL mechanisms without modification. When this way may be easier than first one, remember your XMPP server should have access to plain-text passwords, which may be insecure.
You questions in order:
Yes, you can disable registration from XMPP client and point users to registration website.
You will see chat sessions in Openfire administration console and able to stop them, also you can write a module for do this by your schedule
If you will write SASL REST mechanism, there will no any difference between requests from chat clients and web clients for your REST backend, they will look the same.
As I described first, you no need separate DB for chat server and you able to setup multiple chat servers connected to your REST backend.

Related

Spring Boot WebSocket Questions

I am new to Spring framework, now I chose it for a new project.
The project is actually an online consulting application. when a customer chooses to query by open page window, A consulting engineer will be assigned to him(many to one). to sum up, this app requires the following considerations.
1- anonymity connections for customer and authentication for consulting engineers.
2- one engineer can serve several customers at a time.
3- the way to assign customer could be configured.
4- WebSocket session should remain open while HTTP session expired.
so I have two questions:
for 1-3 items, I am not sure if I should choose STOMP or plain WebSocket in Spring. it seems STOMP is more advanced but more likely to fit a general messaging requirement (topics, subscriptions ... etc). WebSocket in another hand is simpler and more flexible. I wonder which one is better in this consulting application?
for point 4, session expired. google result suggests spring-session. but I can only found its tutorial about integration spring-session with STOMP. if WebSocket is the better choice, how can I integrate spring-session with Plain WebSocket?
Thanks
When you talk about websocket you have to have in mind that it is a simple and "raw" communication protocol without many defined message controls. If you choose to use plain websocket you should be able to authenticate using basic authentication [1]. In this case, your websocket connection, once opened, will stay open and working indefinitely.
But it's also up to you to control the message flow, deciding how to specify the target for each message. That's where STOMP should help you.
Using STOMP you could define "channels" to which customers and consulting enginners would "subscribe" to and begin communication. And you could also send private messages using the "Principal" from an authenticated Spring Security session.
So, answering your points:
1- anonymity connections for customer and authentication for
consulting engineers.
It is possible to define multiple endpoints within Spring Websocket configuration [2]. You could try to request authentication with only one of the endpoints using a implementation of ChannelInterceptorAdapter.
2- one engineer can serve several customers at a time.
Using the definition of channels, with the help of STOMP, you could subscribe the enginner in multiple channels, each for one customer... Or use private messages between them.
3- the way to assign customer could be configured.
I'm not sure what you meant... But it should be easy to assign a customer to a "channel".
4- WebSocket session should remain open while HTTP session expired.
The HTTP session is only used in the initial process, to connect to the websocket. After that the websocket will remain open or, if you use SockJS for fallback, the HTTP session will be constantly renewed.
I have coded an example of websocket server and client using Spring API. It's not exactly what you need, but I think it'll give a good idea.

websocket, how to not allow cross domain access?

Since the Origin does not work in the case of non-browser clients: non-browser clients can connect to a Websocket server with a fake origin. Non browser clients thereby can do requests that a programmer want through a program. How to stop this? I want that only my script hosted on my domain can connect to my websocket server. This page offers a “ticket”-based authentication system: https://devcenter.heroku.com/articles/websocket-security
However, it looks like it does not solve this problem because any non-browser clients from anywhere can have a ticket also.
I want that only my script hosted on my domain can connect to my websocket server.
Please tell me how to solve this. Thanks.

OAuth2.0 with horizontally scaled servers

I am writing a simple Spring REST api, which I plan to integrate with Oauth2.0 authentication for security. I am aware of the authentication flow and the refresh and access tokens.
My Question is if I horizontally scale my server app, how can clients talk to different servers with access tokens received from another server? Does the client have to authenticate with the other servers too?
Typically in such kind of a deployment you will have one Authorization server and all the other servers will accept the token, validate it with the Authorization server and then serve the request. Check the layout below. You can have a couple (at least 2) to avoid single point of failure of the authorization server.
So in the flow below client can go to server1, 2 or 3 but they will essentially do the same.
There are other ways but this simpler.

Verifiying answers from application to web service and vice versa

Scenario:
My Application stands in connection to Web service (Master Server). Sometimes i make calls like login on application startup, where my application sents user credentials to the master server for validating.
So, how do i 1st validate that the answer is from my real server and not a fake local webserver with routed hosts file? And 2nd how do i parse this answer?
I always parsed like this (dummy code):
if($answerFromWebserver == "LOGIN_OK") {
doLogin();
}
Are there better, more safe solutions?
some of the security feature I see/use,
You can allow specific IPs to server, can setup firewall for this.
Setting up SSL/HTTPS will be great benefit to secure transport level.
You can send username/password encrypted with every message, so at server side authentication will took place each time. You can use SOAP header for this.
You can read huge article from ms here on securing services..

Websockets (Socket.io) and authentication/authorization

I'm giving socket.io a whirl and I'm curious as to what I should and shouldn't be doing with websockets.
For example is there a way to authenticate a websocket (include id in every message perhaps?)? Let's say I'm creating a 'google docs' like app in which people can create new documents. Should I be using AJAX to create new documents instead of websockets? That way I can use the standard HTTP transport layer to do all of the user authorization (checking session, etc) and then simply ping back the page with a websocket event. Curious as to how people handle situations like this.
I would recommend using AJAX wherever you do not absolutely need web sockets. Web sockets end up creating more load on the server side (socket.io will take care of fallbacks in case web sockets & flash sockets are not available). In short, use web sockets where you need to maintain that state/connection to the client.
If you wish to use web sockets, using cookies with socket.io would be one approach that would allow you to keep track of your sessions. If not using socket.io right away, you can send req.sessionID (key) to the client, store the session information in Redis/Mongo etc. When the socket.io connection is attempted, read the cookie value & send it to the server - where you can get the session store information. There may be issues if you use flash sockets as one of the fallbacks.
Hope this helps.

Resources