Skip to content

Instantly share code, notes, and snippets.

@tobyweston
Created December 4, 2013 08:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tobyweston/7784272 to your computer and use it in GitHub Desktop.
Save tobyweston/7784272 to your computer and use it in GitHub Desktop.
OAuth v1 example hashing
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