Authorization Token
Prerequisites
For the example we assume the following environment, as noted in Introduction and Authentication Token:
clientId <a-client-id>
clientSecret *****
Assume a registered Data Asset configured with all available Authorization Scopes: READ, EDIT, DELETE, TRADE.
id f1fbe38e-e143-45d4-a757-f11d18e14d85
name example-pistis-asset
Example policies for testing that:
- authorize anyone with PISTIS_USER role with the READ scope (thus all testing user will be granted with READ scope)
- exclusively allow user pdt-01 to grant EDIT, DELETE, TRADE scopes
Receive authorization for the asset
Initially, we should obtain the access_token of the user via the request described in Authentication Token
(section: Receive Token)
The authorization request for the specified Data Asset can be realized via:
curl --location 'https://auth.pistis-market.eu/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer ${access_token}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'audience=resource-server' \
--data-urlencode 'permission=f1fbe38e-e143-45d4-a757-f11d18e14d85'
where as:
resource-serveris the name of the dedicated client within Keycloak for assets (resources) authorization${access_token}should be replaced by theaccess_tokenas it is received in previous step- asset in the request is represented by the
permissionparameter and can be either asset name (example-pistis-asset) or asset id (f1fbe38e-e143-45d4-a757-f11d18e14d85)
Sample snippet with asset represented with asset name:
curl --location 'https://auth.pistis-market.eu/auth/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer ${access_token}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'audience=resource-server' \
--data-urlencode 'permission=example-pistis-asset'
Query for specific scope
permission parameter can be formulated like: {asset id}#{Scope} for example: 8852867a-d674-4918-903c-412493a2c2c7#READ or
{asset name}#{Scope}, for example: example-pistis-asset#READ
Multiple scopes can be separated using commas.
Sample snippet querying for a specific scope:
curl --location 'https://auth.pistis-market.eu/auth/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer ${access_token}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'audience=resource-server' \
--data-urlencode 'permission=example-pistis-asset#READ'
Sample snippet querying for a specific set of scopes:
curl --location 'https://auth.pistis-market.eu/auth/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer ${access_token}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'audience=resource-server' \
--data-urlencode 'permission=example-pistis-asset#READ,TRADE'
Authorization response modes
If parameter response_mode is specified to decision in the request, we will receive 200 OK if the requested operation is allowed
or 403 Forbidden otherwise.
Sample snippet querying in decision mode:
curl --location 'https://auth.pistis-market.eu/auth/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer ${access_token}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'audience=resource-server' \
--data-urlencode 'permission=example-pistis-asset#READ' \
--data-urlencode 'response_mode=decision'
Unauthorized response
If user has no authority on the requested asset the response will have 403 Forbidden status, with payload:
{
"error": "access_denied",
"error_description": "not_authorized"
}
Authorization examples
The response of such an authorization request will follow the OpenIDC with a response:
{
"upgraded": false,
"access_token": "",
"expires_in": 35999,
"refresh_expires_in": 35999,
"refresh_token": "",
"token_type": "Bearer",
"not-before-policy": 0
}
where access_token is the signed JWT containing the authorization information. When the access_token will be decompiled, it will contain
an authorization section, as illustrated in the following examples.
Example 1
User 00-test is granted with READ scope for the asset.
{
......
"authorization": {
"permissions": [
{
"scopes": [
"READ"
],
"rsid": "f1fbe38e-e143-45d4-a757-f11d18e14d85",
"rsname": "example-pistis-asset"
}
]
},
....
}
Example 2
User pdt-01 is granted all available scopes for the asset.
{
......
"authorization": {
"permissions": [
{
"scopes": [
"READ",
"TRADE",
"DELETE",
"EDIT"
],
"rsid": "f1fbe38e-e143-45d4-a757-f11d18e14d85",
"rsname": "example-pistis-asset"
}
]
},
....
}
Handy visualization script for Postman
The following script can be included as a test operation in a Postman request to directly decompile permissions included in the resulted access_token of the JWT claims:
var jsonData = pm.response.json();
pm.environment.set("jwt", jsonData.access_token);
function parseJwt (token,part) {
var base64Url = token.split('.')[part];
var words = CryptoJS.enc.Base64.parse(base64Url);
var jsonPayload = CryptoJS.enc.Utf8.stringify(words);
return JSON.parse(jsonPayload);
};
var jwtInfo ={};
jwtInfo.size = jsonData.access_token.length;
jwtInfo.header = parseJwt(jsonData.access_token,0);
jwtInfo.payload = parseJwt(jsonData.access_token,1);
jwtInfo.signature = jsonData.access_token.split('.')[2];
jwtInfo.expires = ((jwtInfo.payload.exp-Date.now().valueOf()/1000)/60).toFixed(1);
console.log(jwtInfo);
var auth = jwtInfo.payload.authorization;
console.log(auth);
var template = `
<style type="text/css">
div {white-space: pre-wrap;}
</style>
<div>
{{response}}
</div>
`;
const payload = JSON.stringify(auth, null, 28);
pm.visualizer.set(template, {
response: payload.trim()
});
