This is a clarification to the previous write up about Keycloak Authorization Services. The documentation of the response_mode
documents the two values which can be used: decision
and permissions
. In the first Keycloak article, I have wrongly assumed that no response_mode
in the grant_type=urn:ietf:params:oauth:grant-type:uma-ticket
call implies the value of permissions
.
Mmm, that was a wrong assumption.
Now, looking at the documentation and trying it out, the distinction seems pretty obvious. It turns out there are three types of responses for this grant_type
.
- Asking for
RPT
(requesting party token - an access token with permissions): without response_mode
parameter
1
2
3
4
5
6
|
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=customers" \
--data "permission=CustomerB#customer-b" | jq '.'
|
where the ${access_token}
is the outcome of:
1
2
3
4
|
export access_token=`curl --silent -u customers:${KEYCLOAK_CLIENT_SECRET} \
-k -d "grant_type=password&username=member@service-team&password=${USER_PASSWORD}&scope=email profile" \
-H "Content-Type:application/x-www-form-urlencoded" \
${KEYCLOAK_TOKEN_URL} | jq '.access_token' -r`
|
the response looks like this, the access_token
is the RPT
:
1
2
3
4
5
6
7
8
9
|
{
"upgraded": false,
"access_token": "eyJhbGciOiJSUzI1NiIsI...n8AC51T1AMwDtoqfCEXrdwcrQ",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUz...RG3zFus",
"token_type": "Bearer",
"not-before-policy": 0
}
|
- Asking for permissions - decision only:
response_mode=decision
By adding:
--data "response_mode=decision"
the full call is:
1
2
3
4
5
6
7
|
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=customers" \
--data "response_mode=decision" \
--data "permission=CustomerB#customer-b" | jq '.'
|
and returns only a decision. If user has access to the resources, the response is:
otherwise, the response is:
1
2
3
4
|
{
"error": "access_denied",
"error_description": "not_authorized"
}
|
- Asking for permissions:
response_mode=permissions
By specifying
--data "response_mode=permissions"
full call being:
1
2
3
4
5
6
7
|
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=customers" \
--data "response_mode=permissions" \
--data "permission=CustomerB#customer-b" | jq '.'
|
Keycloak answers:
1
2
3
4
5
6
7
8
9
|
[
{
"scopes": [
"customer-b"
],
"rsid": "00f34b81-c45b-4e28-b267-45fad4e48b4d",
"rsname": "CustomerB"
}
]
|
However, what is more interesting, is the call without specific permissions listed:
1
2
3
4
5
6
|
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=customers" \
--data "response_mode=permissions" | jq '.'
|
which returns all available permissions for the original access token:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[
{
"scopes": [
"customer-a"
],
"rsid": "715f6cc5-8ca7-44e4-a8ce-924493db76b1",
"rsname": "CustomerA"
},
{
"scopes": [
"customer-b"
],
"rsid": "00f34b81-c45b-4e28-b267-45fad4e48b4d",
"rsname": "CustomerB"
}
]
|
§Listing permissions without the name
Optionally, we can ask Keycloak to not return resource names, only IDs. This is achieved by using response_include_resource_name=false
, an example:
1
2
3
4
5
6
7
|
curl --silent -X POST \
${KEYCLOAK_TOKEN_URL} \
-H "Authorization: Bearer ${access_token}" \
--data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
--data "audience=customers" \
--data "response_mode=permissions" \
--data "response_include_resource_name=false" | jq '.'
|
gives:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[
{
"scopes": [
"customer-a"
],
"rsid": "715f6cc5-8ca7-44e4-a8ce-924493db76b1"
},
{
"scopes": [
"customer-b"
],
"rsid": "00f34b81-c45b-4e28-b267-45fad4e48b4d"
}
]
|