I have a web service which authenticates a user, and if successful gives them a JSON Web Token which they can use to persist their session.
Currently I only have one server, but would ideally like to increase that to two or more for the sake of performance, however I'm unsure as to how that'll work with different servers as they'll have different instances of maintaining who is currently logged in.
For example, my service will examine the JWT the client returns, and (assuming it's a good token), will take the user ID and session and check if there is a user logged in with that session ID.
However, if for example, the middleware that precedes the web service layer determines that the server the user was initially logged in is currently unavailable and routes the request to a different server instance of the web service, how is the authentication controller meant to evaluate if the request is valid?
A very basic version of my service can be found below, with the black arrows representing ordinary communication, and the red arrows representing communication in the event that Layer One decides to route the request to Instance Two.
Layer One, in essence is very basic and doesn't really do anything other than route traffic to the next layer dependent on the availability of the layer two instances.
One of the main advantages of JWT is that it does not need server storage because it is self-contained and stateless. If you need server sessions may be JWT it is not your best option to manage authentication. See Stop using JWT for sessions
Currently application servers use the SESSION ID to manage load balancing and redirection to the server that store the user session, including persistent storage and migration of session. Using a JWT you won't take profit of these characteristics.
Use JWT if you need a REST stateless endpoint with authentication or you need to exchange data securely between parties
Related
I have been trying to read through existing information about this topic. I even installed KeyCloak server locally, configured the realm, the client and used Postman to send some requests to KeyCloak, and received some json response.
My problem is that - unless I misunderstand something - none of the descriptions seem to fit my goals.
Our application already has user management and we rely on user identity and roles / access rights configured in the system. The backend runs inside Tomcat and we run a Polymer 1.0 / Javascript frontend to call the REST services of our backend. I cannot get rid of user management as our DB is highly dependant on user to object assignment when deciding the scope of the objects for which the particular user is responsible.
All we need is an extension of our system by the possibility of foreign authentications (like social logins) in the future.
We have now explicit login that delivers a session cookie, Servlet filters to check the presence of this cookie, etc. In the server we use the login token / user identity in each REST call to filter the results from the DB to those available to the particular user.
What I need is a flow like:
in the fronted we check if we have active session (existing code)
if not we redirected the user so far to our own login page, logged in, created the session cookie on server and then returned it. On client side we saved this and added to every REST request as authoriation token.
Now with OIDC I'd like to insert a new unprotected query that checks if OIDC is configured. If not, we keep the old solution. If yes, I'd like to get redirected to KeyCloak login, and - and this is the most important for me - I'd like to get back the user identity (or some role that we associate administratively to the user - using which I could identify one of our configured users.
I tried experimenting with the Tomcat solution but that simply blindly hides the authentication procedure and merely allows or blocks REST access to the backend resources. This is not enough for me, I need some kind of user identity which I can use in the server side.
Also a javascript solution only provides communication between frontend and keycloak, but we need the backend to know who has logged in.
I think this topic and all the used lingo is too complicated for me. Could anyone give me some easy advice how to solve this with best practices?
Thank you very much
If microservices are stateless , how can we manage session in JSP based projects .Assuming I am breaking age old monolith to microservices .
You can't manage session in a stateless server.
What you can do is that storage a unique token and its corresponding information into Redis/MemCache.
You need to storage the token instead of JSESSIONID in client.
The fact that most implementations of microservices in the industry communicate via HTTP does not mean that microservices are meant to be used as web servers.
A microservice:
does not have to communicate via HTTP (though most implementations do, for convenience)
is not meant to receive requests issued by a web browser (although you can use a web browser to issue requests to an HTTP-listening microservice to test it)
is certainly not meant to generate responses containing HTML that can be rendered in a browser.
For these reasons, microservices generally do not have a concept of a session.
If you absolutely must make your microservice session-aware, and retain it stateless (so that it can still be legitimately called a microservice) then you have to have it fetch all necessary session information from your persistence store each time a request arrives, and save whatever parts of it have changed back into the persistence store right before returning its response. But that's not how microservices are meant to work.
Generally, the way we use microservices on the web is as follows:
Either we have javascript running on the browser which maintains session state and issues sessionless requests to the microservice, containing authentication information if necessary, [*] or
We build a conventional web server which maintains session state the traditional way and is therefore not a microservice, and we have that web server internally issue sessionless requests to microservices in order to do its job.
Footnote:
[*] please note that my acknowledgement of the fact that many people do this does not in any way constitute an endorsement of this practice.
I am starting a new project and using javascript based UI as fronted and google cloud endpoints backed by google datastore for data storage.
I don't need to use any of the google services for user login etc. In other words, i will have my own table to store username, pwd and other profile info.
So, the questions are:
1. How will my service based frontend will hold the session?
2. How will it understand that requests are going for which user account to return user specific data?
Also to start with, I have so far created an endpoint which basically returns true or false on passing username to it. (just to mimic valid user or not).
The question is do i really need to configure any security to invoke this api from the javascript client i have?
Even if you want to use custom usernames and passwords, you'll need more than just a process to send and retrieve this data from your endpoint.
Consider using something that's there already. E.g. webapp2 has a basic auth module which allows you to have your own database with usernames and passwords but already has many required security measures in place.
A tutorial I've used to implement this in the past: https://blog.abahgat.com/2013/01/07/user-authentication-with-webapp2-on-google-app-engine/
So the basic answer is Google Cloud Endpoints is best suited for applications which users google accounts as authentication mechanism.
So if you are using cloud endpoints, and wanted to have custom authentication mechanism, you have to create your own.
How will my service based frontend will hold the session?
Upon successful authentication (by any form either user credentials, third party social login etc), you need to setup session for that user eg; by using session cookies.
How will it understand that requests are going for which user account to return user specific data?
Cloud Endpoint cannot tell that, so you have to write an custom filter or interceptor to check if valid session or cookie exists and either reject or continue the request.
To pass the current authenticated user who is requesting the api, you need to inject the user informations somehow (using DI, or request properties etc) into the ApiEndpoints, so with that you can process the request accordingly
I have different java web applications running on tomcat as different modules and one java web application as an addon running on the same tomcat server as another different module. I want to use the addon within the different applications (which essentially appears as a popup and is just one javascript file with a few URL-mapped controllers at the back end). I have allowed cross domain requests for the addon within the Tomcat realm, so the applications can access the popup and retriece the data.
Eg. in WebApp1, [http://localhost:8080/page1.html]:
ajaxGet(http://localhost:8081/getPopup, function(html){
showPopup(html);
});
The architecture of all applications is a simple JSON based request-response driven UI with javascript at the front end and URL-controller/servlet mappings on the JAVA-backend.
It works fine, but of course, it will also work for any requests from within the applications in the realm even if they are not authenticated. ie, even from the login page, I can request the popup.
How shall I take care of the authentication? Considering the addon doesnt need to be connected to the database for separate authentication, its authentication depends on whether the calling application is already authenticated or not.
Thanks in advance for your inputs. :)
Actually you need authorization, which usually depends on authentication. Authentication is the process of telling the service who is making the request, while authorization is the process of deciding if the principal is allowed to make the request.
The first thing you should do anyhow is adding authentication and authorization to the service which makes the popup content (/getPopup). Once you have secured that service, you actually have a number of choices:
implementing some single-sign-on framework
employing a federated authentication technology
forwarding requests from the calling application with a custom authentication scheme
...
Obviously, the simplest solution would be shipping everything together in a single deployment unit.
As a side note, mind the cookie session name when testing on localhost: cookies are bound to the hostname, not hostname + port, so the JSESSIONID issued by one service at localhost:X will be overwritten by the JSESSION id of localhost:Y
I have been struggling with this the last couple of days and haven't found a reliable, understandable solution on the web.
I have a web app that is comprised of a rest api and a presentation layer consuming it. Presentation layer has a login form, the data introduced by the user is sent to the REST api which then uses a third party service to authenticate the user. This part I have already set up.
What I want now is to inrtoduce a token-based authentication for every subsequent request so I don't have to send credentials on every request and then authenticate again against the third party service.
So basically, using Spring Security (v. 3.1.3), I am lost as to how to create a reliable, secure token, return it to the requester, then authenticate request based on said token.
Can you point me to the right direction? Or to some example online?
How do you generate the token? How do you return the token to the
client?
How would you send the token in subsequent requests?
How do you set the whole thing up so the first time you can
somehow send the credentials (user/pass) then the subsequent
requests send only the token?
How do you authenticate against the token?
I've seen implementations where token includes some expiryTime. So what happnes after expiryTime is exhausted? The user must login again, even if he's been making requests the whole time? Should I renew the token "behind the scenes"?
Is the server-side REST application stateful or stateless? If stateful, you won't need to do anything special using a regular HTTP Session. Just start using Spring Security and if the client and server are already exchanging session information, your protected API endpoints will work out of the box. The only caveat is if you have CSRF protection enabled, in which case you will need to tweak the client a little bit. Details for this are in the Spring Security documentation.
On the other hand, if the REST application is stateless, you will have to use a token-based approach like you have proposed. See my answer to a similar post for details. If you do choose to follow the steps in that answer, answers to your questions are:
The token has to be generated on the server-side. If you go through the sample code linked to my answer, you will see that I have replaced the default HTTP-session-dependent infrastructure of Spring Security with a cache-based infrastructure. In the session-based implementation, the unique conversation identifier, which is the session ID, is generated by the servlet container, whereas in the custom implementation, the identifier, which is the token, is generated within the application. Specifically, I have used a SecureRandom instance to generate strong tokens.
The token is sent back by the client as an HTTP header. This protects the content over an SSL channel.
The trick is to implement four very simple interfaces from Spring Security. My sample app has full details. The whole process took me less than an hour.
Authentication against the token is done automatically by Spring Security. We simply need to provide an implementation for storing and retrieving tokens, which is straightforward and takes only a few lines of code.
In my sample app I have used an expirable cache with sliding expiration for storing the tokens. If a client keeps sending requests periodically, the server keeps on accessing the cache for the authentication token, thereby keeping the token alive in the cache. Tokens are evicted from the cache only after a period of inactivity equaling or exceeding the cache expiration period.
So overall, a token-based authentication/authorization approach can be easily implemented with Spring Security and leveraging a caching library like EHCACHE.