You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2026/06/10 08:43:21 UTC
(jena) 02/02: GH-3977: Support SHA-256 for digest authentication
This is an automated email from the ASF dual-hosted git repository.
afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
commit 1034f3ee9b9f147d7bc0d481892ee546acf08a48
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Mon Jun 8 20:38:26 2026 +0100
GH-3977: Support SHA-256 for digest authentication
---
.../main/java/org/apache/jena/http/HttpLib.java | 6 +-
.../org/apache/jena/http/auth/AuthChallenge.java | 6 +-
.../java/org/apache/jena/http/auth/AuthHttp.java | 51 ++++---
.../java/org/apache/jena/http/auth/AuthLib.java | 12 +-
.../org/apache/jena/http/auth/DigestAlgorithm.java | 57 ++++++++
.../java/org/apache/jena/http/auth/DigestLib.java | 29 +++-
.../org/apache/jena/http/auth/TestAuthDigest.java | 159 ++++++++++++++++++++-
.../jena/http/auth/TestAuthHeaderParser.java | 5 -
.../jena/fuseki/main/auth/AuthBearerFilter.java | 4 +
9 files changed, 287 insertions(+), 42 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/http/HttpLib.java b/jena-arq/src/main/java/org/apache/jena/http/HttpLib.java
index 422978e154..58cd087d5f 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/HttpLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/HttpLib.java
@@ -445,7 +445,11 @@ public class HttpLib {
String path = uri.getRawPath();
if ( path == null || path.isEmpty() )
path = "/";
- return path;
+ String target = path;
+ String qs = uri.getRawQuery();
+ if ( qs != null )
+ target = target+"?"+qs;
+ return target;
}
/** Return a HttpRequest */
diff --git a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthChallenge.java b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthChallenge.java
index 41e2fb9072..2a3e37a10c 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthChallenge.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthChallenge.java
@@ -38,6 +38,8 @@ public class AuthChallenge {
public final String nonce;
public final String opaque;
public final String qop;
+ public final String algorithm;
+
// May be null;
public final Map<String, String> authParams;
@@ -80,13 +82,14 @@ public class AuthChallenge {
get(auth, AuthHttp.strNonce), // Required for digest, not for basic.
get(auth, AuthHttp.strOpaque),
get(auth, AuthHttp.strQop),
+ get(auth, AuthHttp.strAlgorithm),
auth.getAuthParams());
} catch (NullPointerException ex) {
return null;
}
}
- private AuthChallenge(AuthScheme authScheme, AuthHeader authHeader, String realm, String nonce, String opaque, String qop, Map<String, String> authParams) {
+ private AuthChallenge(AuthScheme authScheme, AuthHeader authHeader, String realm, String nonce, String opaque, String qop, String algorithm, Map<String, String> authParams) {
Objects.requireNonNull(authScheme);
Objects.requireNonNull(authHeader);
this.authScheme = authScheme;
@@ -95,6 +98,7 @@ public class AuthChallenge {
this.nonce = nonce;
this.opaque = opaque;
this.qop = qop;
+ this.algorithm = algorithm;
this.authParams = authParams;
}
diff --git a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthHttp.java b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthHttp.java
index d2bc4dbbb9..54fee56752 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthHttp.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthHttp.java
@@ -23,33 +23,40 @@ package org.apache.jena.http.auth;
import java.util.Objects ;
-import org.apache.commons.codec.digest.DigestUtils ;
-
-/** Constants and operations from RFC 2617 (digest, now RFC 7616; basic, now RFC 7617), using MD5 (the default) */
+/**
+ * Constants and operations from RFC 2617 (digest, now RFC 7616; basic, now RFC 7617)
+ * Original digest authentication: RFC 2069
+ */
class AuthHttp {
- public static String strUsername = "username";
- public static String strRealm = "realm";
- public static String strNonce = "nonce";
- public static String strNc = "nc";
- public static String strCNonce = "cnonce";
- public static String strQop = "qop";
- public static String strResponse = "response";
- public static String strOpaque = "opaque";
- public static String strUri = "uri";
+ // Field names
+ public static final String strUsername = "username";
+ public static final String strRealm = "realm";
+ public static final String strNonce = "nonce";
+ public static final String strNc = "nc";
+ public static final String strCNonce = "cnonce";
+ public static final String strQop = "qop";
+ public static final String strResponse = "response";
+ public static final String strOpaque = "opaque";
+ public static final String strUri = "uri";
+ public static final String strAlgorithm = "algorithm";
- public static String KD(String data) {
- return H(data) ;
- }
+ // Algorithm names.
+ public static final String algortihmSHA256 = "SHA-256";
+ public static final String algortihmSHA256_sess = "SHA-256-sess";
+ public static final String algortihmSHA512_256 = "SHA-512-256";
+ public static final String algortihmSHA512_256_sess = "SHA-512-256-sess";
+ public static final String algortihmMD5 = "MD5";
+ public static final String algortihmMD5_sess = "MD5-sess";
- public static String KD(String secret, String data) {
- return H(secret+":"+data) ;
+ public static String KD(String secret, String data, DigestAlgorithm digestAlgorithm) {
+ return H(secret+":"+data, digestAlgorithm) ;
}
- public static String H(String string) {
- return DigestUtils.md5Hex(string) ;
+ public static String H(String string, DigestAlgorithm algorithm) {
+ return algorithm.digest.apply(string);
}
- public static String A1_MD5(String username, String realm, String password) {
+ public static String A1(String username, String realm, String password, DigestAlgorithm digestAlgorithm) {
Objects.requireNonNull(username) ;
Objects.requireNonNull(realm) ;
Objects.requireNonNull(password) ;
@@ -57,14 +64,14 @@ class AuthHttp {
return s ;
}
- public static String A1_MD5_sess(String username, String realm, String password, String nonce, String cnonce) {
+ public static String A1_sess(String username, String realm, String password, String nonce, String cnonce, DigestAlgorithm digestAlgorithm) {
Objects.requireNonNull(username) ;
Objects.requireNonNull(realm) ;
Objects.requireNonNull(password) ;
Objects.requireNonNull(nonce) ;
Objects.requireNonNull(cnonce) ;
String s = username+":"+realm+":"+password ;
- String x = H(s)+":"+nonce+":"+cnonce ;
+ String x = H(s, digestAlgorithm)+":"+nonce+":"+cnonce ;
return s ;
}
diff --git a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthLib.java b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthLib.java
index 14a2ac0b75..16a1b28cc9 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/auth/AuthLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/auth/AuthLib.java
@@ -83,9 +83,9 @@ public class AuthLib {
/* Handle a 401 (authentication challenge). */
private static <T> CompletableFuture<HttpResponse<T>> handle401Async(HttpClient httpClient,
- HttpRequest request,
- BodyHandler<T> bodyHandler,
- HttpResponse<T> httpResponse401) {
+ HttpRequest request,
+ BodyHandler<T> bodyHandler,
+ HttpResponse<T> httpResponse401) {
AuthChallenge aHeader = wwwAuthenticateHeader(httpResponse401);
if ( aHeader == null )
// No valid header - simply return the original response.
@@ -103,7 +103,6 @@ public class AuthLib {
throw HttpException.create(httpResponse401);
}
- // Request target - no query string.
AuthRequestModifier authRequestModifier;
switch (aHeader.authScheme) {
case BASIC :
@@ -113,6 +112,8 @@ public class AuthLib {
String requestTarget = HttpLib.requestTargetServer(request.uri());
authRequestModifier = digestAuthModifier(aHeader, passwordRecord.getUsername(), passwordRecord.getPassword(),
request.method(), requestTarget);
+ if ( authRequestModifier == null )
+ throw HttpException.error("Unrecognized digest algorithm");
break;
}
case BEARER : {
@@ -154,7 +155,6 @@ public class AuthLib {
return null;
// Choose first digest or bearer, else the first basic. Prefer digest or bearer to basic.
AuthChallenge aHeader = null;
- String result = null;
for ( String headerValue : headers ) {
AuthChallenge aHeader2 = AuthChallenge.parse(headerValue);
if ( aHeader2 == null ) {
@@ -163,7 +163,7 @@ public class AuthLib {
}
AuthScheme authScheme = aHeader2.authScheme;
switch(authScheme) {
- case DIGEST :
+ case DIGEST :
return aHeader2;
case BASIC:
if ( aHeader == null )
diff --git a/jena-arq/src/main/java/org/apache/jena/http/auth/DigestAlgorithm.java b/jena-arq/src/main/java/org/apache/jena/http/auth/DigestAlgorithm.java
new file mode 100644
index 0000000000..c320d9be17
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/http/auth/DigestAlgorithm.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.http.auth;
+
+import static org.apache.jena.http.auth.AuthHttp.*;
+import java.util.function.Function;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+/** Algorithms for digest authentication. */
+public enum DigestAlgorithm {
+ SHA_256(algortihmSHA256, DigestUtils::sha256Hex),
+ SHA_256_sess(algortihmSHA256_sess, DigestUtils::sha256Hex),
+ SHA_512_256(algortihmSHA512_256, DigestUtils::sha512_256Hex),
+ SHA_512_256_sess(algortihmSHA512_256_sess, DigestUtils::sha512_256Hex),
+ MD5(algortihmMD5, DigestUtils::md5Hex),
+ MD5_sess(algortihmMD5, DigestUtils::md5Hex)
+ ;
+ public final String algorithmName;
+ public final Function<String, String> digest;
+
+ private DigestAlgorithm(String algorithmName, Function<String, String> digest) {
+ this.algorithmName = algorithmName ;
+ this.digest = digest;
+ }
+
+ /** Algothm name to enum, or null (unecognized) */
+ public static DigestAlgorithm fromString(String name) {
+ return switch(name) {
+ case algortihmSHA256 -> SHA_256;
+ case algortihmSHA256_sess -> SHA_256_sess;
+ case algortihmSHA512_256 -> SHA_512_256;
+ case algortihmSHA512_256_sess -> SHA_512_256_sess;
+ case algortihmMD5 -> MD5;
+ case algortihmMD5_sess -> MD5_sess;
+ default -> null;
+ };
+ }
+}
diff --git a/jena-arq/src/main/java/org/apache/jena/http/auth/DigestLib.java b/jena-arq/src/main/java/org/apache/jena/http/auth/DigestLib.java
index 654ce8e6ea..50243a77fa 100644
--- a/jena-arq/src/main/java/org/apache/jena/http/auth/DigestLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/http/auth/DigestLib.java
@@ -21,7 +21,7 @@
package org.apache.jena.http.auth;
-import static org.apache.jena.http.auth.AuthHttp.A1_MD5;
+import static org.apache.jena.http.auth.AuthHttp.A1;
import static org.apache.jena.http.auth.AuthHttp.A2_auth;
import static org.apache.jena.http.auth.AuthHttp.H;
import static org.apache.jena.http.auth.AuthHttp.KD;
@@ -47,21 +47,34 @@ class DigestLib {
String username, String password,
String method, String requestTarget,
String cnonce, String nc, String authType) {
- String a1 = A1_MD5(username, auth.realm, password) ;
+ DigestAlgorithm dAlgo = getAlgorithm(auth);
+ if ( dAlgo == null )
+ // Unrecognized algorithm name.
+ return null;
+ String a1 = A1(username, auth.realm, password, dAlgo) ;
if ( auth.qop == null ) {
// RFC 2069
// Firefox seems to prefer this form??
- return KD(H(a1), auth.nonce+":"+H(A2_auth(method, requestTarget))) ;
+ return KD(H(a1, dAlgo), auth.nonce+":"+H(A2_auth(method, requestTarget), dAlgo), dAlgo) ;
}
else {
Objects.nonNull(cnonce) ;
Objects.nonNull(nc) ;
- return KD(H(a1),
- auth.nonce+":"+nc+":"+cnonce+":"+authType+":"+H(A2_auth(method, requestTarget))
+ return KD(H(a1, dAlgo),
+ auth.nonce+":"+nc+":"+cnonce+":"+authType+":"+H(A2_auth(method, requestTarget), dAlgo),
+ dAlgo
) ;
}
}
+ public static DigestAlgorithm getAlgorithm(AuthChallenge challenge) {
+ if ( challenge.algorithm == null )
+ // Default by RFC 7616
+ return DigestAlgorithm.MD5;
+ // null means ignore.
+ return DigestAlgorithm.fromString(challenge.algorithm);
+ }
+
private static Random nonceGenerator = new SecureRandom();
/**
@@ -105,10 +118,16 @@ class DigestLib {
String responseField = calcDigestChallengeResponse(aHeader, user, password,
method, requestTarget,
clientNonce, nc, "auth");
+ if ( responseField == null ) {
+ return null;
+ // Unrecognized algorithm. RFC says "ignore request"
+ }
+
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Digest ");
field(stringBuilder, true, "username", user, true);
field(stringBuilder, false, "realm", aHeader.realm, true);
+ field(stringBuilder, false, "algorithm", aHeader.algorithm, false);
field(stringBuilder, false, "nonce", aHeader.nonce, true);
field(stringBuilder, false, "uri", requestTarget, true);
field(stringBuilder, false, "qop", "auth", false);
diff --git a/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthDigest.java b/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthDigest.java
index 9ca17e770b..eb02b7bebd 100644
--- a/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthDigest.java
+++ b/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthDigest.java
@@ -22,13 +22,21 @@
package org.apache.jena.http.auth;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
public class TestAuthDigest {
- // Example from RFC 2617
+ // Examples from RFC 2617
+
+ // digest 1
+ // No algorithm - use MD5
+ // MD5: 6629fae49393a05397450978507c4ef1
+ // SHA-256: 5abdd07184ba512a22c53f41470e5eea7dcaa3a93a59b630c13dfe0a5dc6e38b
+ // SHA-512-256: f23c08ec7334a881f8286e68450ddbd9f0cd91c41481f0e1433604da8113c6dc
+
@Test
- public void digest_1() {
+ public void digest_1_no_algorithm() {
String header = "Digest realm=\"testrealm@host.com\", qop=\"auth,auth-int\","+
" nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","+
" opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
@@ -49,7 +57,84 @@ public class TestAuthDigest {
assertEquals("6629fae49393a05397450978507c4ef1", responseField);
}
+
+ @Test
+ public void digest_1_md5() {
+ String header = "Digest realm=\"testrealm@host.com\", qop=\"auth,auth-int\","+
+ " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","+
+ " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"" +
+ " algorithm=MD5";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "0a4f113b";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle Of Life";
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertEquals("6629fae49393a05397450978507c4ef1", responseField);
+ }
+
+ @Test
+ public void digest_1_sha256() {
+ String header = "Digest realm=\"testrealm@host.com\", qop=\"auth,auth-int\","+
+ " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","+
+ " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""+
+ " algorithm=SHA-256";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "0a4f113b";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle Of Life";
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertEquals("5abdd07184ba512a22c53f41470e5eea7dcaa3a93a59b630c13dfe0a5dc6e38b", responseField);
+ }
+
+ @Test
+ public void digest_1_sha512_256() {
+ String header = "Digest realm=\"testrealm@host.com\", qop=\"auth,auth-int\","+
+ " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","+
+ " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""+
+ " algorithm=SHA-512-256";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "0a4f113b";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle Of Life";
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertEquals("f23c08ec7334a881f8286e68450ddbd9f0cd91c41481f0e1433604da8113c6dc", responseField);
+ }
+
+
// Example from RFC 7616
+
+ // digest 2
+ // MD5: 8ca523f5e9506fed4657c9700eebdbec
+ // SHA-256 753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1
+ // SHA-512-256: 430d05014cecc49cab6fbe03176d41a1da86cbfe24a16580e22aaad928d960d0
+
@Test
public void digest_2() {
String header = "Digest realm=\"http-auth@example.org\", qop=\"auth,auth-int\"," +
@@ -70,4 +155,74 @@ public class TestAuthDigest {
assertEquals("8ca523f5e9506fed4657c9700eebdbec", responseField);
}
+
+ // Example from RFC 7616
+ @Test
+ public void digest_2_sha256() {
+ String header = "Digest realm=\"http-auth@example.org\", qop=\"auth,auth-int\"," +
+ " nonce=\"7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v\","+
+ " opaque=\"FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS\""+
+ " algorithm=SHA-256";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle of Life"; // NB Different to RFC 2617
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertEquals("753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1", responseField);
+ }
+
+ // Example from RFC 7616
+ @Test
+ public void digest_2_sha512_256() {
+ String header = "Digest realm=\"http-auth@example.org\", qop=\"auth,auth-int\"," +
+ " nonce=\"7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v\","+
+ " opaque=\"FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS\""+
+ " algorithm=SHA-512-256";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle of Life"; // NB Different to RFC 2617
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertEquals("430d05014cecc49cab6fbe03176d41a1da86cbfe24a16580e22aaad928d960d0", responseField);
+ }
+
+ // Bad algorithm
+ @Test
+ public void digest_3_unknown() {
+ String header = "Digest realm=\"testrealm@host.com\", qop=\"auth,auth-int\","+
+ " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","+
+ " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""+
+ " algorithm=UNKNOWN";
+ AuthChallenge aHeader = AuthChallenge.parse(header);
+
+ String requestTarget = "/dir/index.html";
+ String method = "GET";
+ String cnonce = "0a4f113b";
+ String nc = "00000001";
+ String username = "Mufasa";
+ String password = "Circle Of Life";
+
+ String responseField =
+ DigestLib.calcDigestChallengeResponse(aHeader, username, password,
+ method, requestTarget,
+ cnonce, nc, "auth");
+
+ assertNull(responseField);
+ }
}
diff --git a/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthHeaderParser.java b/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthHeaderParser.java
index 5978d48765..0d157992fd 100644
--- a/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthHeaderParser.java
+++ b/jena-arq/src/test/java/org/apache/jena/http/auth/TestAuthHeaderParser.java
@@ -41,7 +41,6 @@ public class TestAuthHeaderParser {
return AuthHeader.parseChallenge(input);
}
-
@Test public void parse_empty() {
AuthHeader auth = parseAuth("");
assertNull(auth.getAuthScheme());
@@ -162,7 +161,6 @@ public class TestAuthHeaderParser {
assertNull(map);
}
-
@Test public void parse_bearer_bad_01() {
AuthHeader auth = parseAuth("Bearer ");
assertTrue(auth.isBearerAuth());
@@ -191,8 +189,6 @@ public class TestAuthHeaderParser {
assertEquals("a=b", auth.getUnknown());
}
-
-
@Test public void parse_challenge_01() {
AuthHeader auth = parseChallenge("Bearer realm=\"somewhere\"");
assertEquals(AuthScheme.BEARER, auth.getAuthScheme());
@@ -236,5 +232,4 @@ public class TestAuthHeaderParser {
assertNotNull(map);
assertEquals("hades", map.get("realm"));
}
-
}
\ No newline at end of file
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/auth/AuthBearerFilter.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/auth/AuthBearerFilter.java
index 5de9a31542..59d5893687 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/auth/AuthBearerFilter.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/auth/AuthBearerFilter.java
@@ -133,6 +133,10 @@ public class AuthBearerFilter implements Filter {
// ---- "Authorization:" header present.
AuthHeader authHeader = getAuthToken(request, auth);
+ if ( authHeader == null ) {
+ ServletOps.errorBadRequest("Bad syntax in Authorization header");
+ return;
+ }
// Test for Authorization: Bearer ..."
if ( ! authHeader.isBearerAuth() ) {