Keycloak/OpenID: request user-information on behalf of the client application - spring

I have a Spring Boot-application with a public REST-API. The user authentication is handled by Keycloak. Users can use the API to submit jobs, which are then executed periodically as a Spring Batch. Some of these jobs require the user to be notified via eMail after completion.
The application currently does not store any user-related information, except the ID of the user, who submitted the job. My problem is now, that I need the eMail-address belonging to that User-ID to send the job-completion notification. The JWT passed to the API, which contains this information, can't be used at this time, since the job is executed asynchronous in the batch-context.
I came up with 2 possible solutions so far, which both have their own drawbacks in my opinion:
solution 1: extracting the required information from the JWT and persist them in the application's database for later use
drawbacks:
the application should not be concerned with storing user-information; it also shouldn't duplicate data controlled by other applications
the user might change its eMail-address in the primary user-database, without getting noticed by my application
solution 2: requesting user-details as needed by using Keycloak-APIs.
This looks theoretically like a good approach to me. The suggested solutions on SO utilize the Keycloak Admin-API (endpoint /auth/admin/realms/{realm}/users/{user-id}) to fetch user-details. This requires the application to be configured as a "confidential client" with own client-credentials and an enabled service account. What bothers me here: It appears a bit strange to me, that a regular application without any special privileges uses an Admin-API. Also, the users-endpoint is not restricted to users, which have previously given consent to access their data.
Is there a good way to solve this problem?

If job requires an e-mail for its completion, why doesn't it request it as start parameter and just keep it in memory?
This is how I would proceed:
#Controller extracts e-mail from ID token on the end-point from which the user triggers job start
user e-mail is provided among other parameters to the job
job completes sending the e-mail
e-mail is lost, with other job resources

Related

How to upload to YouTube without authorization

I need to check the uploaded videos on a YouTube Channel and then upload missing videos via a CRON JOB.
I first thing I tried was the REST API and the server response with the endpoint was moved.
The problem I ran into with the PHP Google API Client is that it requires the user to authorize the token.
I now tried using the Python Code, but it also requires a authorize session. Also when creating the OAuth 2.0 client ID we are suppose to use OTHER. And there is no OTHER.
Python quickstart
Any Ideas? This has been really frustrating as there does not seem to be a lot of examples other than the ones Google provides. I also could not find a rest equivalent. I do not care if the solution is python or Rest or PHP client. I just need a user less CRON job doing the work.
What you need to consider is that there are two types of data public data and private data.
Public data is not owned by any user. Videos on YouTube for example for the most part are publicly available and do not require authorization to access. On the other had private data is data that is owned by a user.
In order to access public data you just need an api key to identify your application, however in order to access private user data you need the permission of the user who owns the account in question.
In order to upload to a users account (yes even your own) you need to be authenticated there for you will need to use Oauth2 yes even if you are using a cron job you still need to be authenticated there is no way around this. There for you will need to create Oauth2 credentials.
What i recommend you do is. Authorize your code once your your local machine store the refresh token and use the refresh token to request a new access token when ever your cron job needs access. I recomend you give that a try and if you have any issues create a new question include your code and a description of the problem you are having.
This is your only option with the YouTube API.

Does token auth make sessions unnecessary?

My question may be answered here, Are sessions needed for python-social-auth, but I feel as if I'd be making assumptions and would like to be positive regarding my understanding (NOTE: I'm not using django, I'm using mongo express react node, I'm guessing django might come with sessions built in or something). I followed this guide https://medium.com/hyphe/token-based-authentication-in-node-6e8731bfd7f2 to add token authentication and user login to my CRUD web app, works great, users are authenticated properly, routes are protected. However, everywhere I read about the fundamentals of session and session management states that "every web application in the world that maintains user data has to deal with sessions" (source: https://nodewebapps.com/2017/06/18/how-do-nodejs-sessions-work/). Currently, my react client uses setInterval to regularly check if the access token will expire soon enough to receive a new one via the refresh token. Is implementing sessions required for my app? If so, what is it that they add that I am missing?
It depends on the type of application.
If the resources being accessed using a token are not user specific, then sessions are not useful.
However, in a scenario where the resources are unique for different users (e.g. one has to sign in, etc), then it's wise to implement both sessions and access tokens.
Remember that tokens can also be saved within a session. Checkout 'express-session' to implement sessions in expressjs.

Best practice in securing user creation for a REST API

I'm currently working on a iphone/android project where the mobile talk ta java backend server through REST API calls.
The Java backend is done using Spring and its Authentication system (with a JSESSION ID token)
I'm not an expert in security but I can see that if not implemented correctly there could be quite a lot of issues.
One of my biggest concern would be user creation for example.
When the app creates a user it simply makes a POST request to (url.com/rest/create)
How can I avoid, server side, that a malicious user puts this url in a loop and create thousands of users ?
What are common best practices to secure API calls ?
Is the Spring Authentication token enough ?
Thank you!
It's not really possible to prevent a client from making many calls to your server. A malicious user can create a script or application firing requests to your server.
The solution is to authenticate and authorize the calls to the server. You give certain users (for example administrators) the privilege to create users. You trust those users to behave in a correct manner. You have your users authenticate before they call the APIs on your server. Then, on the server side your check who the user is and what he/she is allowed to do.
If you are still concerned about privileged users not behaving, you can assign quota to each user on the actions they are allowed to perform.
The hightech solution (with as much framework fuctions as possible) would be
first: have a created-by and created-date field at the entity you want to protect (I recommend to use Spring-Data-JPA Auditing for that).
second: create a custom spring method (or web) expression method that is able to check how many items the current user has created in the (for example) last 10minutes and if this are more then (for examle) 20, then return false (or make them parameters of the method).
Then you can protect your method (or url) with that expression (#PreAuthorize("createsNotExeced(10, 20)"))
But this is the high tech solution - it would be quite intresstion implementing them when one wants to learn spring security. (and you would need to add some caching, but this is also a Spring feature).
The lowtech solution would be: put an list of timestamp in the users session, and add an new item to that array whenever the user creates an new item. When the last (for example) 20 timestamp enties are within the last (for example) 10 minutes, then throw an TooMuchHeavyUseRuntimeException or somthing else.

Spring Social- Connect without having to constantly authorize the user

I have an application that needs to stream a specific users twitter data and search for specific hash-tag data then mass distribute an email, but if I'm understanding things correctly every time I want to connect, I have to redirect to an authorization page. All this should be in the background. Is there a way I can have the application authorize once, then always stream the data using spring social, if not, are there any alternatives?
OAuth uses tokens that expire. So no matter what, your users will still have to periodically log in via Twitter and go through the OAuth process again to get a fresh token. They will only have to authorize your app the first time, so subsequently they should get sent right back to your app (assuming this is a Web app). You might want to look at using ReconnectFilter, again assuming you're making a Web app:
http://docs.spring.io/spring-social/docs/current/apidocs/org/springframework/social/connect/web/ReconnectFilter.html

How can I avoid using server-side sessions for authentication in a Java webapp?

I'd like to secure access to resources in my web application, so I authenticate my users using the standard mechanisms and use server-side sessions to preserve the authenticated state.
I'd like to deploy across multiple systems in a load balanced configuration, but I don't want to start synchronising session state across my infrastructure. Are there ways (using either spec-driven facilities in Java EE or commonly available libs like Spring Security) of preserving the authentication state of a user without server-side sessions, for example by pushing the required state back out to the client? If so, are there additional risks I need to be aware of?
Update - I am using declarative security as per Java EE webapp specs and authenticating via an LDAP repository.
I'm not aware of a framework solution, but the following does work:
After the user successfully logged in you create a secured token and set it's value as a cookie. The token contains all information required (user ID, creation time, etc.) and is encrypted using some algorithm. So all nodes in your cluster can read the token, decrypt it and identify the user. Then you create a ServletFilter intercepting all requests, examining the token and set corresponding user credentials for e.g. ServletRequest.getRemoteUser() by using an HttpServletRequestWrapper.
One way to solve the problem. But you must take care, self-made security must be well-thought-out.
You can store some kind of token in a cookie after authentication, and manage session attributes yourself. E.g., have a database table whose primary key is the authentication token and stores user session data... Don't forget to implement a job to clean inactive "sessions".
As for what you should be aware of, keep in mind that cookies are something easy to access, steal, delete, disable, etc. The authentication token should be something strong and verifiable (hash a combination of the user ip + browser + rotating salt + some other things you can check for).
It is also wise to divide user authentications in two levels. "Has the cookie" and "just validated the cookie"... Let's say that "has the cookie" is a state that can be there for half an hour (or maybe more) which allows the user to navigate the site. "Just validated" state is for important operations, and should require the user to enter it's credentials again. The timeout for this "just validated state" shouldn't be much longer than a couple of minutes.
Keep in mind that I'm assuming that your site is not holding really sensitive data. For those situations I would recommend something such as two-way SSL authentication with external tokens or security cards plus rotating token devices plus biometrics authentication :D:D:D... I guess you see my point.
Cheers,
You can use an open id server to authentication thus separating your authentication and application logic.

Resources