How to the increase keycload bearer access token time using curl? - keycloak

This is the curl command I am using to create a access token but that access token is getting expired after 60s
curl -d "client_id=admin-cli" -d "username=myadminuser" -d "password=myadminpass" -d "grant_type=password" "http://localhost:8080/auth/realms/myrealmname/protocol/openid-connect/token"
Is there any way to increase the time of it while creating it using curl?
or by changing any realm settings in the admin console ui

As default value, the access_token lifetime is set to 60 seconds, and the refresh_token lifetime is 30 minutes.
As described in the OIDC standard you can obtain a renewed access_token with a valid refresh_token whenever you want.
Beside that you can change the access_token lifespan in the realm settings:
Realm master -> Realm Settings -> Tokens -> Access Token Lifespan
But keep in mind - it's recommended to use a short time period.

In my case (Keycloak 15.0.2) I requested the token over the master realm. So my solution was:
Go to master realm
Click on clients
Click on admin-cli client
Scroll down to Advanced Settings, open it
Set your desired time in Access Token Lifespan
Save

Related

Keycloak Huge JWT Token of master admin

We have a realm per customer, multi-tenant architecture. (Expected to have around 500 realms) There is a service account we use, a client in the master realm that will manage the customer realms. The problem is the huge JWT token for the master realm admin user/service account, who manage all the realms that increases in size as the number of realms increases. This is due to the 20+ client roles of each new realm. What are the different options we have to keep the token size low?
EDIT:
ps: Reducing roles is not an option either. The service account is an admin of the keycloak admin portal and needs to manage all the realms, so it needs manage-realm etc roles for all the realms. Keyclaok admin portal will not for example allow to delete the realm if it doesnt have delete-realm role.
To reduce the size of the token you can use the following strategies:
restrict the roles that the client access;
use client scopes to narrow down the claims that will be added to the token.
For the first option, you can go to the client in question, tab Scope, disable Full Scope Allowed, and then choose only the roles that the client is really interested.
For the second option, you can go to Client Scopes, create a scope, save it, then go to the Scope tab, add the roles that will be part of that scope. Then everytime you make a request for a token to the client in question you can send the scope as a parameter of that request. This way you will only include in the token the roles that belong to that scope.
I think you are running into this https://issues.redhat.com/browse/KEYCLOAK-1268.
If you look through the discussion there you will see
Tokens created for admin-cli or security-admin-console no longer have
any roles embedded within them. The Admin REST API now checks the
"aud" claim. If the audience is one of those clients, then it ignores
claims in token and just accesses the UserModel directly to determine
if admin has specific permissions.
Use admin-cli or security-admin-console for your client_id. Otherwise you will get every role there is for every realm there is in your token.
In order to use either one of those clients with a token request, you have to make it confidential and enable Direct Access Grants.
Then something like this will work and give you a managable token
curl -i -X POST \
-H "Content-Type:application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "client_id=admin-cli" \
-d "client_secret=<admin-cli-secret>" \
-d "username=my_admin_user" \
-d "password=<my_admin_user_password>" \
'http://master.foo.com/auth/realms/master/protocol/openid-connect/token'

Change configuration for not change token of private repository

I have a private repository and access of the raw.githubusercontent.com by API is using the ?token=AEDIQE3IPAPDAXI6QPVEBALBSAPEU in the end of the file name. But this token change during the time (10 -15 days) and this is not so good for my purposes. I don't find any way to do not change the token information. Please, this kind of configuration is possible?
Since that token can change, you might consider creating a Personal Access Token (PAT), and downloading the files using the Authorization header instead of a token in the URL.
curl -H "Authorization: token ${PAT}" \
https://raw.githubusercontent.com/user/repo/main/file.txt
The other approach seen here would be, still with a PAT, to
curl -H "Authorization: token ${PAT}" \
https://github.com/<username>/<reponame>/raw/<branch>/<path-to-your-file>
This will return a “redirect (HTTP 302)” with location header value pointing to the URL with the token.
You can get the current "raw.githubusercontent.com" token that way.

How to auto generate new Bearer Token in Postman for GCP Storage

I am trying to upload file from local to GCP bucket through cloud storage Rest API (https://storage.googleapis.com/upload/storage/v1/b) using Postman.
I am using Bearer Token for authorization and running $(gcloud auth print-access-token) command on GCP Shell to generate that token every time.
I need to know, how to auto generate that token from Postman while sending request ?
Is there any way to execute $(gcloud auth print-access-token) every time as a Pre-request Script within Postman ?
Thanks
I'm not very good with postman, but I think you can run pre-request to get token and reuse it in the subsequent request.
If so, you can get inspiration from the gcloud auth print-access-token command by adding the --log-http param to visualize the request performed by the CLI and to reproduce them in Postman.
EDIT 1
If you perform the request, you can see that a post is performed to this URL https://oauth2.googleapis.com/token
To reproduce the call, you can try with a curl
curl -X POST -d "grant_type=refresh_token&client_id=32555940559.apps.googleusercontent.com&client_secret=ZmssLNjJy2998hD4CTg2ejr2&refresh_token=<REFRESH_TOKEN>&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth" https://oauth2.googleapis.com/token
In this call, you need your REFRESH_TOKEN, that you can get here
cat ~/.config/gcloud/legacy_credentials/<YOUR EMAIL>/adc.json
Google Cloud Storage requires authentication as other Google APIs and one of the authentication way is providing bearer token. These bearer tokens are short lived and require regeneration.
So there are 3 ways to generate bearer tokens so you can interact with Google Storage API or other Google APIs using Postman:
Using oauth2l CLI ( Manual Regeneration of new bearer token and update of Authorization header with the new token)
This oauth2l CLI utility allows you to generate bearer tokens which can be pasted into the Authorization header in postman. You can use
Configuration of Postman with OAuth 2 and User Credentials ( Tokens can be managed via the Postman UI and expired ones cleaned up at the click of a button)
Postman can be configured to trigger the OAuth 2 flow and use a generated bearer token in all of the requests. But please make sure that all users have the correct permissions in the Google Cloud Platform project.
You will need to create OAuth 2 credentials in Google Cloud Console:
Go to APIS and Services
Then go to Credentials tab
Click on Create Credentials
Select OAuth Client ID
Fill the fields to create OAuth Client ID ( also add an Authorized redirect URI however this doesn’t need to resolve to anywhere).
The Client ID and Client Secret need to be saved in your machine.
Use Postman’s environment variable functionality to use different credentials per environment/project. In Postman create a new environment for your credentials using the cog icon at the top right.
Configure the variables accordingly: AUTH_CALLBACK_URL , AUTH_URL, AUTH_CLIENT_ID, AUTH_CLIENT_SECRET, AUTH_ACCESS_TOKEN_URL
This variable should be identical to that defined in the OAuth 2 Client ID creation menu and should be one of the following : AUTH_SCOPE
Once defined, these variables can be used in your Authorization tab in Postman. This can be configured at the collection level, the folder level or even the individual request level.
To Regenerate the Token, you can go to Authorization Tab and click on GET NEW ACCESS TOKEN
Configuration of Postman to use a pre-request script and service credentials (The pre-request script automatically regenerates the bearer token when it expires)
For this please check this Tutorial to follow the steps provided there.

Keycloak token exchange across realms

We use Keycloak 12.02 for this test.
The idea is that we have a lot of customers, that we all have in their own realms. We want to be able to impersonate a user in any non-master realm for an admin/support user in the master realm.
The flow would be to:
login using a super-user/password to login into the master realm
get a list of all available realms and their users
craft a request to exchange the current access token with a new access token for that specific user.
It is the last step I cannot get to work.
Example:
Login to master realm
token=$(curl -s -d 'client_id=security-admin-console'
-d 'username=my-super-user' -d 'password=my-super-pass' \
-d 'grant_type=password' \
'https://login.example.net/auth/realms/master/protocol/openid-connect/token' | jq -r .access_token)
(we now have an access token for the super-user in the master realm)
The Keycloak server has enabled token exchange (-Dkeycloak.profile.feature.token_exchange=enabled) as described here https://www.keycloak.org/docs/latest/securing_apps/#_token-exchange.
Attempt to impersonate a user in another realm (not master):
curl -s -X POST "https://login.example.net/auth/realms/some_realm/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d 'client_id=some_client' \
-d "requested_subject=some_user" \
-d "subject_token=$token"
However, this does not work. The result is: {"error":"invalid_token","error_description":"Invalid token"}
(Doing this inside a single realm work)
What am I doing wrong here? This seems like a very normal feature to utilize in a real-life deployment, so any help is much appreciated!
UPDATE:
First of all, I found the very same use-case here: https://lists.jboss.org/pipermail/keycloak-user/2019-March/017483.html
Further, I can get it to work by working through some major hoops. As described above, one can use the broker client in the master realm as an identity provider:
Login as super-user adminA -> TokenA
use TokenA to get a new external token, TokenExt from the master identity provider.
Use TokenExt to do a token exchange for the user you want to impersonate
The caveat with the above is that the user adminA is created in each of the realms you log into with this method, so still not ideal.
as far as I know what you are describing is not possible. I'm wondering where you are, more than a year afterwards... did you solve your issue?
Before going further, note that I have found Keycloak discourse a good forum for Keycloak questions: https://keycloak.discourse.group/
Second, this is what I understand: for Keycloak, 2 realms or 2 different Keycloaks is the same. There is nothing common, they are 2 completely different id providers. So any reasoning that supposes shared trust or shared users between realms will not work.
For logging in to the other realm, you need a token that is trusted. There is no reason for the other realm to trust the master realm. The way to set that trust is to set up the master realm client as an identity provider to the other realm (I understand that this is what you do not want to do), so that tokens signed by the master realm will be trusted by the other realm.
And once you have that set up, I have not seen any other way of exchanging than having the token exchange create a federated "admin" user in the other realm (I configure it to be created each time from scratch, to avoid any synch). Also, 2 mappings are going to come in to play, the ID provider mapping, and the client mapping, for creating the resulting JWT.
If this doesn't match with your findings, please correct me.
Ah yes: there is also the question of using token exchange as defined in OAuth, with the may_act claim, which would be perfect here. But it would come after the exchange between realms, in addition. See https://datatracker.ietf.org/doc/html/rfc8693#section-4.4
EDIT: to "create the user each time from scratch"
go to "identity providers" / / "settings"
select "sync mode" to "force"
This is the relevant extrant from the tooltip:
The sync mode determines when user data will be synced using the
mappers. Possible values are: 'legacy' to keep the behaviour before
this option was introduced, 'import' to only import the user once
during first login of the user with this identity provider, 'force' to
always update the user during every login with this identity
provider.
so when you choose "force", basically the user will be overwritten at each login.
Ok so it's not really a creation, but as close as you can get :-)
The idea here is to not care about it, which is fine for prototyping. But I guess that in production you may want to optimize this.

Keycloak: grant_type=password in custom Identity Provider

I added a custom OIDC Identity Provider to my realm and i want to use the Direct Access Grants flow (or grant_type=password) but this doesn't work.
Is it possible with Keycloak?
When try with Authorization Code flow every thing works fine but with
grant_type=password the error
{
"error":"invalid_grant",
"error_description":"Invalid user credentials"
}
is returned.
I'm trying to get the access token e the refresh token doing the following request:
$ curl -X POST 'http://localhost:8080/auth/realms/master/protocol/openid-connect/token'
-H 'content-type: application/x-www-form-urlencoded'
-d 'grant_type=password'
-d 'client_id=test-client'
-d 'client_secret=834a546f-2114-4b50-9af6-697adc06707b'
-d 'username=user' // valid user in custom Identity Provider
-d 'password=password' // password in custom Identity Provider
And this is the Identity Provider configuration:
this is the Identity Provider configuration
Please have a look below curl command
curl -X POST -k -H 'Content-Type: application/x-www-form-urlencoded' -i 'https://135.250.138.93:8666/auth/realms/<Realm-Name>/protocol/openid-connect/token' --data 'username=<userName>&password=<Password>&client_id=<Client-ID>&grant_type=password&client_secret=7df18c0d-d4c7-47b1-b959-af972684dab0'
In above command you have to provide these details
Realm-Name - Realm name against which you want token
userName - You should have a user which can access the above realm
Password - Password for above user
Client-ID - Client Name(Generally its a String Value) under the
Client-Secret - Client secret of above client which you can find [Realm->Client List->Select the client->Credential tab]
I was also stuck with this issue as well. In the beginning I also suspected that it looked like a bug. However, the turning point is that I tried with the master realm and the client_id=admin-cli with my admin user. I can retrieve the token with grand_type=password. It's just failed for my own realm and client_id like reported here.
I figured out my issue is that the user I used wasn't activated after I tried to login into my realm's console(eg: http://localhost:18080/auth/realms/quarkus-workshop-labs/account/). I need to reset my password, so it can be finally activated. Then the password grant_type just starts to work.
(note that by default, your new created user needs to reset password before it can use.)
Keycloak doing below validations before the DirectGrant auth flow.
username
password
otp (if configured)
if the user is enabled
if the user is locked due to brute force direction (only if it's enable)
You can customize this in Authentication -> Flows and select Direct grant flow.
For example you can disable Direct Grant - Conditional OTP to genarate token without checking otp.
Yes it is possible.
You need to enable/Grant Direct access in Keycloak settings for the particular client.
You need to set a client with test-client and the user should be available in the realm. Though cannot get what you wanna achieve with this 🧐
I got exactly same scenario it looks like a bug to me. I had to unlink the account from IDP, set the password and remove pending user actions. It is not a solution but in my case was ok as I needed only test user account for API tests and don't have that scenario on production.
I was able to use DAG if I set the (automatically provisioned) user's password in Keycloak to something and with that password I was able to get the token from the external iDP. I used this to investigate an Okta token. Hope this helps.
I think this is actually the right answer: answer.
To summarize: You can't do exactly what you requested, because Keycloak is not storing the password in DB, so password grant type flow is not valid for this user.
The alternative is to use Token Exchange feature that allows you to login to OIDC directly and use it's access token to retrieve keycloak access token.
There is an example code in the linked answer.