Jayesh Dhandha
Jayesh Dhandha

Reputation: 2129

How to add array values in Claims of IdToken in Cognito using claimsToAddOrOverride

I am using Pre Token Generation to update the claims of IdToken.

I am successfully able to update claim using single key:value pair. Below is the sample example of that.

event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": "test.debug"}}}

But when i am trying to add array of string inside that, it giving me internal server error (Response from AWS Cognito)

Ex:

event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": ["test1","test2]}}}

It is working fine using 'Test' option of lambda function.

If i am using groupsToOverride then it is overriding the cognito:groups claim.

Any help?

Upvotes: 13

Views: 6350

Answers (3)

NULL pointer
NULL pointer

Reputation: 1377

As annoying as it is, this is behaving as documented here.

The response.claimsOverrideDetails.claimsToAddOrOverride where you correctly are adding the claims you want added to the jwt takes a StringMap type, which is an object with all key value pairs having all values being strings.

This is in spite of the fact that some of the claims provided by AWS and passed into the PreTokenGeneration lambda are not strings, such as auth_time which is a number.

I find this particuarly annoying when I want to add a 'isRegistrationComplete' boolean to the jwt (which is used to force display of the pages to collect final registration details). I need to pass it in as:

{
  isRegistrationComplete: "true"
}

or

{
  isRegistrationComplete: "false"
}

Hence for your array, you must encode it as a string first.

You can do this for any object (including your array) using JSON.stringify() in the lambda code, and JSON.parse() code in your client.

You can find this documented on this page (find the text: "claimsToAddOrOverride": {"string": "string"},)

Upvotes: 3

Erwin
Erwin

Reputation: 672

The name scope have special meaning in a JWT, libraries expect this to be a list in string form separated by space. So the scopes test1 and test2 would become "test1 test2".

I would recommend using space as separator and not any other format. If you prefer another format just give your field a different name - like group.

{
  "iss": "https://authorization-server.example.com/",
  "sub": " 5ba552d67",
  "aud":   "https://rs.example.com/",
  "exp": 1544645174,
  "client_id": "s6BhdRkqt3_",
  "scope": "openid profile reademail"
}

Upvotes: 0

Sam Shiles
Sam Shiles

Reputation: 11259

I think this must be a bug with Cognito and unfortunately will require a workaround until it's resolved.

It's not ideal I know, but I've worked around this issue by using a delimited string which I then parse to an array when I receive the token.

Lambda:

exports.handler = (event, context, callback) => {
    event.response = {
        "claimsOverrideDetails": {
            "claimsToAddOrOverride": {
                "scope": "test1|test2"
            }
        }
    };

    // Return to Amazon Cognito
    callback(null, event);
};

Client:

const token = jwt.decode(id_token);
const scopes = token.scope.split('|');

Upvotes: 12

Related Questions