[JERSEY-642] HTTP Digest Authentication auth-int is Broken in Client Created: 08/Feb/11 Updated: 10/Sep/15 Resolved: 10/Dec/13 Status: Project: Component/s: Affects Version/s: Fix Version/s: Closed jersey core None Type: Reporter: Resolution: Labels: Remaining Estimate: Time Spent: Original Estimate: Bug jamesrdf Fixed None 0 minutes Issue Links: Related is related to 2.5 Priority: Assignee: Votes: Minor Miroslav Fuksa 0 13 hours 30 minutes JERSEY2264 Implement "auth-int" method to the Ht... Resolved Description The client filter does not compute the response correctly when using qop=auth-int. The entity body should be hashed before computing A2, however, the implementation uses the entity body as-is (without hashing it first). The Entity.toString() method returns a string representation of the entity-body (not a md5 hash). Furthermore a null entity should be treated as an empty body (zero length string). MD5("") = "d41d8cd98f00b204e9800998ecf8427e" http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jerseyclient/src/main/java/com/sun/jersey/api/client/filter/HTTPDigestAuthFilter.java?rev=4578 line 350 says: // HA2 : Switch on qop String HA2; if (state.get().qop == QOP.AUTH_INT && (request.getEntity() != null)) { HA2 = concatMD5( request.getMethod(), uri, request.getEntity().toString()); } else { HA2 = concatMD5( request.getMethod(), uri); } http://tools.ietf.org/html/rfc2617#section-3.2.2.3 says: If the "qop" value is "auth-int", then A2 is: A2 = Method ":" digest-uri-value ":" H(entity-body) This would be better, but only works if the entity is not streamed and has charset iso-8859-1. // HA2 : Switch on qop String HA2; if (state.get().qop == QOP.AUTH_INT && (request.getEntity() == null)) { HA2 = concatMD5( request.getMethod(), uri, "d41d8cd98f00b204e9800998ecf8427e"); } else if (state.get().qop == QOP.AUTH_INT) { HA2 = concatMD5( request.getMethod(), uri, concatMD5(request.getEntity().toString())); } else { HA2 = concatMD5( request.getMethod(), uri); } The call to concatMD5(request.getEntity().toString()) would have to be changed to hash the binary form of the entity (using request charset if applicable). A short term workaround would be to disable qop=auth-int in the client. Most servers supporting qop=auth-int also support qop=auth. As it is now the client can't talk to server's supporting qop=auth-int because of this broken client implementation. Comments Comment by Pavel Bucek [ 08/Feb/12 ] I'm not sure whether we will be able to fix this in 1.x; any contributions are welcomed, but it might not be an easy task (streaming entities, proper testing, etc.). Anyway, thanks for thorough analysis, it will definitely help. Comment by Miroslav Fuksa [ 09/Dec/13 ] Hi jamesrdf, Which container have you used. I have tested that with glassfish and jetty and none of them uses qop=auth-int. I found only a support for qop=auth. Thank you Mira Comment by jamesrdf [ 09/Dec/13 ] We had to remove support for auth-int on the server side to allow jersey to connect to it. See http://www.xiven.com/weblog/2003/07/23/DigestiveBiscuits for an implementation James Comment by Miroslav Fuksa [ 09/Dec/13 ] Ok, I see. I have removed support for auth-int in jersey digest filter (HttpBasicAuthFilter) in jersey 2.x. When server requests qop="auth,auth-int" then auth will be used. The code will be part of the release 2.5. Thank you for your help. Mira Comment by Miroslav Fuksa [ 09/Dec/13 ] I created a task for implementing auth-int correctly. Comment by Miroslav Fuksa [ 10/Dec/13 ] fixed bugs in digest filter (client nonce, dropping entity) removed support for "qop=auth-int" Generated at Tue Feb 09 19:32:04 UTC 2016 using JIRA 6.2.3#6260sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.