Digest auth improvements

* ignore case when comparing auth scheme names
* accept (illegal) lower-case algorithm values
* always send back algorithm values (not required by RFC, but some servers require it)
* tests
parent 8064d17d
......@@ -44,9 +44,10 @@ public class BasicDigestAuthenticatorTest extends TestCase {
assertTrue(auth.contains("opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""));
}
public void testRealWorldExample() {
public void testRealWorldExamples() {
BasicDigestAuthenticator authenticator = new BasicDigestAuthenticator(null, "demo", "demo", "MDI0ZDgxYTNmZDk4MTA1ODM0NDNjNmJjNDllYjQ1ZTI=");
// example 1
HttpUtils.AuthScheme authScheme = new HttpUtils.AuthScheme("Digest");
authScheme.params.put("realm", "Group-Office");
authScheme.params.put("qop", "auth");
......@@ -68,6 +69,30 @@ public class BasicDigestAuthenticatorTest extends TestCase {
assertTrue(auth.contains("qop=auth"));
assertTrue(auth.contains("response=\"de3b3b194d85ddc62537208c9c3637dc\""));
assertTrue(auth.contains("opaque=\"df58bdff8cf60599c939187d0b5c54de\""));
// example 2
authenticator = new BasicDigestAuthenticator(null, "test", "test");
authScheme = new HttpUtils.AuthScheme("digest"); // lower case
authScheme.params.put("nonce", "87c4c2aceed9abf30dd68c71");
authScheme.params.put("algorithm", "md5"); // note the (illegal) lower case!
authScheme.params.put("opaque", "571609eb7058505d35c7bf7288fbbec4-ODdjNGMyYWNlZWQ5YWJmMzBkZDY4YzcxLDAuMC4wLjAsMTQ0NTM3NzE0Nw==");
authScheme.params.put("realm", "ieddy.ru");
original = new Request.Builder()
.method("OPTIONS", null)
.url("https://ieddy.ru/")
.build();
request = authenticator.authorizationRequest(original, authScheme);
auth = request.header("Authorization");
assertTrue(auth.contains("algorithm=\"MD5\"")); // some servers require it
assertTrue(auth.contains("username=\"test\""));
assertTrue(auth.contains("realm=\"ieddy.ru\""));
assertTrue(auth.contains("nonce=\"87c4c2aceed9abf30dd68c71\""));
assertTrue(auth.contains("uri=\"/\""));
assertFalse(auth.contains("cnonce="));
assertFalse(auth.contains("nc="));
assertFalse(auth.contains("qop="));
assertTrue(auth.contains("response=\"d42a39f25f80b0d6907286a960ff9c7d\""));
assertTrue(auth.contains("opaque=\"571609eb7058505d35c7bf7288fbbec4-ODdjNGMyYWNlZWQ5YWJmMzBkZDY4YzcxLDAuMC4wLjAsMTQ0NTM3NzE0Nw==\""));
}
public void testMD5Sess() {
......
......@@ -69,9 +69,9 @@ public class BasicDigestAuthenticator implements Authenticator {
HttpUtils.AuthScheme basicAuth = null, digestAuth = null;
for (HttpUtils.AuthScheme scheme : HttpUtils.parseWwwAuthenticate(response.headers(HEADER_AUTHENTICATE).toArray(new String[0])))
if ("Basic".equals(scheme.name))
if ("Basic".equalsIgnoreCase(scheme.name))
basicAuth = scheme;
else if ("Digest".equals(scheme.name))
else if ("Digest".equalsIgnoreCase(scheme.name))
digestAuth = scheme;
// we MUST prefer Digest auth [https://tools.ietf.org/html/rfc2617#section-4.6]
......@@ -87,6 +87,7 @@ public class BasicDigestAuthenticator implements Authenticator {
// Basic auth
if (triedBefore) // credentials didn't work last time, and they won't work now -> stop here
return null;
return request.newBuilder()
.header(HEADER_AUTHORIZATION, Credentials.basic(username, password))
.build();
......@@ -128,13 +129,15 @@ public class BasicDigestAuthenticator implements Authenticator {
else
return null;
if (algorithm != null)
params.add("algorithm=" + quotedString(algorithm.name));
final String method = request.method();
final String digestURI = request.httpUrl().encodedPath();
params.add("uri=" + quotedString(digestURI));
if (qop != null) {
params.add("qop=" + qop.name);
params.add("cnonce=" + quotedString(clientNonce));
int nc = nonceCount.getAndIncrement();
......@@ -164,6 +167,8 @@ public class BasicDigestAuthenticator implements Authenticator {
response = kd(h(a1), nonce + ":" + ncValue + ":" + clientNonce + ":" + qop.name + ":" + h(a2));
} else {
//Constants.log.debug("Using legacy Digest auth");
// legacy (backwards compatibility with RFC 2069)
if (algorithm == Algorithm.MD5) {
String a1 = username + ":" + realm + ":" + password,
......@@ -208,7 +213,7 @@ public class BasicDigestAuthenticator implements Authenticator {
Algorithm(String name) { this.name = name; }
static Algorithm determine(String paramValue) {
if (paramValue == null || Algorithm.MD5.name.equals(paramValue))
if (paramValue == null || Algorithm.MD5.name.equalsIgnoreCase(paramValue))
return Algorithm.MD5;
else if (Algorithm.MD5_SESSION.name.equals(paramValue))
return Algorithm.MD5_SESSION;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment