Search code examples
exceptionopenidplayframework-2.1

How to catch the play.api.libs.openid.Errors$AUTH_CANCEL$ exception?


Using Play Framework 2.1 with OpenID, if I cancel my authentication from the OpenID Provider, I get this exception :

[RuntimeException: play.api.libs.openid.Errors$AUTH_CANCEL$]

Here's my code :

Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
UserInfo userInfo = userInfoPromise.get(); // Exception thrown here

But since it's a Runtime exception, I can't catch it with a try/catch so I'm stuck on how to avoid exception and returns something nicer than a server error to the client.

How can I do that?


Solution

  • A Promise is success biased, for all its operations, it assumes it actually contains a value and not an error. You get the exception because you try to call get on a promise which contains an untransformed error.

    What you want is to determine if the Promise is a success or an error, you can do that with pattern matching for instance.

    try this code:

    AsyncResult(
          OpenID.verifiedId.extend1( _ match {
            case Redeemed(info) => Ok(info.attributes.get("email").getOrElse("no email in valid response"))
            case Thrown(throwable) => {
              Logger.error("openid callback error",throwable)
              Unauthorized
            }
          }
          )
        )
    

    You may want to read more on future and promises, I recommend this excellent article : http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html

    edit : checking the documentation (http://www.playframework.com/documentation/2.1.0/JavaOpenID) in java it seems you are supposed to catch and handle exceptions yourself.

    In any case, you should catch exceptions and if one is thrown redirect back the user to the login page with relevant information.

    something like this should work :

    public class Application extends Controller {
    
    
        public static Result index() {
            return ok("welcome");
        }
    
        public static Result auth() {
            Map<String, String> attributes = new HashMap<String, String>();
            attributes.put("email", "http://schema.openid.net/contact/email");
            final Promise<String> stringPromise = OpenID.redirectURL("https://www.google.com/accounts/o8/id", "http://localhost:9000/auth/callback",attributes);
            return redirect(stringPromise.get());
        }
    
    
        public static Result callback() {
            try{
                Promise<UserInfo> userInfoPromise = OpenID.verifiedId();
                final UserInfo userInfo = userInfoPromise.get();
                System.out.println("id:"+userInfo.id);
                System.out.println("email:"+userInfo.attributes.get("email"));
                return ok(userInfo.attributes.toString());
            } catch (Throwable e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
                return unauthorized();
            }
        }
    }