Last active
May 11, 2023 05:56
-
-
Save slightfoot/5624590 to your computer and use it in GitHub Desktop.
HTTP Digest Auth for Android (incomplete and probably hackable, but works!)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.io.UnsupportedEncodingException; | |
import java.net.HttpURLConnection; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import java.util.HashMap; | |
import com.google.common.base.CharMatcher; | |
import com.google.common.base.Joiner; | |
import com.google.common.base.Splitter; | |
import com.google.common.collect.Iterables; | |
import com.google.common.collect.Maps; | |
public class HttpDigestAuth | |
{ | |
public HttpURLConnection tryAuth(HttpURLConnection connection, String username, String password) | |
throws IOException | |
{ | |
int responseCode = connection.getResponseCode(); | |
if(responseCode == HttpURLConnection.HTTP_UNAUTHORIZED){ | |
connection = tryDigestAuthentication(connection, username, password); | |
if(connection == null){ | |
throw new AuthenticationException(); | |
} | |
} | |
return connection; | |
} | |
public static HttpURLConnection tryDigestAuthentication(HttpURLConnection input, String username, String password) | |
{ | |
String auth = input.getHeaderField("WWW-Authenticate"); | |
if(auth == null || !auth.startsWith("Digest ")){ | |
return null; | |
} | |
final HashMap<String, String> authFields = splitAuthFields(auth.substring(7)); | |
MessageDigest md5 = null; | |
try{ | |
md5 = MessageDigest.getInstance("MD5"); | |
} | |
catch(NoSuchAlgorithmException e){ | |
return null; | |
} | |
Joiner colonJoiner = Joiner.on(':'); | |
String HA1 = null; | |
try{ | |
md5.reset(); | |
String ha1str = colonJoiner.join(username, | |
authFields.get("realm"), password); | |
md5.update(ha1str.getBytes("ISO-8859-1")); | |
byte[] ha1bytes = md5.digest(); | |
HA1 = bytesToHexString(ha1bytes); | |
} | |
catch(UnsupportedEncodingException e){ | |
return null; | |
} | |
String HA2 = null; | |
try{ | |
md5.reset(); | |
String ha2str = colonJoiner.join(input.getRequestMethod(), | |
input.getURL().getPath()); | |
md5.update(ha2str.getBytes("ISO-8859-1")); | |
HA2 = bytesToHexString(md5.digest()); | |
} | |
catch(UnsupportedEncodingException e){ | |
return null; | |
} | |
String HA3 = null; | |
try{ | |
md5.reset(); | |
String ha3str = colonJoiner.join(HA1, authFields.get("nonce"), HA2); | |
md5.update(ha3str.getBytes("ISO-8859-1")); | |
HA3 = bytesToHexString(md5.digest()); | |
} | |
catch(UnsupportedEncodingException e){ | |
return null; | |
} | |
StringBuilder sb = new StringBuilder(128); | |
sb.append("Digest "); | |
sb.append("username").append("=\"").append(username ).append("\","); | |
sb.append("realm" ).append("=\"").append(authFields.get("realm") ).append("\","); | |
sb.append("nonce" ).append("=\"").append(authFields.get("nonce") ).append("\","); | |
sb.append("uri" ).append("=\"").append(input.getURL().getPath()).append("\","); | |
//sb.append("qop" ).append('=' ).append("auth" ).append(","); | |
sb.append("response").append("=\"").append(HA3 ).append("\""); | |
try{ | |
final HttpURLConnection result = (HttpURLConnection)input.getURL().openConnection(); | |
result.addRequestProperty("Authorization", sb.toString()); | |
return result; | |
} | |
catch(IOException e){ | |
return null; | |
} | |
} | |
private static HashMap<String, String> splitAuthFields(String authString) | |
{ | |
final HashMap<String, String> fields = Maps.newHashMap(); | |
final CharMatcher trimmer = CharMatcher.anyOf("\"\t "); | |
final Splitter commas = Splitter.on(',').trimResults().omitEmptyStrings(); | |
final Splitter equals = Splitter.on('=').trimResults(trimmer).limit(2); | |
String[] valuePair; | |
for(String keyPair : commas.split(authString)){ | |
valuePair = Iterables.toArray(equals.split(keyPair), String.class); | |
fields.put(valuePair[0], valuePair[1]); | |
} | |
return fields; | |
} | |
private static final String HEX_LOOKUP = "0123456789abcdef"; | |
private static String bytesToHexString(byte[] bytes) | |
{ | |
StringBuilder sb = new StringBuilder(bytes.length * 2); | |
for(int i = 0; i < bytes.length; i++){ | |
sb.append(HEX_LOOKUP.charAt((bytes[i] & 0xF0) >> 4)); | |
sb.append(HEX_LOOKUP.charAt((bytes[i] & 0x0F) >> 0)); | |
} | |
return sb.toString(); | |
} | |
public static class AuthenticationException extends IOException | |
{ | |
private static final long serialVersionUID = 1L; | |
public AuthenticationException() | |
{ | |
super("Problems authenticating"); | |
} | |
} | |
} |
Does the response to the request come encrypted?
Hi, thank you! It works. Should i leave a special copyright in the source if using this code?
Dou you have an example, how to use it ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use HttpDigestAuth with Volley library ?