OpenID Connect not parsing multi-value (array/list) user attributes

We've setup Elasticsearch (7.5.0) to provide authentication and authorisation using OpenID Connect (a Keycloak setup in this case). Within the OIDC provider, we've mapped a custom User Attribute to be present as a field in the UserInfo response (also tried adding the same to the Access and ID Tokens, but the same problem persists).

This all works fine in Elasticsearch for AuthN and Role/Group based AuthZ (using a role mapping in ES to assign Roles to authentications users from the realm). It also works when passing a single value (i.e. a String) via the attribute, but when setting the OIDC Mapper to pass a multi-value (i.e. Array/List) of values back, Elasticsearch seems to simply ignore the field and it doesn't appear in the authenticated User's metadata.

I think this is a problem with the OpenIdConnectRealm parsing of attributes from the Claims/UserInfo - it checks the instanceof types of the claim Values is one of:

  • String
  • Boolean
  • Number
  • Collections
    But this last check seems invalid, presumably it should be Collection (i.e. to handle List, Set, Map objects) and not Collections (i.e. a class of static helper methods for dealing with Collection Objects... which isn't likely to ever be found in the serialised ID/Access Token or UserInfo objects from a OP).

To hopefully help a little with further diagnostics/discussion:

  • Example (sanitised) Access Token from OpenID Connect Provider when mapping department User Attribute as single-value field:
{
  "jti": "...",
  "exp": 1576508489,
  "nbf": 0,
  "iat": 1576508189,
  "iss": "...",
  "aud": [
    "realm-management",
    "account"
  ],
  "sub": "...",
  "typ": "Bearer",
  "azp": "elastic",
  "auth_time": 0,
  "session_state": "...",
  "acr": "1",
  "realm_access": {
    "roles": [
      ...
    ]
  },
  "resource_access": {
    "realm-management": {
      "roles": [
       ...
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
  "scope": "openid profile email",
  "email_verified": false,
  "department": "accounts",
  "name": "Chris S",
  "groups": [
    ...
  ],
  "preferred_username": "chris.s@...",
  "given_name": "Chris",
  "family_name": "S",
  "email": "chris.s@..."
}
  • Logging in to Kibana via OIDC and calling GET /_security/_authenticate from the Dev Tools console, I see (sanitised):
{
  "username" : "...",
  "roles" : [
    "department_abac_test",
    "superuser"
  ],
  "full_name" : "chris.s",
  "email" : "chris.s@...",
  "metadata" : {
    "oidc(iss)" : "...",
    "oidc(email)" : "chris.s@...",
    "oidc(auth_time)" : 1576504468,
    "oidc(email_verified)" : false,
    "oidc(sub)" : "...",
    "oidc(azp)" : "elastic",
    "oidc(department)" : "accounts",
    "oidc(name)" : "Chris S",
    "oidc(family_name)" : "S",
    "oidc(acr)" : "1",
    "oidc(id_token_hint)" : "...",
    "oidc(jti)" : "...",
    "oidc(given_name)" : "Chris",
    "oidc(session_state)" : "...",
    "oidc(s_hash)" : "...",
    "oidc(at_hash)" : ...,
    "oidc(typ)" : "ID",
    "oidc(preferred_username)" : "chris.s@...",
    "oidc(nonce)" : "..."
  },
  "enabled" : true,
  "authentication_realm" : {
    "name" : "oidc1",
    "type" : "oidc"
  },
  "lookup_realm" : {
    "name" : "oidc1",
    "type" : "oidc"
  }
}
  • Example (sanitised) showing the same when department is set to multi-value field:
  ...
  "department": [
    "accounts",
    "it"
  ],
  ...
  • With multi-value mapper setting enabled, the _authenticate response does not contain an entry for oidc(department) at all and I can't apply a role mapping to assign my test role based upon the user attribute

Yes, that Collections check is definitely a bug and it looks like it's the cause of the problem you're facing.

I've opened an issue for this.
I can't think of any sort of useful workaround for you though.

Thanks for confirming, will watch issue for updates

Only possible workaround I've been considering is to use a delimited single value field, e.g. accounts,it then regex for mappings on the ES side (but I've not tried this yet and it's not ideal)

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.