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 foroidc(department)
at all and I can't apply a role mapping to assign my test role based upon the user attribute