alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Play Framework/Scala example source code file (OAuthRequestVerifier.scala)

This example Play Framework source code file (OAuthRequestVerifier.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Play Framework (and Scala) source code examples by using tags.

All credit for the original source code belongs to Play Framework; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Play Framework tags/keywords

api, core, hmac-sha1, hmacsha1, lib, library, matchresult, oauth, oauthrequestverifier, parser, play, play framework, requestheader, requesttoken, seq, string, us-ascii

The OAuthRequestVerifier.scala Play Framework example source code

/*
 * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
 */
package play.api.libs.oauth

import play.api.mvc.RequestHeader
import play.core.parsers.FormUrlEncodedParser
import java.util.Locale
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Mac
import org.apache.commons.codec.binary.Base64
import org.specs2.matcher.MustExpectations._
import org.specs2.matcher.Matchers._
import _root_.oauth.signpost.{ OAuth => SPOAuth }
import org.specs2.matcher.MatchResult

/**
 * Verifies OAuth requests
 */
object OAuthRequestVerifier {

  import SPOAuth.{ percentEncode, percentDecode }

  /**
   * Verify that the given request is a valid OAuth request given the consumer key and request token
   */
  def verifyRequest(request: RequestHeader, body: Array[Byte], hostUrl: String, consumerKey: ConsumerKey,
                    requestToken: RequestToken): MatchResult[_] = {
    val method = request.method
    val baseUrl = hostUrl + request.path

    request.headers.get("Authorization") must beSome.like {
      case authorization =>
        authorization must startWith("OAuth ")
        val oauthParams = authorization.drop(6).split(", ").map { param =>
          val splitted = param.split("=")
          val key = percentDecode(splitted(0))
          val rawValue = splitted(1)
          rawValue must startWith("\"")
          rawValue must endWith("\"")
          val value = percentDecode(rawValue.drop(1).dropRight(1))
          key -> value
        }

        val oauthParamsMap = oauthParams.toMap
        val oauthSignature = oauthParamsMap.get("oauth_signature")
        val oauthToken = oauthParamsMap.get("oauth_token")
        val oauthConsumerKey = oauthParamsMap.get("oauth_consumer_key")
        val oauthSignatureMethod = oauthParamsMap.get("oauth_signature_method")
        val oauthTimestamp = oauthParamsMap.get("oauth_timestamp")

        // Verify various fields
        oauthToken must beSome(requestToken.token)
        oauthConsumerKey must beSome(consumerKey.key)
        oauthSignatureMethod must beSome("HMAC-SHA1")
        oauthTimestamp must beSome.like {
          case timestamp =>
            // Verify no more than 100 seconds in the past
            timestamp.toLong must beGreaterThan(System.currentTimeMillis() / 1000 - 100)
        }

        // Verify the signature
        val collectedParams = oauthParams.filterNot(_._1 == "oauth_signature") ++ request.queryString.toSeq.flatMap {
          case (key, values) => values.map(value => key -> value)
        }
        // If the body is form URL encoded, must include body parameters
        val collectedParamsWithBody = request.contentType match {
          case Some(formUrlEncoded) if formUrlEncoded.startsWith("application/x-www-form-urlencoded") =>
            val form = FormUrlEncodedParser.parse(new String(body, "US-ASCII")).toSeq.flatMap {
              case (key, values) => values.map(value => key -> value)
            }
            collectedParams ++ form
          case _ => collectedParams
        }
        oauthSignature must beSome.like {
          case signature =>
            val ourSignature = signParams(method, baseUrl, collectedParamsWithBody, consumerKey.secret, requestToken.secret)
            signature must_== ourSignature
        }
    }

  }

  def signParams(method: String, baseUrl: String, params: Seq[(String, String)], consumerSecret: String, tokenSecret: String) = {
    // See https://dev.twitter.com/docs/auth/creating-signature

    // Params must be percent encoded before they are sorted
    val parameterString = params.map {
      case (key, value) => percentEncode(key) -> percentEncode(value)
    }.sorted.map {
      case (key, value) => s"$key=$value"
    }.mkString("&")

    val signatureBaseString = s"${method.toUpperCase(Locale.ENGLISH)}&${percentEncode(baseUrl)}&${percentEncode(parameterString)}"

    val signingKey = s"${percentEncode(consumerSecret)}&${percentEncode(tokenSecret)}"

    val keySpec = new SecretKeySpec(signingKey.getBytes("US-ASCII"), "HmacSHA1")
    val mac = Mac.getInstance("HmacSHA1")
    mac.init(keySpec)
    val signature = mac.doFinal(signatureBaseString.getBytes("US-ASCII"))
    new String(Base64.encodeBase64(signature), "US-ASCII")
  }

}

Other Play Framework source code examples

Here is a short list of links related to this Play Framework OAuthRequestVerifier.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.