LoginSignup
29
28

More than 5 years have passed since last update.

Play2 + pac4jでお手軽にOAuth認可をする

Last updated at Posted at 2014-05-17

Play2 + pac4jで簡単にOAuth認可をする

はじめに

最近のWebアプリケーションは、やれTwitter連携だやれFacebook連携だとOAuthを利用した認可機能を盛り込むことが多いと思います。しかし、連携するサービスによってAPIの呼び出し方が異なっていたりと、自分で実装をするとコードのフラグメント化が激しいことになります。

pac4jは、外部サービスアカウントの認証、認可に関する処理の共通化を行う、Javaのライブラリです。詳細は公式サイトを見るのが早いのですが、

  • OAuth1.0,2.0

    • DropBox
    • Facebook
    • Github
    • Google
    • Twitter...
  • CAS

  • HTTP

    • form
    • basic
  • OpenID

  • SAML2.0

と、幅広いProtocol、サービスに対応をしています。また、いくつかのフレームワーク向けにプラグイン、ラッパーも提供されていて組み込みも簡単です。今回は、Play2.2xとScalaを利用して、Twitterの認可を行います。

Twitterアプリを登録する

http://dev.twitter.com/からアプリの登録を行って、Api Key,Api Secretを取得しておきます。また、コールバックURLの指定は${FQDN}/callbackとします。

依存関係を追加する

build.sbtに依存関係を追加します。

libraryDependencies += "org.twitter4j" % "twitter4j-core" % "4.0.1"

resolvers ++= Seq(
  "Sonatype snapshots repository" at "https://oss.sonatype.org/content/repositories/snapshots/"
)

libraryDependencies ++= Seq(
  "org.pac4j"   % "play-pac4j_scala" % "1.2.0",
  "org.pac4j" % "pac4j-oauth" % "1.5.1"
)

今回、TwitterAPIを利用するために、Twitter4Jを利用しています。

設定ファイルを作る

Playのconfディレクトリにpac4j.confファイルを以下の内容で作ります。

{
    "twitter": {
        "api": {
            "key": "先ほど取得したapi key",
            "secret": "先ほど取得したsecret",
            "callback": "Twitterアプリ作成時に設定したコールバックのURL"
        }
    }
}

なお、このファイルはアプリ固有情報を含みます。バージョン管理システムなどを利用する際には、適切に設定を行って管理をしてください。

設定ファイルから読み込む部分を作る

次のようなtraitを用意します。

package models

import play.api.Configuration
import com.typesafe.config.ConfigFactory
import java.io.File
import models.TwitterAuthConfig.ConfigurationError

trait TwitterAuthConfig {

  lazy val consumer : TwitterConsumer = {
    val config = Configuration(ConfigFactory.parseFileAnySyntax(new File("conf/pac4j.conf")))
    (for {
      key <- config.getString("twitter.api.key")
      secret <- config.getString("twitter.api.secret")
    } yield {
      TwitterConsumer(key, secret)
    }).getOrElse(throw new ConfigurationError("conf/pac4j.conf is not define or format is invalid"))
  }

  lazy val callback = {
    val config = Configuration(ConfigFactory.parseFileAnySyntax(new File("conf/pac4j.conf")))
    (for {
      callback <- config.getString("twitter.api.callback")
    } yield {
      callback
    }).getOrElse(throw new ConfigurationError("conf/pac4j.conf is not define or format is invalid"))
  }
}

object TwitterAuthConfig {
  class ConfigurationError(m: String) extends RuntimeException(m)
}
case class TwitterConsumer(key: String, secret: String)

アプリのエントリーポイントを設定する

Playのアプリが立ち上がった際に呼び出されるコールバックをOverrideします。Global.scalaファイルを作り、以下の内容とします。

package controllers

import play.api.GlobalSettings
import play.api.mvc.{ Results, SimpleResult, RequestHeader }
import scala.concurrent.Future
import org.pac4j.oauth.client.TwitterClient
import org.pac4j.core.client.Clients
import org.pac4j.play.Config
import models.twitter.TwitterAuthConfig

object Global extends GlobalSettings with TwitterAuthConfig {

  override def onError(request: RequestHeader, ex: Throwable): Future[SimpleResult] = {
    Future.successful(Results.InternalServerError)
  }

  override def onStart(app: play.api.Application): Unit = {
    val ti = consumer
    val tc = new TwitterClient(ti.key, ti.secret)
    val cl = new Clients(callback, tc)
    Config.setClients(cl)
  }
}

また、このクラスが呼び出されるように、application.confに書き足します。

application.global=controllers.Global

ルーティングを設定する

routesに以下の内容を追記します。

# Authorication
GET     /callback                   org.pac4j.play.CallbackController.callback()
POST    /callback                   org.pac4j.play.CallbackController.callback()
GET     /casProxyCallback           org.pac4j.play.CallbackController.callback()
POST    /casProxyCallback           org.pac4j.play.CallbackController.callback()
GET     /logout                     org.pac4j.play.CallbackController.logoutAndRedirect()

コントローラーを実装する

最期にコントローラーの実装を行います。今回は、

  • Twitterの認可がされてないなら、認可URLを表示
  • Twitterの認可があるなら、上位のツイートを表示

するコントローラーを実装します。

Application..scalaを以下の内容とします。

package controllers

import play.api.mvc._
import org.pac4j.play.scala.ScalaController
import org.pac4j.oauth.profile.twitter.TwitterProfile
import models.TwitterAuthConfig
import twitter4j.auth.AccessToken
import twitter4j.TwitterFactory
import scala.collection.JavaConversions._

object Application extends ScalaController with TwitterAuthConfig {

  lazy val twitter = {
    val tw = TwitterFactory.getSingleton
    tw.setOAuthConsumer(consumer.key, consumer.secret)
    tw
  }

  def index = Action { request =>
    val newSession = getOrCreateSessionId(request)
    val content = Option(getUserProfile(request)).fold(getRedirectAction(request, newSession, "TwitterClient", "/").getLocation) { p =>
      val tp = p.asInstanceOf[TwitterProfile]
      val ac = new AccessToken(tp.getAccessToken, tp.getAccessSecret)

      twitter.setOAuthAccessToken(ac)
      twitter.getUserTimeline.map(_.getText).mkString("\n")
    }
    Ok(content)
  }
}

動かす

とりあえず/にアクセスをすると認可用のURLが表示されるので、そのページへアクセスします。Twitterの認可を了承すれば、画面に最近のツイートが表示されるはずです。

以上です。お疲れ様でした。

おわりに

今回の実装はあくまでサンプルなので、エラー処理とかが曖昧です。例えば、ユーザによって認可が拒否された場合の処理とかがまだ微妙です。また、pac4jやplayframeworkのアップデートは非常に早いです。自分が利用しているバージョンに注意を払い、公式サイトやリポジトリのドキュメントを参照しましょう。

29
28
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
28