Authentication Token

Prerequisites

To receive an Authentication Token (or User Access Token) we need a registered client. For testing and integration the following can be used, assuming you have obtained a ClientID and Client Secret from PISTIS Consortium:

clientId        <a-client-id>
clientSecret    *****

NOTE: For factory deployments see: Factory Registry → Keycloak Clients.

For the example, user: 00-test is used just for reference.

Receive token

NOTE

This is only a quick example on how to get an access token using username/password for testing.

The correct way of authenticating a user is done via redirection in the UI and an example configuration can be found in the Integration with Frontend guide.

We can obtain the access_token of the user via the following request:

curl --location 'https://auth.pistis-market.eu/realms/PISTIS/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=a-client-id' \
--data-urlencode 'client_secret=*****' \
--data-urlencode 'username=00-test' \
--data-urlencode 'password=*****'

A sample response of the above request will be:

{
  "access_token": "eyJhbGciOiJSUzI1Ni....",
  "expires_in": 7200,
  "refresh_expires_in": 7200,
  "refresh_token": "eyJhbGciOiJIUzI1N.....",
  "token_type": "Bearer",
  "not-before-policy": 0,
  "session_state": "88b2cf48-b342-462a-81f0-0935c406a885",
  "scope": "email profile pistis"
}

Decode token

Online via JWT.io

The received access_token is a signed JWT and can be decoded, for example using jwt.io

The decoded JWT will have the following payload:

{
  "exp": 1720701033,
  "iat": 1720693833,
  "jti": "0c4070b5-e2db-429e-9675-1006d574ea5f",
  "iss": "https://auth.pistis-market.eu/realms/PISTIS",
  "aud": "account",
  "sub": "dca6be83-9aff-42c4-8598-1f5ac89078ad",
  "typ": "Bearer",
  "azp": "pistis-test-only",
  "session_state": "88b2cf48-b342-462a-81f0-0935c406a885",
  "acr": "1",
  "realm_access": {
    "roles": [
      "PISTIS_USER",
      "offline_access",
      "uma_authorization",
      "default-roles-pistis"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "email profile pistis",
  "sid": "88b2cf48-b342-462a-81f0-0935c406a885",
  "email_verified": false,
  "pistis": {
    "user": {
      "role": [
        "PISTIS_USER",
        "offline_access",
        "uma_authorization",
        "default-roles-pistis"
      ],
      "validationCommittee": "vc"
    },
    "group": {
      "country": "GR",
      "size": "Medium",
      "domain": "ICT",
      "id": "56885023-abd0-4545-a83a-3c7c74a7cbf4",
      "type": "Research"
    }
  },
  "preferred_username": "00-test",
  "given_name": "",
  "family_name": "",
  "group": [
    "/00_TEST"
  ]
}

NOTE: pistis object in the JWT is an extension to default OpenID claim to include dedicated information for PISTIS.

Mapping of PISTIS attributes in token claims

User has the attributes:

  • mapped roles, mapped in pistis.user.role claim
  • validationCommittee: vc, mapped in pistis.user.validationCommittee claim

Organization of the user has the following attributes:

  • size: Medium, mapped in pistis.group.size claim
  • domain: ICT, mapped in pistis.group.domain claim
  • country: GR, mapped in pistis.group.country claim
  • type: Research, mapped in pistis.group.type claim
  • id: UUIDv4, mapped in pistis.group.id claim (required by factory registration)

Organization of the user is mapped in group claim

Postman script

The following script can be included as a test operation in a Postman request to directly decompile the access_token:

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(jwtInfo.payload, null, 28);
pm.visualizer.set(template, {
    response: payload.trim()
});