Created
December 4, 2013 08:42
-
-
Save tobyweston/7784272 to your computer and use it in GitHub Desktop.
OAuth v1 example hashing
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 javax.crypto.Mac | |
import javax.crypto.spec.SecretKeySpec | |
import rtx.forest.web.PercentEncoder | |
import com.googlecode.utterlyidle.{RequestBuilder, Request} | |
object OAuth { | |
type ApiKey = String | |
type SharedSecret = String | |
def createAuthorizationRequest(request: Request, nonce: String, timestamp: String, apiKey: String, sharedSecret: String): Request = { | |
RequestBuilder.modify(request).header("Authorization", authorizationHeader(request.method(), request.uri().toString, nonce, timestamp, apiKey, sharedSecret)).build() | |
} | |
private def authorizationHeader(requestMethod: String, requestUri: String, nonce: String, timestamp: String, apiKey: String, sharedSecret: String): String = { | |
val baseParams = Map( | |
"oauth_version" -> "1.0", | |
"oauth_nonce" -> nonce, | |
"oauth_consumer_key" -> s"$apiKey!email@example.com", | |
"oauth_signature_method" -> "HMAC-SHA1", | |
"oauth_timestamp" -> timestamp | |
) | |
val signature = createMessageAuthenticationCode(sharedSecret, requestUri, baseParams.toMap, requestMethod) | |
val allParams = baseParams + ("oauth_signature" -> signature) | |
val encodedParams = allParams.map { | |
case (k, v) => { | |
val encodedValue: String = PercentEncoder.encode(v) | |
k + "=\"" + encodedValue + "\"" | |
} | |
} | |
s"OAuth ${encodedParams.mkString(", ")}" | |
} | |
private def createMessageAuthenticationCode(sharedSecret: String, requestUrl: String, params: Map[String, String], requestMethod: String): String = { | |
val elements = new StringBuffer(requestMethod) | |
elements.append("&").append(PercentEncoder.encode(requestUrl)) | |
val encodedParams: Seq[String] = params.map { | |
case (key, value) => PercentEncoder.encode(key) + "=" + PercentEncoder.encode(value) | |
}.toSeq | |
elements.append("&").append(PercentEncoder.encode(encodedParams.sorted.mkString("&"))) | |
val algorithm = Mac.getInstance("HmacSHA1") | |
val encodedSecret = PercentEncoder.encode(sharedSecret) // probably not necessary for a UUID? | |
val key = (encodedSecret + "&").getBytes("UTF-8") | |
algorithm.init(new SecretKeySpec(key, "HmacSHA1")) | |
val messageAuthenticationCode = algorithm.doFinal(elements.toString.getBytes) | |
new sun.misc.BASE64Encoder().encode(messageAuthenticationCode) | |
} | |
import org.apache.commons.codec.net.URLCodec | |
import org.apache.commons.codec.binary.Base64 | |
import scala.xml.Elem | |
object PercentEncoder { | |
def encode(string: String): String = { | |
new URLCodec("UTF-8").encode(string) | |
} | |
def decode(string: String): String = ??? | |
} | |
object Base64Encoder { | |
def encode(string: String): String = { | |
new String(Base64.encodeBase64(string.getBytes("UTF-8"))) | |
} | |
def encode(xml: Elem): String = { | |
encode("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + xml.toString) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment