From db339704e5bb4662c0e25a3f3a2abe2d155189e1 Mon Sep 17 00:00:00 2001 From: lhazlewood <121180+lhazlewood@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:59:35 -0700 Subject: [PATCH] Custom empty claims Closes #858. Custom claims can now be empty again (which was the behavior for <= 0.11.5). --- .../java/io/jsonwebtoken/lang/Objects.java | 4 +- .../io/jsonwebtoken/impl/ParameterMap.java | 16 ++----- .../impl/DefaultJwtBuilderTest.groovy | 7 ---- .../jsonwebtoken/issues/Issue858Test.groovy | 42 +++++++++++++++++++ 4 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 impl/src/test/groovy/io/jsonwebtoken/issues/Issue858Test.groovy diff --git a/api/src/main/java/io/jsonwebtoken/lang/Objects.java b/api/src/main/java/io/jsonwebtoken/lang/Objects.java index 12a92dfd7..4284713ce 100644 --- a/api/src/main/java/io/jsonwebtoken/lang/Objects.java +++ b/api/src/main/java/io/jsonwebtoken/lang/Objects.java @@ -94,7 +94,7 @@ public static boolean isArray(Object obj) { * Returns {@code true} if the specified argument: *
    *
  1. is {@code null}, or
  2. - *
  3. is a String and {@link Strings#hasText(String)} is {@code false}, or
  4. + *
  5. is a CharSequence and {@link Strings#hasText(CharSequence)} is {@code false}, or
  6. *
  7. is a Collection or Map with zero size, or
  8. *
  9. is an empty array
  10. *
@@ -106,7 +106,7 @@ public static boolean isArray(Object obj) { */ public static boolean isEmpty(Object v) { return v == null || - (v instanceof String && !Strings.hasText((String) v)) || + (v instanceof CharSequence && !Strings.hasText((CharSequence) v)) || (v instanceof Collection && Collections.isEmpty((Collection) v)) || (v instanceof Map && Collections.isEmpty((Map) v)) || (v.getClass().isArray() && Array.getLength(v) == 0); diff --git a/impl/src/main/java/io/jsonwebtoken/impl/ParameterMap.java b/impl/src/main/java/io/jsonwebtoken/impl/ParameterMap.java index 2daf1b701..c8e462ec0 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/ParameterMap.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/ParameterMap.java @@ -124,13 +124,6 @@ public Object get(Object o) { return values.get(o); } - private static Object clean(Object o) { - if (o instanceof String) { - o = Strings.clean((String) o); - } - return o; - } - /** * Convenience method to put a value for an idiomatic param. * @@ -143,7 +136,7 @@ protected final Object put(Parameter param, Object value) { assertMutable(); Assert.notNull(param, "Parameter cannot be null."); Assert.hasText(param.getId(), "Parameter id cannot be null or empty."); - return apply(param, clean(value)); + return apply(param, value); } @Override @@ -156,12 +149,12 @@ public final Object put(String name, Object value) { return put(param, value); } else { // non-standard or custom property, just apply directly: - return nullSafePut(name, clean(value)); + return nullSafePut(name, value); } } private Object nullSafePut(String name, Object value) { - if (Objects.isEmpty(value)) { + if (value == null) { return remove(name); } else { this.idiomaticValues.put(name, value); @@ -199,9 +192,8 @@ private Object apply(Parameter param, Object rawValue) { String msg = sb.toString(); throw new IllegalArgumentException(msg, e); } - Object retval = nullSafePut(id, canonicalValue); this.idiomaticValues.put(id, idiomaticValue); - return retval; + return this.values.put(id, canonicalValue); } @Override diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy index bfeebeb15..3d0dfa949 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy @@ -219,13 +219,6 @@ class DefaultJwtBuilderTest { assertEquals b.claimsBuilder.foo, 'bar' } - @Test - void testClaimEmptyString() { - String value = ' ' - builder.claim('foo', value) - assertTrue builder.claimsBuilder.isEmpty() // shouldn't populate claims instance - } - @Test void testExistingClaimsAndSetClaim() { Claims c = Jwts.claims().add('foo', 'bar').build() diff --git a/impl/src/test/groovy/io/jsonwebtoken/issues/Issue858Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/issues/Issue858Test.groovy new file mode 100644 index 000000000..a470c10f0 --- /dev/null +++ b/impl/src/test/groovy/io/jsonwebtoken/issues/Issue858Test.groovy @@ -0,0 +1,42 @@ +/* + * Copyright © 2023 jsonwebtoken.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.jsonwebtoken.issues + +import io.jsonwebtoken.Jwts +import org.junit.Test + +import static org.junit.Assert.assertEquals + +class Issue858Test { + + @Test + void testEmptyAndNullEntries() { + def jwt = Jwts.builder() + .subject('Joe') + .claim('foo', '') // empty allowed + .claim('list', []) // empty allowed + .claim('map', [:]) // empty map allowed + .claim('another', null) // null not allowed (same behavior since <= 0.11.5), won't be added + .compact() + + def claims = Jwts.parser().unsecured().build().parseUnsecuredClaims(jwt).getPayload() + assertEquals 4, claims.size() + assertEquals 'Joe', claims.getSubject() + assertEquals '', claims.get('foo') + assertEquals([], claims.get('list')) + assertEquals([:], claims.get('map')) + } +}