JAX-RS - Authentication and getting user data in RESTful web services - java

I am new to RESTful Web Services and I'm trying to design my first secure web service using JAX-RS. But I have got this doubt.
Imagine I have a messenger API where I have a "/posts" web service, which would give me all the posts for the user who calls it. So I have designed a basic auth filter which does the authentication and if valid user, it passes the request to the /posts service which gives a list of posts for the user. Now the problem is the user in my DB has a user id which is not exposed to the user. Inside the /posts service I need the userId to get the posts of the requesting user. So my filter does the authentication and gets the userId for the logged in user.
My question is how to pass this userId to the /posts web service ?
My approach now is to add this userId as a request header info in the filter and then pass it to the /posts service.
But I am confused if this is the right approach to do it, or should this scenario be handled elegantly in some other way?
Please help me to understand what might be the best approach to do it.

It sounds like you're considering creating your own security when there are already established standards that are well documented out there. I've used OAuth and JWT tokens in the past to secure rest end points. Depending on your specific requirements, you may be able to use Basic Authentication.
When it comes to security, it's rare that you'll be able to do a better job then the experts, so if you can follow a standard, you probably should. The additional benefit being the next person to come a long has all the documentation and support to go along with it.
Update:
Just having the user ID in the request would not be sufficient. Anyone who knows someone else's user id would be able to spoof being that person and post to the endpoint as the other user.
"My question is how to pass this userId to the /posts web service ?"
Sessions can be used to store the internal user id. If you already have them logged in with a session, you should be able to pull the user id from the session. If you were to use JWT (which is stateless) you can pull whatever information you have stored in the token to accomplish the same thing.

Related

Adding OAuth / OIDC features using KeyCloak to existing application with java backend (run inside Tomcat) and Polymer (javascript) frontend

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

Create a custom identity provider and configure it with keycloak

I am working on a project where I need to create an application that shall act as an OIDC mediator between a client which only supports OIDC for authentication and a REST api. The REST api is able to generate tokens and give user info but does not support OIDC.
To achieve this I am thinking of using keycloak to handle the OIDC communication with the client and implement my own java application that keycloak can trigger to realize the authorization, token and userinfo endpoint (sort of a custom ownmade identity provider) handling the communication with the rest api.
I have created a realm in keycloak and configured the realm to use an Identity Provider Redirector with an Identity Provider I added in keycloak (user-defined OpenID Connect v1.0). In the identity provider configuration I have set all the URLs to point to my java application but the initial OIDC authorization call from the client just redirects to the redirect_uri with a #error=login_required without any of my endpoints in the java application beeing triggered.
I guess there is something I have missed.. I need to intervene the authorization flow so that I can pick up a query param from the authorization request that needs to be handled in my java application. I also need to map the token from the rest api into the token request (when this request comes from the backend of the client app), and finally map the userinfo object as a response to the userinfo request.
I really hope someone have time to point me in the right direction. Thank you so much in advance.
Edit:
I have added a sequence diagram to explain it better:
I need to intercept the authorization request call to pick up a custom query param (endUserString) that identifies the user. There will be no user login form. I need the param in my code that uses this towards the REST API. Both the token and the userinfo must be received from my APP and not from keycloak itself.
The Java Mediator may ask for a token in advance (A) and use this to access the Rest API (using a predefined clientId and clientsecret). Alternatively this token may be fetched for each method. To token must be used to retrieve customer info from the REST API (B). I want to wrap this with OIDC support without any login form. A browser will just redirect to the authorization flow with the endUserString identifying the end user. The customer info will be returned from the java mediator into keycloak responding this in the GetUserInfoRsp.
I think there might be a simpler solution than what you envisioned: implementing your own custom authenticator for Keycloak.
Keycloak has a notion of authentication flow which is a tree of authenticators than are provided by Keycloak or custom made. Each authenticator can be called to try to authenticate the user.
The most common one is the Username/Password Form which displays a login page to the user and authenticates the user if the provided credentials are valid. But you could imagine any type of authenticator such as an SMS authenticator or a magic link one.
You can find the existing Keycloak's authenticators on their repo and the documentation on how to create your own here.
In your case, you would need to implement your own logic where your authenticator would get the endUserString param from the request and call the REST API to validate the user's identity. You could fetch the REST API token at initialisation or for each request. You could also modify the user stored in Keycloak with data coming from the REST API's user info endpoint (common OIDC attributes or custom attributes).
Please note that the dev team announced Keycloak X, a sort of reboot of the project which will probably bring breaking changes to their APIs.
Also, please consider all the security impacts of your design as, from what you provided, it seems the authentication of a user will only rely on a simple query parameter which, if it doesn't change over time for example, feels like a big security hole.

google app engine cloud endpoint security

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

How to secure the Rest webservice by token based authentication?

I have created few rest services using jersey implementation.
In security concerns, service can invoke by any one. So I decided to use the token based authentication system.
I wrote one filter in spring security which handles every request before its hits the server.
One login service were created so user can invoke this service by passing the username and password for valid credentials it will generates the access token and expiry date and saves it in Hashmap and DB and returned as a response to the user.
For remaining services user have to pass the generated token in header to access the JAX-RS services.
All these process are coded by us i.e., generation,storage and expiration of the token.
Since we have some security API like oauth1,oauth2 in market is it good to provide the security for rest service by above mentioned way???
Is oauth api will suits my requirement . If it is please guide me how to achieve this ?
Please help me out with valuable suggestions ???
Thanks in advance.
We've been in a similiar position before starting with our rest api. The only difference we had no exisitng code. So basically we saw 2 choices
Run our own Tokenhandling, that what you already have
Use something existing, i.e. oauth2
Our main requirement was authentification via token and we prefered an existing solution. So we just run with oauth2 in form of spring-security-oauth2, even we are not using the whole self authorization stuff.
What i like and probably had missed in an own implementation is that a token generally identifies a user and a client combination and that clients can have rights too. Its nice to have this extra layer of security in our rest api, so i can block early on before even hitting one line of our code.
In form of spring-security-oauth2 its proven code, which works and like much of spring its customizable. Example: In our first version we did use the provided JdbcTokenstore for storing the token, but as requirements changed, we just coded our own and switched it in the config.
The disadvantage of using at least spring-security-oauth2 is that the whole authorization flow is normally webbased and needs communication between the client, the user and our app. As this would not work with our clients we had to trigger the token generation, etc ourselfs, which is doable with spring, but needed some code exploration :-)
If i had to build it again with java and where already using spring, i'd go with spring-security-oauth2 and the oauth way again. But when i had an existing working solution and dont need any of the oauth stuff i would keep the homegrown solution.

SSO via encrypted token

We have the need in a project to implement single sign-on for two different web applications, one being our own and one is implemented by someone else. For our own application we have user/password stored (encrypted) in the database. Since our application will be integrated in their environment, we now need a mechanism to let us authorize the user already being logged in at their side without showing a login screen again.
Since I'm not a security expert myself, I started reading (on a high-level) about a few techniques regarding SSO, e.g. OpenID, Kerberos, SAML, CAS - but I have not yet gained practical experience.
Before marching in the wrong direction - can someone provide me with own experience in that field and point me to a framework to use or a good (and recent) article about how this should be done?
One more infomation: The customer talks about preferring to pass encrypted tokens between the two webapps. Does this make sense? And does this lead to a certain technique?
We use a SAML realization for this purpose ( https://svn.softwareborsen.dk/oiosaml.java/sp/trunk/docs/index.html ) - it was easily integrated inside our existing web applications.
The working scheme can look like as follows: you will have a login page, where the SAML framework redirects user. so, after successful login, he got a cookie with the auth token, and redirected back to the web application page. you will also have an identification webservice, which you can call, passing the token provided, and be able to get the auth credentials (user role, etc) from there, so all your web applications can identify this user as logged in.

Categories