5

I'm developing some SpringBoot microservices that exposes REST through WSO2 APIM.

Microservice itself does not implement any kind of authentication or authorization mecanism, it is delegated to APIM.

If I set API to use Password Grant as described here, front end application can authenticate and generate JWT token.

The problem now is that I can't fetch user roles from JWT payload because it is not being added by APIM. This information is important because front-end render menus and buttons based on user roles.

The user I'm passing when generate token does have some roles as you can see bellow:

enter image description here

But generated JWT token does not include any information about roles. Here is a sample token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5UZG1aak00WkRrM05qWTBZemM1TW1abU9EZ3dNVEUzTVdZd05ERTVNV1JsWkRnNE56YzRaQT09In0.eyJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC9hcHBsaWNhdGlvbnRpZXIiOiJVbmxpbWl0ZWQiLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC92ZXJzaW9uIjoidjEiLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC9rZXl0eXBlIjoiUFJPRFVDVElPTiIsImlzcyI6IndzbzIub3JnXC9wcm9kdWN0c1wvYW0iLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC9hcHBsaWNhdGlvbm5hbWUiOiJDYWRhc3RybyBkZSBDbGllbnRlcyIsImtleXR5cGUiOiJTQU5EQk9YIiwiaHR0cDpcL1wvd3NvMi5vcmdcL2NsYWltc1wvZW5kdXNlciI6ImVtaWxpb0BjYXJib24uc3VwZXIiLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC9lbmR1c2VyVGVuYW50SWQiOiItMTIzNCIsImh0dHA6XC9cL3dzbzIub3JnXC9jbGFpbXNcL3N1YnNjcmliZXIiOiJhZG1pbiIsImh0dHA6XC9cL3dzbzIub3JnXC9jbGFpbXNcL3RpZXIiOiJVbmxpbWl0ZWQiLCJzY29wZSI6ImRlZmF1bHQiLCJleHAiOiIxNTk5NTYyOTQ4MDI4IiwiaHR0cDpcL1wvd3NvMi5vcmdcL2NsYWltc1wvYXBwbGljYXRpb25pZCI6IjIiLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC91c2VydHlwZSI6IkFwcGxpY2F0aW9uX1VzZXIiLCJjb25zdW1lcktleSI6IktJaTdnUk1RYmg1OWZGbmpVOFhNbnhGcm9pNGEiLCJodHRwOlwvXC93c28yLm9yZ1wvY2xhaW1zXC9hcGljb250ZXh0IjoiXC9ia25nXC92MSJ9.km4w2V7dGmoGl8f4_ZqKHvdofAPLOOw__GPjWKrpjYelbi7IjDIpRODEZNn8hE1krRdDTSjKRviJ-NBvXtTXIiLdfPh1p-zNtX26vrS77ZcSZ2WsQA7Ku21YMqcm6cyZvEhZ99qfTxOtbJfkwt6Yt8itkyr-aqk83pNp85LTnwtNboib9VOOvh37zNEJUImzKw4WvENp4SGLuHO978FriHyHPN9vibzPjpItW5DOXTFNdN4rP6RK_vcOH6hpuZHwivJpTHxf9qMB3Gd2yTig-Hkr-sZGbx89pQf8kqtCLWbhRG5jOtcEJNf2CSNLB0Glg_e4F6LfhVD5JUCz15jdlg

When I extract it in https://jwt.io/ I get following payload:

{
  "http://wso2.org/claims/applicationtier": "Unlimited",
  "http://wso2.org/claims/version": "v1",
  "http://wso2.org/claims/keytype": "PRODUCTION",
  "iss": "wso2.org/products/am",
  "http://wso2.org/claims/applicationname": "Cadastro de Clientes",
  "keytype": "SANDBOX",
  "http://wso2.org/claims/enduser": "emilio@carbon.super",
  "http://wso2.org/claims/enduserTenantId": "-1234",
  "http://wso2.org/claims/subscriber": "admin",
  "http://wso2.org/claims/tier": "Unlimited",
  "scope": "default",
  "exp": "1599562948028",
  "http://wso2.org/claims/applicationid": "2",
  "http://wso2.org/claims/usertype": "Application_User",
  "consumerKey": "KIi7gRMQbh59fFnjU8XMnxFroi4a",
  "http://wso2.org/claims/apicontext": "/bkng/v1"
}

How do I add user roles to JWT payload? Do I need to implement a custom generator as described here?

Thanks in advance!

Emilio Numazaki
  • 836
  • 1
  • 5
  • 25
  • In which token do you need role claim included? Is it the Authentication JWT or Backend JWT? – Praminda Sep 08 '20 at 11:47
  • Actually I was expecting to pass APIM generated token to backend to check roles when necessary or get roles in front-end to render specific content based on roles. Is this a viable approach? If so, is it a good practice? – Emilio Numazaki Sep 08 '20 at 13:25
  • Did you try `ClaimsRetrieverImplClass` configuration. Usage is documented in the "Passing enduser attributes..." doc. – Praminda Sep 10 '20 at 08:12
  • Yes it works but it is valid only for JWT sent to backend, I mean, APIM gets the request, checks JWT sent over header, generate new JWT and forwards to backend. This class and article is for this purpose no to client JWT, isn't it? What I need is user roles to JWT generated to API client. – Emilio Numazaki Sep 11 '20 at 13:37
  • Can you confirm the apim version in use? – Praminda Sep 17 '20 at 06:09
  • It is the latest, v3.2.0 – Emilio Numazaki Sep 17 '20 at 09:27

1 Answers1

5

Easiest way to get role claim included in the auth JWT is to add a claim mapping in service provider level and request the token with openid scopes. To do this try below steps.

  1. Log in to management console https://<host>:<port>/carbon

  2. List service providers in the left menu

  3. Go to edit on the required service provider (Each application in the developer portal has a mapping service provider)

  4. Add a claim mapping to role claim as below enter image description here

  5. Send the token request with the scope=openid parameter

    curl -k -X POST https://localhost:8243/token -d "grant_type=password&username=<Username>&password=<Password>&scope=openid" -H "Authorization: Basic <Credentials>"
    
  6. Response access token will contain roles in this format

    {
        "sub": "admin@carbon.super",
        "iss": "https://localhost:9443/oauth2/token",
        "groups": [
            "Internal/subscriber",
            "Internal/creator",
            "Application/apim_devportal",
            "Application/admin_NewApp_PRODUCTION",
            "Internal/publisher",
            "Internal/everyone",
            "Internal/analytics",
        ],
        ...
    }
    
Praminda
  • 565
  • 4
  • 8
  • 2
    Yes! It works this way. Actually I did something pretty different, in this case, I setup a IS-KM and configured SSO with OAuth2/OIDC, so when user requests access to protected resource, the request is forwarded to IS logon page, when access is granted, a token is forwarded through callback URL. But your approach is perfect when you're not using WEB API client. Thank you! – Emilio Numazaki Sep 17 '20 at 18:02