Keycloak: cannot get token from a custom spi - keycloak

I have to create two rest services via keycloak.
The first one sends a verification code to a phone number. The second one grant a token to a user if the verification code is correct for a given phone number.
I have created a module with a custom SPI following the guide in https://github.com/FX-HAO/keycloak-phone-authenticator. The provider can be found. I have also created the Direct grant flow copy and made it the default direct grant flow for the realm.
I can send the verification code with a request to http://{host}//auth/realms/{my_realm}/{my_provider}/send_sms
However, I cannot get the token using the following request:
curl -X POST http://{host}/auth/realms/{my realm}/protocol/openid-connect/token
-H 'authorization: Basic {my keycloak admin username and password}'
-H 'content-type: application/x-www-form-urlencoded' -d 'grant_type=password&phone_number={phone number}&code={code}'
I keep getting the invalid_client_credentials error and it seems that my provider is not called because there is nothing in its logs.
What am I doing wrong?

As #sventorben said, the problem was in specifying wrong credentials for the client

Related

How do I set up a Google Cloud Function with Authentication?

Disclaimer: I'm completely new to Google Cloud Functions and serverless functions in general.
I've set up a basic Google Cloud Function, set it to HTTPS trigger and Require Authentication, and given the service account and my account the cloud function invoker role.
However, whenever I use Postman to sent an HTTP request to the function using my oauth2 token, I get a 401 Unauthorized error.
I've also followed the steps here: https://cloud.google.com/functions/docs/securing/authenticating
to create and download the service account key and make an HTTP request using cURL and get the same error.
How do I need to set this up so that authorized users can send HTTP requests to this function?
Here's what I'm doing:
$gcloud auth login (to log in with my account with cloud invoker permission)
$curl https://my-trigger-url \ -H "Authorization: bearer $(gcloud auth print-identity-token)"
Guillaume found the solution:
My cURL syntax to trigger the Cloud Function needed the -H "Authorization: bearer $(gcloud auth print-identity-token)" before the URL instead of after, which is the opposite of Google's own documentation.
Thanks for your help.

Getting Users and groups from Keycloak

I have a web application secured by Keycloak. Now I want to read all the security groups and users from keycloak in my application. Is it possible?
Keycloak has a very good documentation around the APIs.
I believe you are looking to get all the groups and users from the Keycloak. It could be as straightforward as calling any REST APIs.
You can follow this link to get all the groups from the Keycloak.
And this link to get the users based on the given search criteria.
But I would be wary of the performance implication it might have calling these APIs. Make sure to use pagination and appropriate filters for getting users.
Also, if you want, you can write a custom extension in Keycloak to serve your purpose. You can follow this link for it.
I could get the access token using the client secret key using the curl command from command line.
$curl -X POST -d "client_id=my_client" -d "username=username" -d "client_secret=c957b0ba-c421-4021-8433-764aa2fwes72" -d "grant_type=client_credentials" HOST/auth/realms/my_realm/protocol/openid-connect/token
I could also get the list of users after getting the access token
$curl -X GET HOST/auth/admin/realms/my_realm/users -H "Authorization: Bearer access-token" -H 'cache-control: no-cache'
Now, I'm thinking how can I do this from my web application.

Keycloak impersonation API not implemented

I've been trying to use the Keycloak Impersonation API (semi-recent addition) to get an access token for another user. I have created a semi-successful CURL request based on the docs and another StackOverflow question. The CURL request (below) returns a 501 Not Implemented and I am trying to figure this out. If it would be another error I would assume I am doing something incorrectly, but this appears to be at least partially correct.
curl --verbose -X POST "http://localhost:8081/auth/realms/master/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=admin-cli" \
-d "requested_subject={TARGET_USER_ID}" \
-d "subject_token={USER_MANAGER_TOKEN}"
My workflow so far has been to get the Keycloak master realm "admin" user's access token (successful) and use that in the impersonation request, along with the target user's Keycloak ID. Am I doing something wrong or missing a step?
I haven't changed any Keycloak permissions, is this required?
From my understanding and the documentation, impersonation is currently supported and enabled by default in Keycloak v5 - Sever Installation. However, another article (Keycloak v5 - Token Exchange) seems to indicate that the feature is disabled by default; could this be why I am getting the 501 Not Implemented?
EDIT: #qdivision mentioned that the Token Exchange needs to be enabled for this to work. However, we are using the jboss/keycloak Docker image and I am wondering where I should add the profile.properties file to enable this feature?
Impersonation is enabled by default, Token Exchange is not.
To enable start the server with -Dkeycloak.profile=preview or -Dkeycloak.profile.feature.token_exchange=enabled as mentioned in the docs
https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange

How to obtain the authorization code required for User Credentials through the cURL's command line

I trying to use GCS "User Credentials" to connect to Google cloud storage using libcurl library.
"User Credentials" authentication needs Client Id & Secret key to connect to GCS, but in this process Authentication Code also needs to be generated.
I need to generate this Authentication code using cURL.
Can anyone help me ??
The Client ID you mentioned is the same as the Authentication ID and can only be generated from either the Cloud Console's Credentials Page or via the OAuth 2.0 Playground.
If you are trying to generate an Access Token (OAUTH2_TOKEN), you will need to complete an authentication flow to authorize requests as a user. Cloud Storage uses OAuth 2.0 for API authentication and authorization.
Here's what you need to do to get an authorization access token from the OAuth 2.0 Playground:
Select & authorize APIs (Cloud Storage)
Select the scope for the APIs you would like to access or input your own OAuth scopes, e.g.: https://www.googleapis.com/auth/devstorage.read_write
Then click the "Authorize APIs" button
Once you've got the Authorization Code click the "Exchange authorization code for tokens" button, you will get a refresh and an access token which is required to access OAuth protected resources.
Grab the Access Token to use in your cURL command
Then configure your request to Cloud Storage API by constructing your HTTP request like so (upload):
curl -X POST --data-binary #[OBJECT_LOCATION] \
-H "Authorization: Bearer [OAUTH2_TOKEN]" \
-H "Content-Type: [OBJECT_CONTENT_TYPE]" \
"https://www.googleapis.com/upload/storage/v1/b/[BUCKET_NAME]/o?uploadType=media&name=[OBJECT_NAME]"
You can have a look at this Cloud Storage upload example in our public docs to guide you with constructing a request and testing it out.
Hope this helps.

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.