OIDC Claims not returned in token

This topic has 5 replies, 3 voices, and was last updated 1 week, 2 days ago by Scott Heger.

  • Author
    Posts
  • #28664
     deevodavis
    Participant

    For the life of me I can’t get any claims / userinfo returned in the JWT token returned as part of the ‘/oauth2/access_token’ API call and wondered if someone could help me to resolve/debug.

    I have followed the instructions here to modify the OIDC claims script and assigned it to my OAuth2 Provider under the OIDC Claims Script setting.

    I’ve restarted countless times, and it’s almost as if it’s not executing the script at all; I have managed to find the AM logs (and modified the logger levels) and I can see that the ‘May Act’ script assigned is executed, but it doesn’t seem to be executing the OIDC script.

    I have checked that the “enable claims_parameter_supported” is enabled, as too is the “always return claims in ID tokens” for the OAuth2 Provider.

    The call I am making to get the token is as follows:

    curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/access_token' \
    --header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ=' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=password' \
    --data-urlencode 'username=user1' \
    --data-urlencode 'password=7fYCi0Frhcq5p3gCXGxJ2B' \
    --data-urlencode 'scope=cn' \
    --data-urlencode 'claims={"id_token": {"roles":null, "name": null, "email": null}}'

    which returns an ‘access_token’ as follows:

    {
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIodXNyIXVzZXIxKSIsImN0cyI6Ik9BVVRIMl9TVEFURUxFU1NfR1JBTlQiLCJhdXRoX2xldmVsIjowLCJhdWRpdFRyYWNraW5nSWQiOiJhZmZhYWQxNy03YWIwLTQxMjEtOTEzYi1mY2FiYTFkMmVkY2ItMzQ4OTkiLCJzdWJuYW1lIjoidXNlcjEiLCJpc3MiOiJodHRwOi8vYW0uZXhhbXBsZS5jb206ODA4MC9hbS9vYXV0aDIiLCJ0b2tlbk5hbWUiOiJhY2Nlc3NfdG9rZW4iLCJ0b2tlbl90eXBlIjoiQmVhcmVyIiwiYXV0aEdyYW50SWQiOiI4V21ONEh0cENGLW5NRHZ3VU5PeGd1dF8yeUkiLCJhdWQiOiJzdGV2ZSIsIm5iZiI6MTYzMDA2MjkxNSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwic2NvcGUiOlsiY24iXSwiYXV0aF90aW1lIjoxNjMwMDYyOTE1LCJjbGFpbXMiOiJ7XCJpZF90b2tlblwiOiB7XCJyb2xlc1wiOm51bGwsIFwibmFtZVwiOiBudWxsLCBcImVtYWlsXCI6IG51bGx9fSIsInJlYWxtIjoiLyIsImV4cCI6MTYzMDA2NjUxNSwiaWF0IjoxNjMwMDYyOTE1LCJleHBpcmVzX2luIjozNjAwLCJqdGkiOiJ6NTFsM1BXYlFJaW4wSWJLamE3Tm12Vi1fUEUiLCJtYXlfYWN0Ijp7ImNsaWVudF9pZCI6InN0ZXZlIiwic3ViIjoiKHVzciF1c2VyMSkifX0.puVvth9YenEDfUZaFtzzgunACe8TEnhlj-Bo66z6s80",
        "refresh_token": "eyJ...",
        "scope": "cn",
        "token_type": "Bearer",
        "expires_in": 3599
    }

    If I decode this token I can see this in the payload:

    {
      "sub": "(usr!user1)",
      "cts": "OAUTH2_STATELESS_GRANT",
      "auth_level": 0,
      "auditTrackingId": "affaad17-7ab0-4121-913b-fcaba1d2edcb-34899",
      "subname": "user1",
      "iss": "http://am.example.com:8080/am/oauth2",
      "tokenName": "access_token",
      "token_type": "Bearer",
      "authGrantId": "8WmN4HtpCF-nMDvwUNOxgut_2yI",
      "aud": "steve",
      "nbf": 1630062915,
      "grant_type": "password",
      "scope": [
        "cn"
      ],
      "auth_time": 1630062915,
      "claims": "{\"id_token\": {\"roles\":null, \"name\": null, \"email\": null}}",
      "realm": "/",
      "exp": 1630066515,
      "iat": 1630062915,
      "expires_in": 3600,
      "jti": "z51l3PWbQIin0IbKja7NmvV-_PE",
      "may_act": {
        "client_id": "steve",
        "sub": "(usr!user1)"
      }
    }

    I’m pretty sure it’s just a configuration issue, but I was expecting the payload to contain the full userinfo (as that’s what I thought the “always return claims in ID tokens” option did?). If I remove the “claims” parameter I still don’t get anything relevant.

    I have added my user to a group per the link quoted above and don’t get roles out either. I’ve added “roles” “email”, “name”, “given_name” .. to every “claims” related field I could find and still nothing.

    Can anyone help? Thanks Steve

    • This topic was modified 3 weeks ago by deevodavis.
    #28666
     deevodavis
    Participant

    OK, so a little more info and progress, as my understanding grows…

    If I use the Implicit No Browser flow and do an initial authenticate, followed by an authorize and request a “response_type” with value “token id_token” then I get back an “access_token” and an “id_token”.

    If I decode the “id_token” then I can see the claims in that tokens payload.

    So, clearly I’m misunderstanding whether “claims” should be in an access_token at all.

    I guess my question now is, if I call the “http://am.example.com:8080/am/oauth2/realms/root/access_token” API would I ever expect to see the “claims” or do I need to exchange the access_token for an id_token somehow?

    Thanks

    #28667
     deevodavis
    Participant

    OK, I believe I needed to do a token exchange to swap the access_token for an id_token.

    This is the call in CURL terms… (using a new “access_token” to that shown above above)

    curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/access_token' \
    --header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ=' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
    --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
    --data-urlencode 'subject_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIodXNyIXVzZXIxKSIsImN0cyI6Ik9BVVRIMl9TVEFURUxFU1NfR1JBTlQiLCJhdXRoX2xldmVsIjowLCJhdWRpdFRyYWNraW5nSWQiOiJhZmZhYWQxNy03YWIwLTQxMjEtOTEzYi1mY2FiYTFkMmVkY2ItNTc4NzMiLCJzdWJuYW1lIjoidXNlcjEiLCJpc3MiOiJodHRwOi8vYW0uZXhhbXBsZS5jb206ODA4MC9hbS9vYXV0aDIiLCJ0b2tlbk5hbWUiOiJhY2Nlc3NfdG9rZW4iLCJ0b2tlbl90eXBlIjoiQmVhcmVyIiwiYXV0aEdyYW50SWQiOiIwOExpLVlGM2RKNk5WUlVCTDZNOWZ5REFQazQiLCJhdWQiOiJzdGV2ZSIsIm5iZiI6MTYzMDA2NzA2NSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwic2NvcGUiOlsiY24iXSwiYXV0aF90aW1lIjoxNjMwMDY3MDY1LCJjbGFpbXMiOiJ7XCJpZF90b2tlblwiOiB7XCJyb2xlc1wiOm51bGwsIFwibmFtZVwiOiBudWxsLCBcImVtYWlsXCI6IG51bGx9fSIsInJlYWxtIjoiLyIsImV4cCI6MTYzMDA3MDY2NSwiaWF0IjoxNjMwMDY3MDY1LCJleHBpcmVzX2luIjozNjAwLCJqdGkiOiJoam4xcVMxVktwUHBSZHBJdnVrRnhFaTJEOEUiLCJtYXlfYWN0Ijp7ImNsaWVudF9pZCI6InN0ZXZlIiwic3ViIjoiKHVzciF1c2VyMSkifX0.I5Z7QtCznkcJPGTKtsGEmrHXvDYDY4E92dBnJhm7hLM' \
    --data-urlencode 'scope=cn' \
    --data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:id_token' \
    --data-urlencode 'claims={"id_token": {"roles":null, "name": null, "email": null}}'

    which gives me a token which when decoded gives me this:

    {
      "sub": "(usr!user1)",
      "auditTrackingId": "affaad17-7ab0-4121-913b-fcaba1d2edcb-61669",
      "roles": [
        "ROLE_DEVELOPER"
      ],
      "subname": "user1",
      "iss": "http://am.example.com:8080/am/oauth2",
      "tokenName": "id_token",
      "aud": "steve",
      "azp": "steve",
      "auth_time": 1630067065,
      "name": "User One",
      "realm": "/",
      "may_act": {
        "client_id": "steve",
        "sub": "(usr!user1)"
      },
      "exp": 1630071141,
      "tokenType": "JWTToken",
      "iat": 1630067541,
      "email": "[email protected]"
    }

    You can see from the payload that it now gives me a “name”, “email” and “roles” claim.

    Happy days…

    • This reply was modified 3 weeks ago by deevodavis.
    #28669
     deevodavis
    Participant

    Additional information for anyone else coming this way..

    Ref: https://developer.okta.com/docs/guides/validate-id-tokens/overview/

    ID Tokens vs Access Tokens

    The ID Token is a security token granted by the OpenID Provider that contains information about an End-User. This information tells your client application that the user is authenticated, and can also give you information like their username or locale.

    You can pass an ID Token around different components of your client, and these components can use the ID Token to confirm that the user is authenticated and also to retrieve information about them.

    Access tokens, on the other hand, are not intended to carry information about the user. They simply allow access to certain defined server resources.

    • This reply was modified 3 weeks ago by deevodavis.
    #28671

    thanks for posting the issue and sharing your understandings. It’s helping others.

    #28688
     Scott Heger
    Participant

    In your very first access_token request if you include the scope “openid” then AM will return an id_token along with the access_token….assuming you set up your realm as an OpenID Connect provider. So:

    curl --location --request POST 'http://am.example.com:8080/am/oauth2/realms/root/access_token' \
    --header 'Authorization: Basic c3RldmU6cGFzc3dvcmQ=' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=password' \
    --data-urlencode 'username=user1' \
    --data-urlencode 'password=7fYCi0Frhcq5p3gCXGxJ2B' \
    --data-urlencode 'scope=cn openid'
Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.

©2021 ForgeRock - we provide an identity and access platform to secure every online relationship for the enterprise market, educational sector and even entire countries. Click to view our privacy policy and terms of use.

Log in with your credentials

Forgot your details?