elastic / elastic/elasticsearch
bug on OpenID connect: java.lang.ClassCastException when the users claims do contain JSON
- Dominant language
- Java
- Stars
- 77.9k
- Forks
- 26.1k
- PR merge metrics
- PR metrics pending
Description
**Elasticsearch version** (`bin/elasticsearch --version`): 7.6.1
**Plugins installed**: []
**JVM version** (`java -version`): 1.8.0_242
**OS version** (`uname -a` if on a Unix-like system): RHEL 7.7 (exact version 3.10.0-1062.12.1.el7.x86_64)
**Description of the problem including expected versus actual behavior**:
When using OpenID connect method, some claims can contain JSON objects in JSON lists. This is especially desirable in real world applications, when having rights to multiple ressources (eg, multiple elastic instances). While it [isn't strictly part of the OpenID standard](https://openid.net/specs/openid-connect-core-1_0.html#IndividualClaimsRequests), many companies are using this format to transmit users permissions.
For example, a claim can have the following format :
```"user_authorization":[{"resource":"myElasticInstance","permissions":[{"name":"SUPERUSER","constraints":[]}]}],```
ElasticSearch does not handle the JSON object ```{"ressource": ...}```, and thus throw an error.
**Current behavior:**
A java.lang.ClassCastException is trigered
**Expected behavior:**
The "permission" field is mapped to the roles of the user (via role mapping or automatically)
The logs (see below) should provide a relevant explanation of the issue
**Steps to reproduce**:
1. Install an OpenAM instance (or any OpenID server). Store the permissions in the JSON format.
2. Configure a basic OpenID authentication in elasticsearch.yml :
```
logger.org.elasticsearch.xpack.security.authc.oidc: "TRACE"
xpack.security.authc.realms.oidc.oidc1:
rp.client_id: "11111111-1111-1111-1111-111111111111"
rp.response_type: code
rp.requested_scopes: ["openid","profile","myElasticInstance.KibanaAccess"]
rp.redirect_uri: "https://kibanaURL/api/security/oidc/callback"
op.issuer: "https://opURL/oauth2"
op.authorization_endpoint: "https://opURL/oauth2/authorize"
ssl.certificate_authorities: ["sslkeys/ca-bundle.crt"]
op.token_endpoint: "https://opURL/oauth2/access_token"
op.jwkset_path: "https://opURL/oauth2/jwk_uri"
op.userinfo_endpoint: "https://opURL/oauth2/userinfo"
op.endsession_endpoint: "https://opURL/oauth2/logout"
rp.post_logout_redirect_uri: "https://kibanaURL/logged_out"
claims.principal: "sub"
claims.groups: "user_authorization"
claims.name: "name"
claims.mail: "mail"
```
3. Try to get authentiated on kibana.
4. View your logs and see a java.lang.ClassCastException
The problem seems to come [from this part of the code](https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectRealm.java#L460-L476). Not sure what's the best way to fix that through...
**Provide logs (if relevant)**:
```
2020-04-23T11:26:32,779][TRACE][o.e.x.s.a.o.OpenIdConnectAuthenticator] [elastic-node-0] Successfully retrieved user information: [
{
"sub":"myname@mycompany.com",
"mail":"myname@mycompany.com",
"auth_level":"L2",
"origin_network":"LAN",
"rc_local_sigle":"MyWonderful\/And\/Amazing\/Department",
"first_name":"MyFirstName",
"preferred_language":"EN",
"last_name":"myLastName",
"user_authorization":[{"resource":"myElasticInstance","permissions":[{"name":"SUPERUSER","constraints":[]}]}],
"name":"MyFirstName MyLastName",
"family_name":"MyLastName"
}
]
[2020-04-23T11:26:32,779][WARN][o.e.x.s.a.AuthenticationService] [elastic-node-0] An error occurred while attempting to authenticate [] against realm [oidc1]
java.lang.ClassCastException: class net.minidev.json.JSONObject cannot be cast to class java.lang.String (net.minidev.json.JSONObject is in unnamed module of loader java.net.FactoryURLClassLoader @7e4d2287; java.lang.String is in module java.base of loader 'bootstrap')
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176) ~[?:?]
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1621) ~[?:?]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[?:?]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[?:?]
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[?:?]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[?:?]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm$ClaimParser.lambda$forSetting$2(OpenIdConnectRealm.java:480) ~[?:?]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm$ClaimParser.getClaimValues(OpenIdConnectRealm.java:403) ~[?:?]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm.buildUserFromClaims(OpenIdConnectRealm.java:228) ~[?:?]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm.lambda$authenticate$0(OpenIdConnectRealm.java:168) ~[?:?]
at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:63) [elasticsearch-7.6.1.jar:7.6.1]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator.handleUserinfoResponse(OpenIdConnectAuthenticator.java:411) [x-pack-security-7.6.1.jar:7.6.1]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator.access$700(OpenIdConnectAuthenticator.java:122) [x-pack-security-7.6.1.jar:7.6.1]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator$1.completed(OpenIdConnectAuthenticator.java:364) [x-pack-security-7.6.1.jar:7.6.1]
at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator$1.completed(OpenIdConnectAuthenticator.java:361) [x-pack-security-7.6.1.jar:7.6.1]
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:122) [httpcore-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:181) [httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:448) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:338) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:265) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81) [httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39) [httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104) [httpcore-nio-4.4.12.jar:4.4.12]
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591) [httpcore-nio-4.4.12.jar:4.4.12]
at java.lang.Thread.run(Thread.java:830) [?:?]
```
Contributor guide
Assessment
This issue has not been assessed yet.