Documentation

You are viewing the documentation for the 2.3.8 release in the 2.3.x series of releases. The latest stable release series is 3.0.x.

§OpenID Support in Play

OpenID is a protocol for users to access several services with a single account. As a web developer, you can use OpenID to offer users a way to log in using an account they already have, such as their Google account. In the enterprise, you may be able to use OpenID to connect to a company’s SSO server.

§The OpenID flow in a nutshell

  1. The user gives you his OpenID (a URL).
  2. Your server inspects the content behind the URL to produce a URL where you need to redirect the user.
  3. The user confirms the authorization on his OpenID provider, and gets redirected back to your server.
  4. Your server receives information from that redirect, and checks with the provider that the information is correct.

Step 1 may be omitted if all your users are using the same OpenID provider (for example if you decide to rely completely on Google accounts).

§Usage

To use OpenId, first add javaWs to your build.sbt file:

libraryDependencies ++= Seq(
  javaWs
)

§OpenID in Play

The OpenID API has two important functions:

If the Promise fails, you can define a fallback, which redirects back the user to the login page or return a BadRequest.

§Example

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;
  }

}

§Extended Attributes

The OpenID of a user gives you his identity. The protocol also supports getting extended attributes such as the e-mail address, the first name, or the last name.

You may request optional attributes and/or required attributes from the OpenID server. Asking for required attributes means the user cannot login to your service if he doesn’t provides them.

Extended attributes are requested in the redirect 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
);

Attributes will then be available in the UserInfo provided by the OpenID server.

Next: Accessing resources protected by OAuth