Understanding Access token expiration when using client_credentials grant type - authentication

we are using KeyCloak (version 16.0.0) as our IAM.
in our code, we are using the Admin Rest Api to handle user login.
in the first login, we are sending the user credentials and using the password grant type to get a valid access token.
but after that, whenever the access token is about to be expired (in our case 5 minutes) we are using the client_credentials grant type to generate a new access token.
I'm not an expert but it seems to me, that unlike working with refresh tokens, this way to generate a new access token can last forever and it's not bound by any value from KC configuration.
Am I right?
I tried to play around with SSO Session Idle/Max and Client Session Idle/Max values (both on realm and client level) but it seems to have no impact.
any insight will be helpful

I'm not an expert but it seems to me, that unlike working with refresh
tokens, this way to generate a new access token can last forever and
it's not bound by any value from KC configuration. Am I right?
What happens if the account of user A gets compromised? According, to your current setup you would keep that user logged in "forever", unless you would "tell" Keycloak to not omitted tokens on behalf of the client that is being used with the client_credentials grant type. But then other unrelated users would suffer. There is additional issues with this design, for example the assignment of roles to users, how would you handle user specify roles in the access token omitted by the client that is being used with the client_credentials grant type?
This seams to me to be a poor man's version of the refresh token mechanism.
in the first login, we are sending the user credentials and using the
password grant type to get a valid access token.
If possible you should use more modern workflows for user login, like for example Authorization Code Flow (i.e., standard flow in Keycloak). Otherwise, just use the direct access grants with a short access token lifespan and renew it using the refresh token mechanism.

Related

Why should you revoke access token?

I don't understand why should you revoke Access Token when your log out. I mean what should you gain from a security perspective, while there is a Refresh token which is used to get a new access token as soos as you browse to the application?
I don't see the profit from a security perspective when there is a Refresh token which can be used by whoever uses the computer and browse to the application.
Whilst the concept of OAuth 2.0 is based on short lived access tokens that are not revoked, there are exceptions to that rule and there's a protocol specification catering for token revocation, RFC 7009 OAuth 2.0 Token Revocation https://datatracker.ietf.org/doc/html/rfc7009.
When revoking the access token, one should also make sure to revoke the refresh token at the same time (the spec dictates that revoking a refresh token will also revoke associated access tokens). This becomes more important when tokens are long lived and there's a suspicion of some breach, unauthorised 3rd-party token access or other token leakage.
I don't understand why should you revoke Access Token when your log out.
Access tokens cant be revoked. They are used for Authorization, and grant the bearer of the access token access to the data for as long as the token has not expired.
Logging out is Authentication these are two very different concepts.
I mean what should you gain from a security perspective, while there is a Refresh token which is used to get a new access token as soon as you browse to the application?
You are again mixing Authorization (OAuth 2.0 access token refresh token) with authentication(open id connect, logging in a user).
Using OAuth 2.0 an application is granted authorization to access a users data they are granted an access token and a refresh token. The application can access the users data when ever it needs to without the user being present.
I don't see the profit from a security perspective when there is a Refresh token which can be used by whoever uses the computer and browse to the application.
This is the exact point of OAuth 2.0 it is there to grant an application access to a users data when the user is not present. It is not authentication.
When a user logs out from an OAuth2-based session, they might want to make sure that every application on the same machine can no longer do things on a users' behalf.
For example, perhaps your organization has a single-sign on system that spans several applications, some even third party. When the user logs out, you can't rely on applications to 'log themselves out'. Perhaps all they got is a a session cookie, sitting in a browsers' cookie jar waiting for the next request.
If I log out on a machine, I want the guarantee that nothing can still act on my behalf, not even for a minute.

How do I implement session authentication across microservices?

I'm working on a project for which I have planned the following architecture:
auth.example.com: Provides login, registration, and password-reset functionalities.
accounts.example.com: Allows users to update their account data.
example.com: Provides other services.
I have figured out the following solution for maintaining authentication across all domains:
Authenticate user on auth.example.com and set a cookie containing JWT token (signed token with shared key) which contains the user data and its domain is set to .example.com.
Once the user is authenticated, redirect them to example.com/dashboard and verify the JWT token present in the cookie. If the token is valid, present the service to the user else redirect to auth.example.com.
Now, I have the following doubts:
Suppose if a user updates his name on accounts.example.com, how do I make all other services use the updated user data?
If I want to ban a user or delete their account or terminate all active sessions, how would I let other services that the user shall not be authenticated?
Is there any better approach to solve this problem?
JWT tokens are generally stateful means they have everything to be authenticated, once issued they can be used and there is no way we can revoke them. However there are few approaches that we can use.
Normally we keep the life time (expiry) of token short (e.g. 15 mins) and refresh the access after X minutes using Refresh Token (Know the difference between Refresh and Access Token).
Say the token is about to get expired then we will re-issue the access token (refresh token will do that without user sign in again). Refresh tokens are long lived token and have to be handled carefully. If we have to revoke the access then we need to revoke Refresh token and after X mins user is not able to get access token since Refresh token is revoked already.
During the time when you revoked the refresh token , any access token issued is still valid until reaches its expiry. If you want to invalidate the token before that then you may have to blacklist the token and maintain the list of such tokens that will stop the user from login using that particular token.
I have found very nice explanation here Check Revoke Token
Club JWT token, protocols like oauth and openid and store the session in redis/memcache.
This redis/memcache will be single point of contact for all your microservices.
Say microservice m1, m2, ... are independent and using restapi gets connected to microservice called mR which checks the session in redis/memcache.

What is the purpose of Resource Owner Password Credential Grant Type in OAuth 2.0?

Based on the answer to my previous question
Ok, OAuth 2.0 is an authorization protocol but when you use ROPC (Resource Owner Password Credential) Grant Type, the way I understand it, you mean to authenticate and authorize isn't it?
Is OpenID still applicable in ROPC? still a little bit confuse with OAuth 2.0 ROPC and OpenID
The Resource Owner Password Credentials grant type does authenticate users but is a non-typical OAuth 2.0 grant type that is only meant for migration purposes, as the spec says:
The resource owner password credentials grant type is often used for
legacy or migration reasons. It reduces the overall risk of storing
usernames and passwords by the client but does not eliminate the need
to expose highly privileged credentials to the client.
This grant type carries a higher risk than other grant types
because it maintains the password anti-pattern this protocol seeks
to avoid.
The Resource Owner Password Credentials grant is not prohibited with OpenID Connect (even though the OpenID Connect spec does not clearly define it beyond OAuth 2.0) but defeats the primary purpose of a federated SSO protocol that OpenID Connect is supposed to be. That is because it locks RPs in to a single authentication method whereby the user credentials are disclosed to the RP. You mileage wrt. to support across Providers may vary.
See also: Does OpenID Connect support the Resource Owner Password Credentials grant?
In my view, the power of resource owner password credentials(ROPC) is utilized properly when we use the refresh token.
Consider a mobile app where user needs to log in. Once logged in and request a token using your clientId, secret, userid and password, normally you get an access token and a refresh token. Access token is normally valid for less time(say 1 hour) and refresh token is valid for a longer time(say 24 hours). ClientId and Secret is stored in the App. UserId and Password is owned by user and never stored anywhere.
When the user tries to access the app after 1 hour, his access token is expired which means in normal scenario, he needs to log in again.
But we can avoid this tedious task of entering his userId and password again by getting a new access token(and new refresh token) by exchanging the refresh token along with the clientId and Secret(no userId and password needed). The new access token will have all the same features of the previous access token. This means as long as user is active atleast 24 hours ago, he doesn't have to log in again. After 24 hours of idle time, both refresh token and access token expires and the log in is required to get a new access token.

Can client credentials grant access token be mapped to a user?

I want to use the Client Credentials Grant in oauth2 for securing an API.
However, I want the access token to map to an individual user (chosen by me, at the out-of-band trust/setup phase where I share a key/secret).
Is this an issue? I understand that the access token using client credentials grant is not supposed to be in the context of a user... Is it bad practice to bind it that way?
It is not an issue per se, at least security-wise, although you may call it bad practice. If you make sure that you assign the client credentials in such a way that it is guaranteed to be bound to exactly one user for which that client is authorized, there's no problem. Note though that the out-of-band process to achieve that is exactly what the Authorization Code grant gives you in-band.
You'll also have to make sure that the client credentials are revoked when required permissions for the user change or the user account is deleted, much like a regular Authorization Server would do for its refresh tokens.

oAuth 2.0 - Acting on behalf of the user

I'm new to oAUth2 and I'm trying to get a few things straight.
I understand the basic principles involved with oAuth2 but I am not sure how to implement it in my situation.
I am writing an app that acts on behalf of the user to automate a manual process and perform some tasks(update/request status...etc). The API we are connecting to uses oAuth2 to grant our application permission. We plan on having the user grant our application permission when they create a new account with us.
I understand that the user will request an authentication code that is provided to our application. Then our application will use the authentication code to generate an access token.
We would like to do this only once. Then act as the user to send and receive notifications without having to have the user to log into the service with their credentials.
I am not sure how to implement this without having to store the user credentials to get an auth code since the auth code and auth tokens expire. I'm guessing that this is a common scenario.
What would I need to do to get what I want accomplished?
You can get a new AccessToken using a RefreshToken, if this is provided by the Authorization Server.
If it's not provided I would contact the Api provider, you should never store a users credentials. In fact if the OAuth protocol is well implemented as a client you should never be able to even get the client credentials. When the user has to login you should redirect the user to the Authorization Server, there the user should login and then the authorization token should be redirected to your application by the Authorization Server.
See also this explanation on Refresh Tokens from the OAuth 2.0 spec:
Refresh tokens are credentials used to obtain access tokens. Refresh
tokens are issued to the client by the authorization server and are
used to obtain a new access token when the current access token
becomes invalid or expires, or to obtain additional access tokens
with identical or narrower scope (access tokens may have a shorter
lifetime and fewer permissions than authorized by the resource
owner). Issuing a refresh token is optional at the discretion of the
authorization server. If the authorization server issues a refresh
token, it is included when issuing an access token
Note
If you request a new AccessToken using your RefreshToken and the response includes a new RefreshToken you should overwrite your currently saved RefreshToken. With other words, you should always use the latest RefresthToken you received.