OAuth2 and Token-based authentication - can it work with sticky sessions or similar mechanism - authentication

I have created application starting with JHipster and at that point implemented Token-based authentication provided by JHipster. Even though I implemented Server Side Controller as RESTful services - I had to keep User Context on server in Custom Implementation of UserDetails because of complexity of my multistage transactions. It all works well in single JVM instance environment but when want to implement it as a horisontal cluster I need to make sure that requests from the same user keep redirecting to the JVM where it's context is. I use Tomcat with Apache HTTP for cluster load balancing and implementation. Can mechanism similar to sticky sessions be implemented in cluster with this type of authentication (or OAuth2 - also stateless)? Replicating User Context via distributed cache is not an option for me as it can be quite heavy.

If I understood question, the answer is - yes, OAuth2 is stateless. Simplified image looks like this:
User become authenticated on the server (login)
User authorize a client to access resources on the server
Spring generate access_token and put mapping between access_token and the user details to a token store.
Client try to get the resource with access_token
Spring intercept the request -> extract the token -> get user from the token store by the token -> add the user to the context.
By default spring uses in memory token store, but you can setup JDBC one out of the box or just implement yours.

Related

When to create backend application in keycloak

I see that in most of the keycloak tutorials it is suggested to create two client in keycloak i.e. frontend, backend. But I don't understand the need for this since I can validated the JWT token provided by frontend using public key even without creating separate client.
So my question is, is the approach of not creating the backend app the wrong approach? Also when & why should we create a backend client in keycloak.
Ref - https://medium.com/devops-dudes/secure-front-end-react-js-and-back-end-node-js-express-rest-api-with-keycloak-daf159f0a94e
I see most of the tutorial of keycloak suggest to create two client in
keycloak i.e. frontend, backend. But I don't understand the need of
this as I can validated JWT token provided by frontend using public
key even without creating separate client.
Typically, such tutorials are created to showcase the authentication and authorization capabilities of Keycloak.
The authentication part is showcased by the user authenticating via the browser (using the frontend client), whereas the authorization part is showcased by the application sending an access token to the Keycloak server where the claims on the access token (e.g., roles) can then be used to infer if the user has the permissions to perform the desire action (i.e., authorization).
So my question is, is approach of not creating backend app is not
right approach?
Depends on your specific use case. Alternatively to the approach that I have previously mentioned, one could have had a single client (i.e, the frontend client), and after the user has successfully authenticated, the application would pass the access token to the backend. The backend could then perform the authorization by directly checking, for instance, the roles in the access token, instead of relying on the Keycloak server to do so. There are pros and cons to both approaches.
Also when & why should we create backend client in keycloak.
A typical example would be if the backend would be a separated micro-service that triggers some maintenance task for example. Assuming that task is not related at all to the user authentication process, it would make more sense to then have a separate client (in this case a confidential one) that would rely on the client credentials flow which is typically used for machine-to-machine use-cases.

add custom fields to current user on gateway after authenticating with keycloak server

We're using Keycloak server for authenticating against several IDPS (google, active directory, etc). We have a spring gateway microservice which plays role of a client and several other microservices which play role of resource servers.
When user authenticates via keycloak, we want to associate the authenticated user with some custom fields (like context, roles, user details) from our custom database (NOT Keycloak DB) and send those fields to other microservices as well, so that we do not need to load the fields from DB in every microservice.
How would you do that? Making a GlobalFilter in the Gateway which would add those fields to request headers and setting those headers somehow to the principal object in resource servers? Or using cache (redis) to store the fields on gateway and load them in resource servers? Or do you have some other solution? For example extending access token, overiding UserDetailsService, etc..
What's important to note is, that we don't want to extends Keycloak Database, since we want to have the whole role management in our custom database. Reason for that is that keycloak schema is not very flexible. We want to use keycloak only as a dummy authentication server.
The preferred option for security related values is for Keycloak to reach out to your APIs or custom data sources at the time of token issuance, then include your domain specific claims in JWT access tokens. In keycloak I believe this is done via a protocol mapper, as in this answer.
This design pattern is discussed in the Claims Best Practices article. It is recommended to not send secure values such as roles in custom headers etc, since they are potentially easier to change by a hostile party. Instead each API should receive the JWT and validate it, in a zero trust manner, then use the received claims for authorization.
For non secure values, such as a session_id or correlation_id used for logging, simple HTTP headers work well.

How do I authenticate a web request from Unity to Node without requiring user credentials?

I have a single player Unity game which records stats about game run-throughs, such as accuracy/runtime. I want these stats to be saved onto a web server / db so I can later aggregate them, the web server being a Node app using Express and the DB being a MongoDB instance. I have made the API routes to POST/GET the data but at the moment the routes are public. Normally, I would implement JWT whereby the user would have to login to be able to make web requests, but since the game is single player there is no login credentials to use.
What would be the best way to verify that a call to my web service has been made from within the Unity game without requiring the user to login/register an account?
So far I have thought about using a key on the Unity-side that needs to be sent through with each request, but this is prone to being discovered by searching through the source code.
Implement oAuth on top of your REST API on the Node side. Now a caller has to provide an access token when calling your API. Make sure your implementation supports a flow you're going to choose in step 2. oauth2authorize is a popular toolkit.
Choose an appropriate oAuth flow and implement it on the Unity side. One possibility is the client credentials grant, a flow designed for service-to-service calls. Another option is exchanging JWT for an access token; the payload of the JWT can reflect the security context of the caller being the Unity game itself.

Microservice Authentication strategy

I'm having a hard time choosing a decent/secure authentication strategy for a microservice architecture. The only SO post I found on the topic is this one: Single Sign-On in Microservice Architecture
My idea here is to have in each service (eg. authentication, messaging, notification, profile etc.) a unique reference to each user (quite logically then his user_id) and the possibility to get the current user's id if logged in.
From my researches, I see there are two possible strategies:
1. Shared architecture
In this strategy, the authentication app is one service among other. But each service must be able to make the conversion session_id => user_id so it must be dead simple. That's why I thought of Redis, that would store the key:value session_id:user_id.
2. Firewall architecture
In this strategy, session storage doesn't really matter, as it is only handled by the authenticating app. Then the user_id can be forwarded to other services. I thought of Rails + Devise (+ Redis or mem-cached, or cookie storage, etc.) but there are tons of possibilities. The only thing that matter is that Service X will never need to authenticate the user.
How do those two solutions compare in terms of:
security
robustness
scalability
ease of use
Or maybe you would suggest another solution I haven't mentioned in here?
I like the solution #1 better but haven't found much default implementation that would secure me in the fact that I'm going in the right direction.
Based on what I understand, a good way to resolve it is by using the OAuth 2 protocol (you can find a little more information about it on http://oauth.net/2/)
When your user logs into your application they will get a token and with this token they will be able to send to other services to identify them in the request.
Example of Chained Microservice Design
Resources:
http://presos.dsyer.com/decks/microservice-security.html
https://github.com/intridea/oauth2
https://spring.io/guides/tutorials/spring-security-and-angular-js/
Short answer : Use Oauth2.0 kind token based authentication, which can be used in any type of applications like a webapp or mobile app. The sequence of steps involved for a web application would be then to
authenticate against ID provider
keep the access token in cookie
access the pages in webapp
call the services
Diagram below depicts the components which would be needed. Such an architecture separating the web and data apis will give a good scalability, resilience and stability
You can avoid storing session info in the backend by using JWT tokens.
Here's how it could look like using OAuth 2.0 & OpenID Connect. I'm also adding username & password login to the answer as I assume most people add it as a login option too.
Here are the suggested components of the solution:
Account-service: a microservice responsible for user creation & authentication. can have endpoints for Google, Facebook and/or regular username & password authentication endpoints - login, register.
On register - meaning via register endpoint or first google/fb login, we can store info about the user in the DB.
After the user successfully logs in using either of the options, on the server side we create a JWT token with relevant user data, like userID. To avoid tampering, we sign it using a token secret we define(that's a string).
This token should be returned as httpOnly cookie alongside the login response. It is recommended that it's https only too for security. This token would be the ID token, with regards to the OpenID connect specification.
Client side web application: receives the signed JWT as httpOnly cookie, which means this data is not accessible to javascript code, and is recommended from a security standpoint. When sending subsequent requests to the server or to other microservices, we attach the cookie to the request(in axios it would mean to use withCredentials: true).
Microservices that need to authenticate the user by the token:
These services verify the signature of the JWT token, and read it using the same secret provided to sign the token. then they can access the data stored on the token, like the userID, and fetch the DB for additional info about the user, or do whichever other logic. Note - this is not intended for use as authorization, but for authentication. for that, we have refresh token & access token, which are out of scope of the question.
I have recently created a detailed guide specifically about this subject, in case it helps someone: https://www.aspecto.io/blog/microservices-authentication-strategies-theory-to-practice/
One more architecture perspective is to use nuget-package (library) which actually do authentication/token validaton. Nuget-package will be consumed by each microservice.
One more benefit is that there is no code duplication.
you can use idenitty server 4 for authentication and authorisation purpose
you must use Firewall Architecture hence you have more control over secutiry , robustness ,scalability and ease of use

Authentication, Authorization and Session Management in Traditional Web Apps and APIs

Correct me if I am wrong: In a traditional web application, the browser automatically appends session information into a request to the server, so the server can know who the request comes from. What exactly is appended actually?
However, in a API based app, this information is not sent automatically, so when developing an API, I must check myself if the request comes from an authenticated user for example? How is this normally done?
HTTP Protocol is stateless by design, each request is done separately and is executed in a separate context.
The idea behind session management is to put requests from the same client in the same context. This is done by issuing an identifier by the server and sending it to the client, then the client would save this identifier and resend it in subsequent requests so the server can identify it.
Cookies
In a typical browser-server case; the browser manages a list of key/value pairs, known as cookies, for each domain:
Cookies can be managed by the server (created/modified/deleted) using the Set-Cookie HTTP response header.
Cookies can be accessed by the server (read) by parsing the Cookie HTTP request header.
Web-targeted programming languages/frameworks provide functions to deal with cookies on a higher level, for example, PHP provides setcookie/$_COOKIE to write/read cookies.
Sessions
Back to sessions, In a typical browser-server case (again), server-side session management takes advantage of client-side cookie management. PHP's session management sets a session id cookie and use it to identify subsequent requests.
Web applications API?
Now back to your question; since you'd be the one responsible for designing the API and documenting it, the implementation would be your decision. You basically have to
give the client an identifier, be it via a Set-Cookie HTTP response header, inside the response body (XML/JSON auth response).
have a mechanism to maintain identifier/client association. for example a database table that associates identifier 00112233445566778899aabbccddeeff with client/user #1337.
have the client resend the identifier sent to it at (1.) in all subsequent requests, be it in an HTTP Cookie request header, a ?sid=00112233445566778899aabbccddeeff param(*).
lookup the received identifier, using the mechanism at (2.), check if a valid authentication, and is authorized to do requested operation, and then proceed with the operation on behalf on the auth'd user.
Of course you can build upon existing infrastructure, you can use PHP's session management (that would take care of 1./2. and the authentication part of 4.) in your app, and require that client-side implementation do cookie management(that would take care of 3.), and then you do the rest of your app logic upon that.
(*) Each approach has cons and pros, for example, using a GET request param is easier to implement, but may have security implications, since GET requests are logged. You should use https for critical (all?) applications.
The session management is server responsibility. When session is created, a session token is generated and sent to the client (and stored in a cookie). After that, in the next requests between client and server, the client sends the token (usually) as an HTTP cookie. All session data is stored on the server, the client only stores the token. For example, to start a session in PHP you just need to:
session_start(); // Will create a cookie named PHPSESSID with the session token
After the session is created you can save data on it. For example, if you want to keep a user logged:
// If username and password match, you can just save the user id on the session
$_SESSION['userID'] = 123;
Now you are able to check whether a user is authenticated or not:
if ($_SESSION['userID'])
echo 'user is authenticated';
else
echo 'user isn't authenticated';
If you want, you can create a session only for an authenticated user:
if (verifyAccountInformation($user,$pass)){ // Check user credentials
// Will create a cookie named PHPSESSID with the session token
session_start();
$_SESSION['userID'] = 123;
}
There are numerous way for authentic users, both for Web applications and APIs. There are couple of standards, or you can write your own custom authorization / and or authentication. I would like to point out difference between authorization and authentication. First, application needs to authenticate user(or api client) that request is coming from. Once user has been authenticated, based on user's identity application needs to determine whatever authenticated user has permission to perform certain application (authorization). For the most of traditional web applications, there is no fine granularity in security model, so once the user is authenticated, it's in most cases also and authorized to perform certain action. However, this two concepts (authentication and authorization) should be as two different logical operations.
Further more, in classical web applications, after user has been authenticated and authorized
(mostly by looking up username/password pair in database), authorization and identity info is written in session storage. Session storage does not have to be server side, as most of the answers above suggest, it could also be stored in cookie on client side, encrypted in most cases. For an example, PHP CodeIgniter framework does this by default. There is number of mechanism for protecting session on client side, and I don't see this way of storing session data any less secure than storing sessionId, which is then looked up in session storage on server-side. Also, storing session client-side is quite convenient in distributed environment, because it eliminates need for designing solution (or using already existing one) for central session management on server side.
Further more, authenticating with simple user-password pair does not have to be in all case done trough custom code which looks up matching user-record in database. There is, for example basic authentication protocol , or digest authentication. On proprietary software like Windows platform, there are also ways of authenticating user trough, for an example,ActiveDirectory
Providing username/password pair is not only way to authenticate, if using HTTPS protocol, you can also consider authentication using digital certificates.
In specific use case, if designing web service, which uses SOAP as protocol, there is also WS-Security extension for SOAP protocol.
With all these said, I would say that answers to following question enter decision procedure for choice of authorization/authentication mechanism for WebApi:
1) What's the targeted audience, is it publicly available, or for registered(paying) members only?
2) Is it run or *NIX, or MS platform
3) What number of users is expected
4) How much sensitive data API deals with (stronger vs weaker authentication mechanisms)
5) Is there any SSO service that you could use
.. and many more.
Hope that this clears things bit, as there are many variables in equation.
If the API based APP is a Client, then the API must have option to retrieve/read the cookies from server response stream and store it. For automatic appending of cookies while preparing request object for same server/url. If it is not available, session id cannot be retrieved.
You are right, well the reason things are 'automatic' in a standard environment is because cookies are preferred over URL propagation to keep things pretty for the users. That said, the browser (client software) manages storing and sending the session cookie along with every request.
In the API world, simple systems often just have authentication credentials passed along with every request (at least in my line of work). Client authors are typically (again in my experience) reluctant to implement cookie storage, and transmission with every request and generally anything more than the bare minimum...
There are plenty of other authentication mechanisms out there for HTTP-based APIs, HTTP basic / digest to name a couple, and of course the ubiquitous o-auth which is designed specifically for these things if I'm not mistaken. No cookies are maintained, credentials are part of every exchange (fairly sure on that).
The other thing to consider is what you're going to do w/ the session on the server in an API. The session on a website provides storage for the current user, and typically stores small amounts of data to take load off the db from page to page. In an API context this is less of a need as things are more-or-less stateless, speaking generally of course; it really depends what the service is doing.
I would suggest you send some kind of token with each request.
Dependent on the server and service those can be a JSESSIONID parameter in your GET/POST request or something mature like SAML in SOAP over HTTP in your Web Service request.