§Play の OpenID サポート
OpenID はユーザが単一のアカウントで複数のサービスにアクセスできるようにするためのプロトコルです。 Web 開発者としては、 OpenID を使うことで、ユーザが別のサービスで既に作成してあるアカウント (例えば Google アカウント ) であなたの Web アプリケーションにログインできるようになります。エンタープライズ向けには、企業の SSO サーバに接続するために OpenID を使うといったことも考えられます。
§OpenID のフロー概要
- ユーザが OpenID (ある URL) を提供します。
- アプリケーションサーバが URL の示すコンテンツを検証し、ユーザのリダイレクト先 URL を生成します。
- ユーザが OpenID プロバイダのサイトにて認可情報を確認し、アプリケーションサーバに再度リダイレクトされます。
- アプリケーションサーバがリダイレクトから認可情報を取得して、その情報が正しいことをプロバイダに確認します。
すべてのユーザが同じ OpenID プロバイダを使う場合 (例えば Google アカウントにのみ依存すると決断した場合) 、ステップ 1 を省略することができます。
§Play における OpenID
OpenID API には特に重要な関数が二つあります。
OpenID.redirectURL
は、ユーザのリダイレクト先 URL を計算する関数です。この関数は、非同期でユーザの OpenID ページを検索するため、String
ではなくPromise[String]
を返します。OpenID が無効な場合、Promise
の中身はThrown
になります。OPenID.verifiedId
は、暗黙的なRequest
を引数にとり、それを元に検証済みの OpenID を始めとするユーザの認可情報を組み立てます。この関数は、認可元の情報を確認するため、 OpenID サーバと通信を行います。この関数がUserInfo
ではなくPromise[UserInfo]
を返すのはそのためです。認可情報が不正か、サーバが単に (リダイレクト URL が書き換えられるなどの理由で) 確認に失敗した場合、Promise
の中身はThrown
になります。
いずれの場合でも、Promise
の中身が Thrown
であった場合、実際にどんな Throwable
が投げられたのかを調べて、エラー情報などと共にユーザを再度ログインページへリダイレクトさせるべきです。
次に、とあるコントローラから抽出した例を示します。
def login = Action {
Ok(views.html.login())
}
def loginPost = Action { implicit request =>
Form(single(
"openid" -> nonEmptyText
)).bindFromRequest.fold(
error => {
Logger.info("bad request " + error.toString)
BadRequest(error.toString)
},
{
case (openid) => AsyncResult(OpenID.redirectURL(openid, routes.Application.openIDCallback.absoluteURL())
.extend( _.value match {
case Redeemed(url) => Redirect(url)
case Thrown(t) => Redirect(routes.Application.login)
}))
}
)
}
def openIDCallback = Action { implicit request =>
AsyncResult(
OpenID.verifiedId.extend( _.value match {
case Redeemed(info) => Ok(info.id + "\n" + info.attributes)
case Thrown(t) => {
// Here you should look at the error, and give feedback to the user
Redirect(routes.Application.login)
}
})
)
}
§拡張属性
OpenID はユーザの同一性を確かめるために利用することができます。それ以外にメールアドレスや名前、苗字などの取得のために 拡張属性 というものもサポートされています。
OpenID サーバに対しては、*任意* および 必須 の属性のどちらか一方または両方をリクエストすることができます。必須の属性を要求するということは、ユーザがその情報を提供しないかぎり、あなたのサービスへログインできないことを意味します。
拡張属性はリダイレクト URL の中でリクエストされます。
OpenID.redirectURL(
openid,
routes.Application.openIDCallback.absoluteURL(),
Seq("email" -> "http://schema.openid.net/contact/email")
)
リクエストした属性は OpenID サーバから返却された UserInfo
より取得することができます。
次ページ: OAuth