Skip to content

Commit f944078

Browse files
authored
Update oidc related dependencies (#71521)
Update: Non-issue, no notable changes. - json-smart from 2.3 to 2.4.2 - accessors-smart from 1.2 to 2.4.2 - asm from 7.1 to 8.0.1 - nimbus-jose-jwt from 8.6 to 9.8.1 - oauth2-oidc-sdk from 7.0.2 to 9.3.1
1 parent 8cb0985 commit f944078

13 files changed

+59
-56
lines changed

x-pack/plugin/security/build.gradle

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ dependencies {
5959
runtimeOnly 'com.google.guava:guava:19.0'
6060

6161
// Dependencies for oidc
62-
api "com.nimbusds:oauth2-oidc-sdk:7.0.2"
63-
api "com.nimbusds:nimbus-jose-jwt:8.6"
62+
api "com.nimbusds:oauth2-oidc-sdk:9.3.1"
63+
api "com.nimbusds:nimbus-jose-jwt:9.8.1"
6464
api "com.nimbusds:lang-tag:1.4.4"
6565
api "com.sun.mail:jakarta.mail:1.6.3"
6666
api "net.jcip:jcip-annotations:1.0"
67-
api "net.minidev:json-smart:2.3"
68-
api "net.minidev:accessors-smart:1.2"
69-
api "org.ow2.asm:asm:7.1"
67+
api "net.minidev:json-smart:2.4.2"
68+
api "net.minidev:accessors-smart:2.4.2"
69+
api "org.ow2.asm:asm:8.0.1"
7070

7171
testImplementation 'org.elasticsearch:securemock:1.2'
7272
testImplementation "org.elasticsearch:mocksocket:${versions.mocksocket}"
@@ -84,7 +84,7 @@ dependencies {
8484
testImplementation('org.apache.kerby:kerb-crypto:1.1.1')
8585
testImplementation('org.apache.kerby:kerb-util:1.1.1')
8686
testImplementation('org.apache.kerby:token-provider:1.1.1')
87-
testImplementation('com.nimbusds:nimbus-jose-jwt:8.6')
87+
testImplementation('com.nimbusds:nimbus-jose-jwt:9.8.1')
8888
testImplementation('net.jcip:jcip-annotations:1.0')
8989
testImplementation('org.apache.kerby:kerb-admin:1.1.1')
9090
testImplementation('org.apache.kerby:kerb-server:1.1.1')
@@ -264,13 +264,6 @@ tasks.named("thirdPartyAudit").configure {
264264
'net.sf.ehcache.Element',
265265
// [missing classes] SLF4j includes an optional class that depends on an extension class (!)
266266
'org.slf4j.ext.EventData',
267-
// Optional dependency of oauth2-oidc-sdk that we don't need since we do not support AES-SIV for JWE
268-
'org.cryptomator.siv.SivMode',
269-
// Optional dependency of nimbus-jose-jwt for handling Ed25519 signatures and ECDH with X25519 (RFC 8037)
270-
'com.google.crypto.tink.subtle.Ed25519Sign',
271-
'com.google.crypto.tink.subtle.Ed25519Sign$KeyPair',
272-
'com.google.crypto.tink.subtle.Ed25519Verify',
273-
'com.google.crypto.tink.subtle.X25519',
274267
// Bouncycastle is an optional dependency for apache directory, cryptacular and opensaml packages. We
275268
// acknowledge them here instead of adding bouncy castle as a compileOnly dependency
276269
'org.bouncycastle.asn1.ASN1Encodable',
@@ -420,11 +413,13 @@ tasks.named("thirdPartyAudit").configure {
420413
'org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util',
421414
'org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil',
422415
'org.bouncycastle.jce.provider.BouncyCastleProvider',
416+
'org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider',
423417
'org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec',
424418
'org.bouncycastle.math.ec.ECFieldElement',
425419
'org.bouncycastle.math.ec.ECPoint',
426420
'org.bouncycastle.openssl.jcajce.JcaPEMWriter',
427421
'org.bouncycastle.operator.jcajce.JcaContentSignerBuilder',
422+
'org.bouncycastle.operator.OperatorCreationException',
428423
'org.bouncycastle.util.Arrays',
429424
'org.bouncycastle.util.Strings',
430425
'org.bouncycastle.util.io.Streams',
@@ -454,7 +449,13 @@ tasks.named("thirdPartyAudit").configure {
454449
'javax.xml.bind.JAXBException',
455450
'javax.xml.bind.Unmarshaller',
456451
'javax.xml.bind.UnmarshallerHandler',
457-
// Optional dependencies of oauth2-oidc-sdk
452+
// Optional dependency of oauth2-oidc-sdk that we don't need since we do not support AES-SIV for JWE
453+
'org.cryptomator.siv.SivMode',
454+
// Optional dependency of nimbus-jose-jwt for handling Ed25519 signatures and ECDH with X25519 (RFC 8037)
455+
'com.google.crypto.tink.subtle.Ed25519Sign',
456+
'com.google.crypto.tink.subtle.Ed25519Sign$KeyPair',
457+
'com.google.crypto.tink.subtle.Ed25519Verify',
458+
'com.google.crypto.tink.subtle.X25519',
458459
'com.nimbusds.common.contenttype.ContentType',
459460
'javax.activation.ActivationDataFlavor',
460461
'javax.activation.DataContentHandler',

x-pack/plugin/security/licenses/accessors-smart-1.2.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4f09981a3c80f0766998c68d83bfd060812d5bcd

x-pack/plugin/security/licenses/asm-7.1.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3f5199523fb95304b44563f5d56d9f5a07270669

x-pack/plugin/security/licenses/json-smart-2.3.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
a7fcd0f985696c37cd3546f19c85c2ff367f2e85

x-pack/plugin/security/licenses/nimbus-jose-jwt-8.6.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2af7f734313320e4b156522d22ce32b775633909

x-pack/plugin/security/licenses/oauth2-oidc-sdk-7.0.2.jar.sha1

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
85891e8c391911ee1073f5e1737689cd804f1a9b

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticator.java

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import com.nimbusds.openid.connect.sdk.validators.AccessTokenValidator;
4242
import com.nimbusds.openid.connect.sdk.validators.IDTokenValidator;
4343
import net.minidev.json.JSONArray;
44-
import net.minidev.json.JSONObject;
4544
import org.apache.commons.codec.Charsets;
4645
import org.apache.http.Header;
4746
import org.apache.http.HttpEntity;
@@ -234,9 +233,9 @@ private void getUserClaims(@Nullable AccessToken accessToken, JWT idToken, Nonce
234233
LOGGER.trace("Received and validated the Id Token for the user: [{}]", verifiedIdTokenClaims);
235234
}
236235
// Add the Id Token string as a synthetic claim
237-
final JSONObject verifiedIdTokenClaimsObject = verifiedIdTokenClaims.toJSONObject();
236+
final Map<String, Object> verifiedIdTokenClaimsObject = verifiedIdTokenClaims.toJSONObject();
238237
final JWTClaimsSet idTokenClaim = new JWTClaimsSet.Builder().claim("id_token_hint", idToken.serialize()).build();
239-
verifiedIdTokenClaimsObject.merge(idTokenClaim.toJSONObject());
238+
mergeObjects(verifiedIdTokenClaimsObject, idTokenClaim.toJSONObject());
240239
final JWTClaimsSet enrichedVerifiedIdTokenClaims = JWTClaimsSet.parse(verifiedIdTokenClaimsObject);
241240
if (accessToken != null && opConfig.getUserinfoEndpoint() != null) {
242241
getAndCombineUserInfoClaims(accessToken, enrichedVerifiedIdTokenClaims, claimsListener);
@@ -413,9 +412,9 @@ private void handleUserinfoResponse(HttpResponse httpResponse, JWTClaimsSet veri
413412
final JWTClaimsSet userInfoClaims = JWTClaimsSet.parse(contentAsString);
414413
validateUserInfoResponse(userInfoClaims, verifiedIdTokenClaims.getSubject(), claimsListener);
415414
if (LOGGER.isTraceEnabled()) {
416-
LOGGER.trace("Successfully retrieved user information: [{}]", userInfoClaims.toJSONObject().toJSONString());
415+
LOGGER.trace("Successfully retrieved user information: [{}]", userInfoClaims);
417416
}
418-
final JSONObject combinedClaims = verifiedIdTokenClaims.toJSONObject();
417+
final Map<String, Object> combinedClaims = verifiedIdTokenClaims.toJSONObject();
419418
mergeObjects(combinedClaims, userInfoClaims.toJSONObject());
420419
claimsListener.onResponse(JWTClaimsSet.parse(combinedClaims));
421420
} else if (ContentType.parse(contentHeader.getValue()).getMimeType().equals("application/jwt")) {
@@ -664,22 +663,21 @@ private void setMetadataFileWatcher(String jwkSetPath) throws IOException {
664663
}
665664

666665
/**
667-
* Merges the JsonObject with the claims of the ID Token with the JsonObject with the claims of the UserInfo response. This is
668-
* necessary as some OPs return slightly different values for some claims (i.e. Google for the profile picture) and
669-
* {@link JSONObject#merge(Object)} would throw a runtime exception. The merging is performed based on the following rules:
666+
* Merges the Map with the claims of the ID Token with the Map with the claims of the UserInfo response.
667+
* The merging is performed based on the following rules:
670668
* <ul>
671669
* <li>If the values for a given claim are primitives (of the same type), the value from the ID Token is retained</li>
672670
* <li>If the values for a given claim are Objects, the values are merged</li>
673671
* <li>If the values for a given claim are Arrays, the values are merged without removing duplicates</li>
674672
* <li>If the values for a given claim are of different types, an exception is thrown</li>
675673
* </ul>
676674
*
677-
* @param userInfo The JsonObject with the ID Token claims
678-
* @param idToken The JsonObject with the UserInfo Response claims
679-
* @return the merged JsonObject
675+
* @param userInfo The Map with the ID Token claims
676+
* @param idToken The Map with the UserInfo Response claims
677+
* @return the merged Map
680678
*/
681679
// pkg protected for testing
682-
static JSONObject mergeObjects(JSONObject idToken, JSONObject userInfo) {
680+
static Map<String, Object> mergeObjects(Map<String, Object> idToken, Map<String, Object> userInfo) {
683681
for (Map.Entry<String, Object> entry : idToken.entrySet()) {
684682
Object value1 = entry.getValue();
685683
Object value2 = userInfo.get(entry.getKey());
@@ -688,8 +686,8 @@ static JSONObject mergeObjects(JSONObject idToken, JSONObject userInfo) {
688686
}
689687
if (value1 instanceof JSONArray) {
690688
idToken.put(entry.getKey(), mergeArrays((JSONArray) value1, value2));
691-
} else if (value1 instanceof JSONObject) {
692-
idToken.put(entry.getKey(), mergeObjects((JSONObject) value1, value2));
689+
} else if (value1 instanceof Map) {
690+
idToken.put(entry.getKey(), mergeObjects((Map<String, Object>) value1, value2));
693691
} else if (value1.getClass().equals(value2.getClass()) == false) {
694692
// A special handling for certain OPs that mix the usage of true and "true"
695693
if (value1 instanceof Boolean && value2 instanceof String && String.valueOf(value1).equals(value2)) {
@@ -710,15 +708,15 @@ static JSONObject mergeObjects(JSONObject idToken, JSONObject userInfo) {
710708
return idToken;
711709
}
712710

713-
private static JSONObject mergeObjects(JSONObject jsonObject1, Object jsonObject2) {
711+
private static Map<String, Object> mergeObjects(Map<String, Object> jsonObject1, Object jsonObject2) {
714712
if (jsonObject2 == null) {
715713
return jsonObject1;
716714
}
717-
if (jsonObject2 instanceof JSONObject) {
718-
return mergeObjects(jsonObject1, (JSONObject) jsonObject2);
715+
if (jsonObject2 instanceof Map) {
716+
return mergeObjects(jsonObject1, (Map<String, Object>) jsonObject2);
719717
}
720718
throw new IllegalStateException("Error while merging ID token and userinfo claims. " +
721-
"Cannot merge JSONObject with [" + jsonObject2.getClass().getName() + "]");
719+
"Cannot merge a Map with a [" + jsonObject2.getClass().getName() + "]");
722720
}
723721

724722
private static JSONArray mergeArrays(JSONArray jsonArray1, Object jsonArray2) {

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticatorTests.java

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import com.nimbusds.openid.connect.sdk.validators.IDTokenValidator;
4242
import com.nimbusds.openid.connect.sdk.validators.InvalidHashException;
4343
import net.minidev.json.JSONArray;
44-
import net.minidev.json.JSONObject;
4544
import org.elasticsearch.ElasticsearchSecurityException;
4645
import org.elasticsearch.action.ActionListener;
4746
import org.elasticsearch.action.support.PlainActionFuture;
@@ -74,6 +73,7 @@
7473
import java.util.Base64;
7574
import java.util.Collections;
7675
import java.util.Date;
76+
import java.util.Map;
7777
import java.util.UUID;
7878

7979
import static java.time.Instant.now;
@@ -698,14 +698,14 @@ public void testJsonObjectMerging() throws Exception {
698698
final JWK jwk = keyMaterial.v2().getKeys().get(0);
699699
RelyingPartyConfiguration rpConfig = getRpConfig(jwk.getAlgorithm().getName());
700700
OpenIdConnectProviderConfiguration opConfig = getOpConfig();
701-
JSONObject address = new JWTClaimsSet.Builder()
701+
Map<String, Object> address = new JWTClaimsSet.Builder()
702702
.claim("street_name", "12, Test St.")
703703
.claim("locality", "New York")
704704
.claim("region", "NY")
705705
.claim("country", "USA")
706706
.build()
707707
.toJSONObject();
708-
JSONObject idTokenObject = new JWTClaimsSet.Builder()
708+
Map<String, Object> idTokenObject = new JWTClaimsSet.Builder()
709709
.jwtID(randomAlphaOfLength(8))
710710
.audience(rpConfig.getClientId().getValue())
711711
.expirationTime(Date.from(now().plusSeconds(3600)))
@@ -724,7 +724,7 @@ public void testJsonObjectMerging() throws Exception {
724724
.build()
725725
.toJSONObject();
726726

727-
JSONObject userinfoObject = new JWTClaimsSet.Builder()
727+
Map<String, Object> userinfoObject = new JWTClaimsSet.Builder()
728728
.claim("given_name", "Jane Doe")
729729
.claim("family_name", "Doe")
730730
.claim("profile", "https://test-profiles.com/jane.doe")
@@ -752,7 +752,7 @@ public void testJsonObjectMerging() throws Exception {
752752
assertTrue(idTokenObject.containsKey("email"));
753753

754754
// Claims with different types throw an error
755-
JSONObject wrongTypeInfo = new JWTClaimsSet.Builder()
755+
Map<String, Object> wrongTypeInfo = new JWTClaimsSet.Builder()
756756
.claim("given_name", "Jane Doe")
757757
.claim("family_name", 123334434)
758758
.claim("profile", "https://test-profiles.com/jane.doe")
@@ -767,7 +767,7 @@ public void testJsonObjectMerging() throws Exception {
767767
});
768768

769769
// Userinfo Claims overwrite ID Token claims
770-
JSONObject overwriteUserInfo = new JWTClaimsSet.Builder()
770+
Map<String, Object> overwriteUserInfo = new JWTClaimsSet.Builder()
771771
.claim("given_name", "Jane Doe")
772772
.claim("family_name", "Doe")
773773
.claim("profile", "https://test-profiles.com/jane.doe2")
@@ -778,11 +778,11 @@ public void testJsonObjectMerging() throws Exception {
778778
.toJSONObject();
779779

780780
OpenIdConnectAuthenticator.mergeObjects(idTokenObject, overwriteUserInfo);
781-
assertThat(idTokenObject.getAsString("email"), equalTo("[email protected]"));
782-
assertThat(idTokenObject.getAsString("profile"), equalTo("https://test-profiles.com/jane.doe"));
781+
assertThat(idTokenObject.get("email"), equalTo("[email protected]"));
782+
assertThat(idTokenObject.get("profile"), equalTo("https://test-profiles.com/jane.doe"));
783783

784784
// Merging Arrays
785-
JSONObject userInfoWithRoles = new JWTClaimsSet.Builder()
785+
Map<String, Object> userInfoWithRoles = new JWTClaimsSet.Builder()
786786
.claim("given_name", "Jane Doe")
787787
.claim("family_name", "Doe")
788788
.claim("profile", "https://test-profiles.com/jane.doe")
@@ -797,13 +797,13 @@ public void testJsonObjectMerging() throws Exception {
797797
assertThat((JSONArray) idTokenObject.get("roles"), containsInAnyOrder("role1", "role2", "role3", "role4", "role5"));
798798

799799
// Merging nested objects
800-
JSONObject addressUserInfo = new JWTClaimsSet.Builder()
800+
Map<String, Object> addressUserInfo = new JWTClaimsSet.Builder()
801801
.claim("street_name", "12, Test St.")
802802
.claim("locality", "New York")
803803
.claim("postal_code", "10024")
804804
.build()
805805
.toJSONObject();
806-
JSONObject userInfoWithAddress = new JWTClaimsSet.Builder()
806+
Map<String, Object> userInfoWithAddress = new JWTClaimsSet.Builder()
807807
.claim("given_name", "Jane Doe")
808808
.claim("family_name", "Doe")
809809
.claim("profile", "https://test-profiles.com/jane.doe")
@@ -816,7 +816,7 @@ public void testJsonObjectMerging() throws Exception {
816816
.toJSONObject();
817817
OpenIdConnectAuthenticator.mergeObjects(idTokenObject, userInfoWithAddress);
818818
assertTrue(idTokenObject.containsKey("address"));
819-
JSONObject combinedAddress = (JSONObject) idTokenObject.get("address");
819+
Map<String, Object> combinedAddress = (Map<String, Object>) idTokenObject.get("address");
820820
assertTrue(combinedAddress.containsKey("street_name"));
821821
assertTrue(combinedAddress.containsKey("locality"));
822822
assertTrue(combinedAddress.containsKey("street_name"));
@@ -826,14 +826,14 @@ public void testJsonObjectMerging() throws Exception {
826826
}
827827

828828
public void testJsonObjectMergingWithBooleanLeniency() {
829-
final JSONObject idTokenObject = new JWTClaimsSet.Builder()
829+
final Map<String, Object> idTokenObject = new JWTClaimsSet.Builder()
830830
.claim("email_verified", true)
831831
.claim("email_verified_1", "true")
832832
.claim("email_verified_2", false)
833833
.claim("email_verified_3", "false")
834834
.build()
835835
.toJSONObject();
836-
final JSONObject userInfoObject = new JWTClaimsSet.Builder()
836+
final Map<String, Object> userInfoObject = new JWTClaimsSet.Builder()
837837
.claim("email_verified", "true")
838838
.claim("email_verified_1", true)
839839
.claim("email_verified_2", "false")
@@ -846,23 +846,23 @@ public void testJsonObjectMergingWithBooleanLeniency() {
846846
assertSame(Boolean.FALSE, idTokenObject.get("email_verified_2"));
847847
assertSame(Boolean.FALSE, idTokenObject.get("email_verified_3"));
848848

849-
final JSONObject idTokenObject1 = new JWTClaimsSet.Builder()
849+
final Map<String, Object> idTokenObject1 = new JWTClaimsSet.Builder()
850850
.claim("email_verified", true)
851851
.build()
852852
.toJSONObject();
853-
final JSONObject userInfoObject1 = new JWTClaimsSet.Builder()
853+
final Map<String, Object> userInfoObject1 = new JWTClaimsSet.Builder()
854854
.claim("email_verified", "false")
855855
.build()
856856
.toJSONObject();
857857
IllegalStateException e =
858858
expectThrows(IllegalStateException.class, () -> OpenIdConnectAuthenticator.mergeObjects(idTokenObject1, userInfoObject1));
859859
assertThat(e.getMessage(), containsString("Cannot merge [java.lang.Boolean] with [java.lang.String]"));
860860

861-
final JSONObject idTokenObject2 = new JWTClaimsSet.Builder()
861+
final Map<String, Object> idTokenObject2 = new JWTClaimsSet.Builder()
862862
.claim("email_verified", true)
863863
.build()
864864
.toJSONObject();
865-
final JSONObject userInfoObject2 = new JWTClaimsSet.Builder()
865+
final Map<String, Object> userInfoObject2 = new JWTClaimsSet.Builder()
866866
.claim("email_verified", "yes")
867867
.build()
868868
.toJSONObject();
@@ -951,7 +951,11 @@ private Tuple<AccessToken, JWT> buildTokens(JWTClaimsSet idToken, Key key, Strin
951951
if (withAccessToken) {
952952
accessToken = new BearerAccessToken(Base64.getUrlEncoder().encodeToString(randomByteArrayOfLength(32)));
953953
AccessTokenHash expectedHash = AccessTokenHash.compute(accessToken, JWSAlgorithm.parse(alg));
954-
idToken = JWTClaimsSet.parse(idToken.toJSONObject().appendField("at_hash", expectedHash.getValue()));
954+
Map<String, Object> idTokenMap = idToken.toJSONObject();
955+
idTokenMap.put("at_hash", expectedHash.getValue());
956+
// This is necessary as if nonce claim is of type Nonce, the library won't take it into consideration when serializing the JWT
957+
idTokenMap.put("nonce", idTokenMap.get("nonce").toString());
958+
idToken = JWTClaimsSet.parse(idTokenMap);
955959
}
956960
SignedJWT jwt = new SignedJWT(
957961
new JWSHeader.Builder(JWSAlgorithm.parse(alg)).keyID(keyId).build(),

0 commit comments

Comments
 (0)