From d2f6e94cd5192cd1c605b9d3d06c3f88af50345c Mon Sep 17 00:00:00 2001 From: Thierry Boileau Date: Sun, 1 Nov 2026 13:05:33 +0100 Subject: [PATCH] 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 | 33 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/changes.md b/changes.md index a50022e46e..9241d1d4f9 100644 --- a/changes.md +++ b/changes.md @@ -18,6 +18,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.7.0 (30-09-2026) - Misc diff --git a/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java b/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java index 282b4fb575..68e1a91377 100644 --- a/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java +++ b/org.restlet/src/main/java/org/restlet/data/ChallengeScheme.java @@ -108,8 +108,8 @@ public final class ChallengeScheme { Map.entry(HTTP_DIGEST.getName().toLowerCase(), HTTP_DIGEST), Map.entry(HTTP_NTLM.getName().toLowerCase(), HTTP_NTLM), Map.entry(HTTP_OAUTH.getName().toLowerCase(), HTTP_OAUTH), - Map.entry(HTTP_OAUTH_BEARER.getName().toLowerCase(), HTTP_OAUTH), - Map.entry(HTTP_OAUTH_MAC.getName().toLowerCase(), HTTP_OAUTH)); + Map.entry(HTTP_OAUTH_BEARER.getName().toLowerCase(), HTTP_OAUTH_BEARER), + Map.entry(HTTP_OAUTH_MAC.getName().toLowerCase(), HTTP_OAUTH_MAC)); /** * Returns the challenge scheme associated with a scheme name. If an existing constant exists, diff --git a/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java b/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java index 67ca7dfdbb..87be3eb27f 100644 --- a/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java +++ b/org.restlet/src/test/java/org/restlet/data/ChallengeSchemeTestCase.java @@ -29,6 +29,39 @@ void valueOf_isCaseInsensitive() { assertSame(ChallengeScheme.HTTP_BASIC, ChallengeScheme.valueOf("http_basic")); } + /** Issue #1618: the Bearer and MAC schemes used to be mapped to HTTP_OAUTH. */ + @Test + void valueOf_oauthBearerAndMac_returnTheirOwnConstants() { + assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("HTTP_Bearer")); + assertSame(ChallengeScheme.HTTP_OAUTH_BEARER, ChallengeScheme.valueOf("http_bearer")); + assertSame(ChallengeScheme.HTTP_OAUTH_MAC, ChallengeScheme.valueOf("HTTP_MAC")); + 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 + void valueOf_everyConstant_isFoundByItsName() throws IllegalAccessException { + int checked = 0; + for (java.lang.reflect.Field field : ChallengeScheme.class.getFields()) { + if (field.getType() != ChallengeScheme.class + || !java.lang.reflect.Modifier.isStatic(field.getModifiers())) { + continue; + } + ChallengeScheme constant = (ChallengeScheme) field.get(null); + if (constant == ChallengeScheme.HTTP_AWS_IAM + || constant == ChallengeScheme.HTTP_AWS_QUERY) { + continue; + } + assertSame(constant, ChallengeScheme.valueOf(constant.getName()), field.getName()); + checked++; + } + assertEquals(12, checked); + } + @Test void valueOf_unknownName_createsNewInstance() { ChallengeScheme scheme = ChallengeScheme.valueOf("CUSTOM_SCHEME");