From 8107982791245842994bb21cd7a1c091b4e0e2ef Mon Sep 17 00:00:00 2001 From: Thierry Boileau Date: Sun, 1 Nov 2026 13:05:34 +0100 Subject: [PATCH 1/2] ChallengeScheme.valueOf: Bearer and MAC no longer resolve to HTTP_OAuth (#1618) The lookup table mapped the names of HTTP_OAUTH_BEARER (HTTP_Bearer) and HTTP_OAUTH_MAC (HTTP_MAC) to HTTP_OAUTH, a copy-paste slip. valueOf now returns the matching constants. Added tests checking the two schemes and that every constant is found again by its name (HTTP_AWS_IAM and HTTP_AWS_QUERY deliberately resolve to HTTP_AWS_S3). Co-Authored-By: Claude Sonnet 5.5 --- changes.md | 1 + .../org/restlet/data/ChallengeScheme.java | 4 +- .../restlet/data/ChallengeSchemeTestCase.java | 58 +++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java diff --git a/changes.md b/changes.md index 5b71bb0072..17929d0c75 100644 --- a/changes.md +++ b/changes.md @@ -13,6 +13,7 @@ Changes log - CorsService and CorsFilter now add `Vary: Origin` to every response when the CORS answer depends on the request origin (origin allow-list or credentials allowed), including requests without an `Origin` header, so shared caches no longer serve the response of one origin to another. A static `*` without credentials still sends no `Vary`, as recommended by the Fetch standard. Issue #1611. - Fixed the parsing of a `WWW-Authenticate` challenge made of a token68 ending with `=` (such as a `Negotiate` token): the whole header was dropped. Issue #191. - The `realm` and `charset` parameters of an HTTP Basic challenge are now recognized whatever their case (`Realm=`, `Charset=`), as required by RFC 9110. Issue #1455. + - `ChallengeScheme.valueOf()` returned `HTTP_OAUTH` for the names of the Bearer and MAC schemes (`HTTP_Bearer`, `HTTP_MAC`) instead of `HTTP_OAUTH_BEARER` and `HTTP_OAUTH_MAC`. Issue #1618. - 2.6.1 (30-09-2026) - Bugs fixed diff --git a/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java b/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java index 49f636a926..71a2d3e044 100644 --- a/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java +++ b/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java @@ -107,8 +107,8 @@ public final class ChallengeScheme { schemes.put(HTTP_DIGEST.getName().toLowerCase(), HTTP_DIGEST); schemes.put(HTTP_NTLM.getName().toLowerCase(), HTTP_NTLM); schemes.put(HTTP_OAUTH.getName().toLowerCase(), HTTP_OAUTH); - schemes.put(HTTP_OAUTH_BEARER.getName().toLowerCase(), HTTP_OAUTH); - schemes.put(HTTP_OAUTH_MAC.getName().toLowerCase(), HTTP_OAUTH); + schemes.put(HTTP_OAUTH_BEARER.getName().toLowerCase(), HTTP_OAUTH_BEARER); + schemes.put(HTTP_OAUTH_MAC.getName().toLowerCase(), HTTP_OAUTH_MAC); ChallengeScheme.SCHEMES = Collections.unmodifiableMap(schemes); } diff --git a/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java b/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java new file mode 100644 index 0000000000..daa375fa46 --- /dev/null +++ b/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java @@ -0,0 +1,58 @@ +/** + * Copyright 2005-2024 Qlik + * + * The contents of this file is subject to the terms of the Apache 2.0 open + * source license available at http://www.opensource.org/licenses/apache-2.0 + * + * Restlet is a registered trademark of QlikTech International AB. + */ + +package org.restlet.data; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test {@link org.restlet.data.ChallengeScheme}. + */ +public class ChallengeSchemeTestCase { + + @Test + public void valueOf_isCaseInsensitive() { + Assertions.assertSame(ChallengeScheme.HTTP_BASIC, ChallengeScheme.valueOf("http_basic")); + } + + /** Issue #1618: the Bearer and MAC schemes used to be mapped to HTTP_OAUTH. */ + @Test + public void valueOf_oauthBearerAndMac_returnTheirOwnConstants() { + Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("HTTP_Bearer")); + Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("http_bearer")); + Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_MAC, ChallengeScheme.valueOf("HTTP_MAC")); + Assertions.assertSame(ChallengeScheme.HTTP_OAUTH, ChallengeScheme.valueOf("HTTP_OAuth")); + } + + /** + * Every constant must be found again by its name, so that a missing or + * mistaken entry in the lookup table is detected. HTTP_AWS_IAM and + * HTTP_AWS_QUERY are deliberately resolved to HTTP_AWS_S3. + */ + @Test + public void valueOf_everyConstant_isFoundByItsName() throws IllegalAccessException { + int checked = 0; + for (Field field : ChallengeScheme.class.getFields()) { + if (field.getType() != ChallengeScheme.class || !Modifier.isStatic(field.getModifiers())) { + continue; + } + ChallengeScheme constant = (ChallengeScheme) field.get(null); + if (constant == ChallengeScheme.HTTP_AWS_IAM || constant == ChallengeScheme.HTTP_AWS_QUERY) { + continue; + } + Assertions.assertSame(constant, ChallengeScheme.valueOf(constant.getName()), field.getName()); + checked++; + } + Assertions.assertEquals(12, checked); + } +} From e98c849fd07896d15eb48a8f8e024c975089df47 Mon Sep 17 00:00:00 2001 From: Thierry Boileau Date: Sun, 1 Nov 2026 13:12:54 +0100 Subject: [PATCH 2/2] Fix Sonar issues Co-Authored-By: Claude Sonnet 5.5 --- .../src/main/java/org/restlet/data/ChallengeScheme.java | 2 +- .../java/org/restlet/data/ChallengeSchemeTestCase.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java b/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java index 71a2d3e044..e980077b3a 100644 --- a/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java +++ b/org.restlet.java/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java @@ -169,7 +169,7 @@ public ChallengeScheme(final String name, final String technicalName, final Stri /** {@inheritDoc} */ @Override public boolean equals(final Object object) { - return (object instanceof ChallengeScheme) && ((ChallengeScheme) object).getName().equalsIgnoreCase(getName()); + return (object instanceof ChallengeScheme other) && other.getName().equalsIgnoreCase(getName()); } /** diff --git a/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java b/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java index daa375fa46..298a805cde 100644 --- a/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java +++ b/org.restlet.java/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java @@ -18,16 +18,16 @@ /** * Test {@link org.restlet.data.ChallengeScheme}. */ -public class ChallengeSchemeTestCase { +class ChallengeSchemeTestCase { @Test - public void valueOf_isCaseInsensitive() { + void valueOf_isCaseInsensitive() { Assertions.assertSame(ChallengeScheme.HTTP_BASIC, ChallengeScheme.valueOf("http_basic")); } /** Issue #1618: the Bearer and MAC schemes used to be mapped to HTTP_OAUTH. */ @Test - public void valueOf_oauthBearerAndMac_returnTheirOwnConstants() { + void valueOf_oauthBearerAndMac_returnTheirOwnConstants() { Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("HTTP_Bearer")); Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("http_bearer")); Assertions.assertSame(ChallengeScheme.HTTP_OAUTH_MAC, ChallengeScheme.valueOf("HTTP_MAC")); @@ -40,7 +40,7 @@ public void valueOf_oauthBearerAndMac_returnTheirOwnConstants() { * HTTP_AWS_QUERY are deliberately resolved to HTTP_AWS_S3. */ @Test - public void valueOf_everyConstant_isFoundByItsName() throws IllegalAccessException { + void valueOf_everyConstant_isFoundByItsName() throws IllegalAccessException { int checked = 0; for (Field field : ChallengeScheme.class.getFields()) { if (field.getType() != ChallengeScheme.class || !Modifier.isStatic(field.getModifiers())) {