Repository: DuendeArchive/identity-model-oidc-client-js (JavaScript)

Issue:
ResponseValidator _mergeClaims not work as expected
Here is the case if I define my custom claims. For example, this is the full user payload
```
{ 
  email_verified: false,
  phone_number_verified: false,
  roles: [ 'cs', 'admin' ],
  enabled: true,
  preferred_username: 'user888',
  name: 'Nobody Wong',
  family_name: 'Wong',
  given_name: 'Nobody',
  middle_name: 'middle',
  nickname: 'nick',
  gender: 'm',
  birthdate: '2000/12/30',
  zoneinfo: 'HKG',
  locale: 'en',
  email: 'test888@test.com',
  address: 'xxxxx',
  phone_number: '888',
  updated_at: 2018-11-15T03:58:12.771Z,
  created_at: 2018-11-15T03:58:12.771Z,
  custom: { accountNumber: '019283747'},
  sub: '4df5d45c-6516-4a3a-8186-122163165701'
}
```
After login and get the user profile using Oidc.UserManager.getUser().  Follow data will be reture and found that the 'custom' field become array.
```
{
  "sub": "4df5d45c-6516-4a3a-8186-122163165701",
  "family_name": "Wong",
  "gender": "m",
  "given_name": "Nobody",
  "locale": "en",
  "middle_name": "middle",
  "name": "Nobody Wong",
  "nickname": "nick",
  "updated_at": "2018-11-15T03:58:12.771Z",
  "email": "test888@test.com",
  "email_verified": false,
  "phone_number": "888",
  "phone_number_verified": false,
  "roles": [
    "cs",
    "admin"
  ],
  "preferred_username": "user888",
  "custom": [
    {
      "accountNumber": "019283747"
    },
    {
      "accountNumber": "019283747"
    }
  ],
  "sid": "c274e159-8c11-4453-b8e1-95250173b25e",
  "s_hash": "aoMFqZCNSBJvwnTY1dpg_A"
}
```

Deep dive into the code and found out ResponseValidator._mergeClaims not work as expected. I extract the code fragment and do a test
```
let _obj1 = {
    custom: {
        foo: 'bar',
        ok: 'go',
        haha: 'lala'
    }
}
let _obj2 = {
    custom: {
        foo: 'bar',
        ok: 'go'
    },
    abcd: 123
}

function _mergeClaims(claims1, claims2) {
        var result = Object.assign({}, claims1);

        for (let name in claims2) {
            var values = claims2[name];
            if (!Array.isArray(values)) {
                values = [values];
            }

            for (let i = 0; i < values.length; i++) {
                let value = values[i];
                if (!result[name]) {
                    result[name] = value;
                }
                else if (Array.isArray(result[name])) {
                    if (result[name].indexOf(value) < 0) {
                        result[name].push(value);
                    }
                }
                else if (result[name] !== value) {
                    result[name] = [result[name], value];
                }
            }
        }

        return result;
    }

_obj1 = _mergeClaims(_obj1, _obj2)
```

The result will be 
````
{
  "abcd": 123,
  "custom": [
    {
      "foo": "bar",
      "haha": "lala",
      "ok": "go"
    },
    {
      "foo": "bar",
      "ok": "go"
    }
  ]
}
````

And expected result should be 
````
{
  "abcd": 123,
  "custom": {
    "foo": "bar",
    "haha": "lala",
    "ok": "go"
  }
}
````





Discussion:
do you have a proposal for a fix? PR would be welcome. Thanks
Fixed in #754 😄 
Thanks! I'll have a look when I can
PR merged. Thanks!



Patch:
diff --git a/src/ResponseValidator.js b/src/ResponseValidator.js
index 61979b02..47fb98e6 100644
--- a/src/ResponseValidator.js
+++ b/src/ResponseValidator.js
@@ -187,7 +187,12 @@ export class ResponseValidator {
                     }
                 }
                 else if (result[name] !== value) {
-                    result[name] = [result[name], value];
+                    if (typeof value === 'object') {
+                        result[name] = this._mergeClaims(result[name], value);
+                    } 
+                    else {
+                        result[name] = [result[name], value];
+                    }
                 }
             }
         }


Test patch:
diff --git a/test/unit/ResponseValidator.spec.js b/test/unit/ResponseValidator.spec.js
index 0187b35c..bcc95059 100644
--- a/test/unit/ResponseValidator.spec.js
+++ b/test/unit/ResponseValidator.spec.js
@@ -538,6 +538,14 @@ describe("ResponseValidator", function () {
 
         });
 
+        it("should merge claims when claim types are objects", function () {
+
+            var c1 = { custom: {'apple': 'foo', 'pear': 'bar'} };
+            var c2 = { custom: {'apple': 'foo', 'orange': 'peel'}, b: 'banana' };
+            var result = subject._mergeClaims(c1, c2);
+            result.should.deep.equal({ custom: {'apple': 'foo', 'pear': 'bar', 'orange': 'peel'}, b: 'banana' });
+        });
+
         it("should merge same claim types into array", function () {
 
             var c1 = { a: 'apple', b: 'banana' };