-
-
Save skyhacker2/e227ea4403359773d134098cea5db59a to your computer and use it in GitHub Desktop.
HTTP Digest Auth for Android (incomplete and probably hackable, but works!)
This file contains hidden or 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"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment