Keycloak PUT-request returns 401 (unauthorized) - java

I am using postman and I've tried updating a user's profile via http://localhost:8180/auth/admin/realms/demo/users/{userID} but I received a 401 response.
The procedure I used:
Requested and received admin token via http://localhost:8180/auth/realms/master/protocol/openid-connect/token
Added token to request headers the appropriate way i.e Authorization: Bearer {access_token}
Sent Put request with Json content type and the user's info as body via http://localhost:8180/auth/admin/realms/demo/users/{userID}.
Unfortunately, I've received back-to-back 401 responses.
First request:
-Body(x-www-form-urlencoded)
client_id : admin_cli
username: ...
password: ...
grant_type: password
client_secret: ...
-To http://localhost:8180/auth/realms/master/protocol/openid-connect/token
Second request:
-Header -> Authorization: Bearer ...
-Body(JSON)
"email": "d#gmail.com",
"firstName": "divad",
"lastName": "d"
-To http://localhost:8180/auth/admin/realms/demo/users/{userID}

In your first call, the david user has to be one with admin-alike privileges. Otherwise, one gets an authorized error response for the actions that the david user does not have the privileges to perform. Have a look at this SO thread to check how to assign admin-alike privileges to a user.
For now let us request a token on the behalf of the master admin user as follows:
from the body response extract the access_token.
For the second call first, copy and paste the access_token to the Authorization > Type Bearer Token:
On the second call, instead of
http://localhost:8180/auth/admin/realms/demo/users/{userID}
you need to replace the userID parameter with the actual userID of the user that you are updating. To get userID you can call the following endpoint:
GET <YOUR_KEYCLOAK_DOMAIN>/auth/admin/realms/<YOUR_REALM>/users/?username=<THE_USERNAME>
or you can copy and paste from the Keycloak Admin Console, under the tab users:
So in Postman would look like:

Related

How to get a token for a POST request from Postman

The application is in Java.
application.yml
server:
port: 9000
platform.properties
jwt.secret="......."
jwt.expiration.time=864000000
jwt.header.prefix=Bearer
jwt.header=my_token
Controller
#PostMapping("/login")
public Result login(#RequestBody LoginRequestDto user){
return userService.login(user);
}
From Postman I'm trying to send a POST request to http://188.130.139.104:9000/login
On the Authorization tab, I select
Type: Basic Auth
I fill in the Username and Password fields
As a result , I get
Could not send request
This looks like you're using oauth2 access token. To replicate that on postman you have two options. The two options adds Authorization to the header of your request.
Option 1:
On the Authorization tab, scroll to Bearer Token. Then put in your token in the 'Token' input field.
Option 2:
You can add it to your headers directly via the Header tab

How to refreseh keycloak user token from the refresh token in java

Due to the architecture of our product, the loadbalancer that I use is not able to manage correctly my servers. To solve this point, I have create a kind of manager which forward the call to the correct server by requesting it directly from the first server when it is needed. The issue is to do that I forward the user keycloak token string in the header of the second call. It works pretty well but after few minutes to token is invalidate. I tried to refresh it by many way without success. I have 2 constraints. I can't reask the credentials to the user, and I can't use the keycloak secret because I'm working in a multi tenant / multi realm app. Do you have any idea?
I'm assuming that you have just the access_token on login.
First you need to exchange that access token for a refresh token (and another access token), you do this by calling:
HTTP POST {{host}}/auth/realms/{{realm}}/protocol/openid-connect/token
HEADERS:
Content-Type: application/x-www-form-urlencoded
BODY:
grant_type: urn:ietf:params:oauth:grant-type:token-exchange
subject_token: the_user_access_token
client_id: your_client_id (in my case this is "public")
requested_token_type: urn:ietf:params:oauth:token-type:refresh_token
you will get back a response that looks like this:
{
"access_token": "access_token_value",
"expires_in": access_token_time_in_seconds,
"refresh_expires_in": refresh_token_time_in_seconds,
"refresh_token": "refresh_token_value",
"token_type": "bearer",
...
}
So with this you have what you need to actually refresh your token with the following request:
HTTP POST {{host}}/auth/realms/{{realm}}/protocol/openid-connect/token
HEADERS:
Content-Type: application/x-www-form-urlencoded
BODY:
grant_type: refresh_token
refresh_token: refresh_token_value
client_id: public
This will get you the following response:
{
"access_token": "access_token_value",
"expires_in": access_token_time_in_seconds,
"refresh_expires_in": refresh_token_time_in_seconds,
"refresh_token": "refresh_token_value",
"token_type": "bearer",
...
}
Now you can repeat step 3 and 4 up until the maximum session duration.

Unable to get user info from OKTA with access token

I have valid access token from OKTA
when i call user info end point for user details i am getting 401 Unauthorised for the below POST request
https://*******.okta.com/oauth2/epros/v1/userinfo
Authorization : Bearer **
I have claims defined at OKTA for accesstoken as well
Any clue why for valid access token, i am getting 401?
Assuming you have checked your token is still valid, not expired revoked etc.
Your userinfo endpoint looks a little odd, where you have epros you would normally have the id of the authorization server.
For example https://*****.okta.com/oauth2/ausaew0e1C0brPuB80x6/v1/userinfo
You may have truncated that address as if that value is wrong you would get 400 bad request.
The correct endpoint will always be the value in the iss claim in the token plus /v1/userinfo, if you are sending the access token of one to another authorization server's userinfo you will get a 401 response.

How to use Google Sign In Java front end and back end

In my application, all I want to do is to get the user's Gmail. I don't use any google services. I want to add Google Sign In for Java front end and validate the user in Java backend.
I am following openid-connect document.
By opening the following link in the browser, I can get the code.
(GET) Request:
https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?
response_type=code&
scope=openid&
redirect_uri=http://localhost:3000/auth/&
client_id=113291176157....
/auth endpoint gets the following:
{
code: '4/0AfDhmrjDTOo7zOrXxm98E...',
scope: 'openid',
authuser: '0',
prompt: 'none'
}
Now to get user details,
(POST) Request:
https://oauth2.googleapis.com/token
{
"code": "4/0AfDhmrjDTOo7zOrXxm98E...",
"client_id": "113291176157-aibhsqjf655ve...",
"client_secret": "lLjenLdeaJnd...",
"redirect_uri": "http://localhost:3000/auth",
"grant_type": "authorization_code"
}
But I get the following response:
{
"error": "redirect_uri_mismatch",
"error_description": "Bad Request"
}
I have added the redirect URL to credentials:
Right now, I'm hoping to open a browser window from Java front end for the user to login to Google. I will receive the code value, and it will get id_token and validate the user.
I have seen some javascript examples, where they get the id_token directly.
So I have multiple questions,
Why do I need to get the code first and request id_token later?
Why am I getting redirect_uri_mismatch error?
Authorization code exchange request looks like below,
URL: https://oauth2.googleapis.com/token
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code
The request should be POST and data should be sent as urlencoded data, not in the request body.
More information about code exchange

Refresh access_token via refresh_token in Keycloak

I need to make the user keep login in the system if the user's access_token get expired and user want to keep login. How can I get newly updated access_token with the use of refresh_token on Keycloak?
I am using vertx-auth for the auth implementation with Keycloak on vert.x. Is it possible to refresh access_token with vertx-auth or Keycloak's REST API itself? Or what will be another implementation of this?
keycloak has REST API for creating an access_token using refresh_token. It is a POST endpoint with application/x-www-form-urlencoded
Here is how it looks:
Method: POST
URL: https://keycloak.example.com/auth/realms/myrealm/protocol/openid-connect/token
Body type: x-www-form-urlencoded
Form fields:
client_id : <my-client-name>
grant_type : refresh_token
refresh_token: <my-refresh-token>
This will give you new access token using refresh token.
NOTE: if your refresh token is expired it will throw 400 exception in that you can make user login again.
Check out a sample in Postman, you can develop and corresponding API using this.
#maslick is correct you have to supply the client secret too, no need for authorization header in this case:
http://localhost:8080/auth/realms/{realm}/protocol/openid-connect/token
In case of expired refresh token it returns:
If you don't add the secret you get 401 unauthorized even though the refresh token is correct
I tried with 4.8.2.Final, it gives following unauthorized_client even with previous access token as 'Bearer'.
Then I tried with Basic YXBwLXByb3h5OnNlY3JldA== in Authorization header.
Then it worked, But still I'm not sure that I am doing right thing.
Extending Yogendra Mishra's answer. Note that
client_id and client_secret can also be sent in Authorization header.
Authorization: Basic ${Base64(<client_id>:<client_secret>)}
This works for both initial token call (without refresh token) and refresh token call to /openid-connect/token endpoint
Reference:
https://developer.okta.com/docs/reference/api/oidc/#client-secret

Categories