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..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 @@ -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); } @@ -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 new file mode 100644 index 0000000000..298a805cde --- /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}. + */ +class ChallengeSchemeTestCase { + + @Test + 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 + 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 + 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); + } +}