Skip to content

Instantly share code, notes, and snippets.

@shin1ogawa
Created February 1, 2011 17:52
Show Gist options
  • Save shin1ogawa/806263 to your computer and use it in GitHub Desktop.
Save shin1ogawa/806263 to your computer and use it in GitHub Desktop.
package appengine.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* utilities for oauth of google app engine.
* @author shin1ogawa
*/
public class OAuthUtil {
static final String ENC = "utf-8";
static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
/**
* @param method
* @param requestUrlBase
* @param parameters
* @param consumerKey
* @param consumerSecret
* @param accessToken
* @param accessTokenSecret
* @return value for Authorization Header
* @throws UnsupportedEncodingException
* @throws InvalidKeyException
* @throws NoSuchAlgorithmException
* @author shin1ogawa
*/
public static String getAuthorizationHeaderValue(String method, String requestUrlBase,
Map<String, String> parameters, String consumerKey, String consumerSecret,
String accessToken, String accessTokenSecret) throws UnsupportedEncodingException,
InvalidKeyException, NoSuchAlgorithmException {
Map<String, String> _params = new LinkedHashMap<String, String>();
if (parameters != null && parameters.isEmpty() == false) {
_params.putAll(parameters);
}
_params.put("oauth_consumer_key", consumerKey);
_params.put("oauth_nonce", generateNonce());
_params.put("oauth_signature_method", "HMAC-SHA1");
_params.put("oauth_timestamp", generateTimestamp());
_params.put("oauth_token", accessToken);
_params.put("oauth_version", "1.0");
String baseString = generateSignatureBaseString(method, requestUrlBase, _params);
String key =
URLEncoder.encode(consumerKey, "utf-8") + "&"
+ URLEncoder.encode(accessTokenSecret, "utf-8");
String signature = URLEncoder.encode(generateHmacSha1Signature(key, baseString), ENC);
StringBuilder b = new StringBuilder("OAuth ");
if (_params.containsKey("oauth_body_hash")) {
b.append("oauth_body_hash").append("=\"").append(_params.get("oauth_body_hash"))
.append("\",");
}
b.append("oauth_consumer_key").append("=\"")
.append(URLEncoder.encode(consumerKey, "utf-8")).append("\"");
b.append(",oauth_token").append("=\"").append(URLEncoder.encode(accessToken, "utf-8"))
.append("\"");
b.append(",oauth_version").append("=\"").append("1.0").append("\"");
b.append(",oauth_timestamp").append("=\"").append(_params.get("oauth_timestamp"))
.append("\"");
b.append(",oauth_nonce").append("=\"").append(_params.get("oauth_nonce")).append("\"");
b.append(",oauth_signature_method").append("=\"").append("HMAC-SHA1").append("\"");
b.append(",oauth_signature").append("=\"").append(signature).append("\"");
return b.toString();
}
static String generateSignatureBaseString(String method, String requestUrlBase,
Map<String, String> params) throws UnsupportedEncodingException {
return escapeAndJoinStrings(Arrays.asList(method, requestUrlBase,
escapeAndJoinParameters(params)));
}
static String escapeAndJoinParameters(Map<String, String> params)
throws UnsupportedEncodingException {
StringBuilder b = new StringBuilder();
boolean first = true;
for (String key : sortedKeyList(params)) {
if (first == false) {
b.append('&');
} else {
first = false;
}
b.append(key).append('=')
.append(URLEncoder.encode(params.get(key), ENC).replace("+", "%20"));
}
return b.toString();
}
static List<String> sortedKeyList(Map<String, String> map) {
List<String> list = new ArrayList<String>(map.keySet());
Collections.sort(list);
return list;
}
static String escapeAndJoinStrings(Iterable<String> params) throws UnsupportedEncodingException {
StringBuilder b = new StringBuilder();
boolean first = true;
for (String s : params) {
if (first == false) {
b.append('&');
} else {
first = false;
}
b.append(URLEncoder.encode(s, ENC));
}
return b.toString();
}
static String generateHmacSha1Signature(String key, String data)
throws NoSuchAlgorithmException, InvalidKeyException, IllegalStateException,
UnsupportedEncodingException {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(ENC), HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
return byteArrayToBase64String(mac.doFinal(data.getBytes(ENC)));
}
static String generateTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000L);
}
static String generateNonce() {
return Long.toString(new Random().nextLong());
}
static String byteArrayToBase64String(byte[] bytes) {
int bytesLength = bytes.length;
int fullGroups = bytesLength / 3;
int partialGroup = bytesLength - 3 * fullGroups;
int resultLength = 4 * ((bytesLength + 2) / 3);
StringBuilder b = new StringBuilder(resultLength);
int cursor = 0;
for (int i = 0; i < fullGroups; i++) {
int byte0 = bytes[cursor++] & 0xff;
int byte1 = bytes[cursor++] & 0xff;
int byte2 = bytes[cursor++] & 0xff;
b.append(intToBase64[byte0 >> 2]);
b.append(intToBase64[(byte0 << 4) & 0x3f | (byte1 >> 4)]);
b.append(intToBase64[(byte1 << 2) & 0x3f | (byte2 >> 6)]);
b.append(intToBase64[byte2 & 0x3f]);
}
if (partialGroup != 0) {
int byte0 = bytes[cursor++] & 0xff;
b.append(intToBase64[byte0 >> 2]);
if (partialGroup == 1) {
b.append(intToBase64[(byte0 << 4) & 0x3f]);
b.append("==");
} else {
int byte1 = bytes[cursor++] & 0xff;
b.append(intToBase64[(byte0 << 4) & 0x3f | (byte1 >> 4)]);
b.append(intToBase64[(byte1 << 2) & 0x3f]);
b.append('=');
}
}
return b.toString();
}
static final char intToBase64[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment