§Play の OpenID 対応
OpenID はユーザが単一のアカウントで複数のサービスにアクセスできるようにするためのプロトコルです。Web 開発者としては、OpenID を使うことで、例えば Google アカウント のような、ユーザがすでに所有しているアカウントを使ってログインする方法を提供できます。エンタープライズにおいては、企業の SSO サーバに接続するために OpenID を使うといったことも考えられます。
§OpenID のフロー概要
- ユーザが OpenID (ある URL) を提供します。
- アプリケーションサーバが URL の示すコンテンツを検証し、ユーザのリダイレクト先 URL を生成します。
- ユーザが OpenID プロバイダのサイトにて認可情報を確認し、アプリケーションサーバに再度リダイレクトされます。
- アプリケーションサーバがリダイレクトから認可情報を取得して、その情報が正しいことをプロバイダに確認します。
すべてのユーザが同じ OpenID プロバイダを使う場合 (例えば Google アカウントにのみ依存すると決断した場合) 、ステップ 1 を省略することができます。
§使い方
OpenId を使うには、まず build.sbt
ファイルに javaWs
を追加します:
libraryDependencies ++= Seq(
javaWs
)
§Play における OpenID
OpenID API には特に重要な関数が二つあります。
OpenID.redirectURL
は、ユーザのリダイレクト先 URL を計算する関数です。この関数は、非同期でユーザの OpenID ページを検索するため、Promise<String>
を返します。OpenID が無効な場合、返却されるPromise
は失敗します。OpenID.verifiedId
は、現在のリクエストを調べて、検証済みの OpenID を始めとするユーザの認可情報を組み立てます。この関数は、非同期に認可元の情報を確認するために OpenID サーバと通信を行うので、Promise<UserInfo>
を返します。認可情報が不正か、サーバが単に (リダイレクト URL が書き換えられるなどの理由で) 確認に失敗した場合、返却されるPromise
はThrown
になります。
Promise
が失敗するかもしれないので、ユーザーをログインページにリダイレクトするか、または BadRequest
を返すフォールバックを定義することができます。
§例
conf/routes
:
GET /openID/login controllers.OpenIDController.login()
POST /openID/login controllers.OpenIDController.loginPost()
GET /openID/callback controllers.OpenIDController.openIDCallback()
controller:
- Java
-
import java.util.HashMap; import java.util.Map; import play.data.DynamicForm; import play.data.Form; import play.libs.F.Function; import play.libs.F.Promise; import play.libs.openid.OpenID; import play.libs.openid.OpenID.UserInfo; import play.mvc.Controller; import play.mvc.Result; public class OpenIDController extends Controller { public static Result login() { return ok(views.html.login.render("")); } public static Promise<Result> loginPost() { DynamicForm requestData = Form.form().bindFromRequest(); String openID = requestData.get("openID"); final Promise<String> redirectUrlPromise = OpenID.redirectURL(openID, routes.OpenIDController.openIDCallback().absoluteURL(request())); final Promise<Result> resultPromise = redirectUrlPromise.map(new Function<String, Result>() { @Override public Result apply(String url) { return redirect(url); } }).recover(new Function<Throwable, Result>() { @Override public Result apply(Throwable throwable) throws Throwable { return badRequest(views.html.login.render(throwable.getMessage())); } }); return resultPromise; } public static Promise<Result> openIDCallback() { final Promise<UserInfo> userInfoPromise = OpenID.verifiedId(); final Promise<Result> resultPromise = userInfoPromise.map(new Function<UserInfo, Result>() { @Override public Result apply(UserInfo userInfo) { return ok(userInfo.id + "\n" + userInfo.attributes); } }).recover(new Function<Throwable, Result>() { @Override public Result apply(Throwable throwable) throws Throwable { return badRequest(views.html.login.render(throwable.getMessage())); } }); return resultPromise; } }
- Java 8
-
import javaguide.ws.controllers.routes; import play.data.DynamicForm; import play.data.Form; import play.libs.F.Promise; import play.libs.openid.OpenID; import play.libs.openid.OpenID.UserInfo; import play.mvc.Controller; import play.mvc.Result; public class OpenIDController extends Controller { public static Result login() { return ok(views.html.login.render("")); } public static Promise<Result> loginPost() { // Form data final DynamicForm requestData = Form.form().bindFromRequest(); final String openID = requestData.get("openID"); final Promise<String> redirectUrlPromise = OpenID.redirectURL(openID, routes.OpenIDController.openIDCallback().absoluteURL(request())); final Promise<Result> resultPromise = redirectUrlPromise.map(url -> { return redirect(url); }).recover(throwable -> { return badRequest(views.html.login.render(throwable.getMessage())); }); return resultPromise; } public static Promise<Result> openIDCallback() { final Promise<UserInfo> userInfoPromise = OpenID.verifiedId(); final Promise<Result> resultPromise = userInfoPromise.map(userInfo -> { return (Result) ok(userInfo.id + "\n" + userInfo.attributes); }).recover(throwable -> { return badRequest(views.html.login.render(throwable.getMessage())); }); return resultPromise; } }
§拡張属性
OpenID はユーザの同一性を提供します。メールアドレスや名前、苗字などを取得する 拡張属性 もサポートしています。
OpenID サーバに対しては、 任意 および 必須 の属性のどちらか一方または両方をリクエストすることができます。必須の属性を要求するということは、ユーザがその情報を提供しないかぎり、あなたのサービスへログインできないことを意味します。
拡張属性はリダイレクト URL の中でリクエストされます。
final Map<String, String> attributes = new HashMap<String, String>();
attributes.put("email", "http://schema.openid.net/contact/email");
final Promise<String> redirectUrlPromise = OpenID.redirectURL(
openID,
routes.OpenIDController.openIDCallback().absoluteURL(request()),
attributes
);
リクエストした属性は OpenID サーバから返却された UserInfo
より取得することができます。
Next: OAuth によリ保護されたデータへのアクセス
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。