Thursday 27 November 2014

How to test an action secure by SecureSocial in Play Framework 2 in Java?

SecureSocial is an authentication module for Play Framework 2 applications supporting OAuth, OAuth2, OpenID, Username/Password and custom authentication schemes. Suppose you have an action and you have secured it with @SecureSocial.SecuredAction annotation:

public class Application extends Controller {
    @SecureSocial.SecuredAction
    public static Result index() {
        Identity user = (Identity) ctx().args.get(SecureSocial.USER_KEY);
        return ok(index.render(user));
    }
}

At the time of writing this blog post, SecureSocial only uses cookies for authentication. If you want to write a functional test for this action without taking care of a fake cookie you will get an unauthorized message. To do this we need to some provisioning before our test. Best is to use the @Befor. Below is the steps:
  1. Lets assume that you save your user authentication data in the User model. Here we create a fake user before
  2. 
    @Before
    public void setUp() throws Exception {
       User user = new User();
       User user = new User();
       user.firstName = "jack";
       user.lastName = "sparrow";
       user.email = "jack.sparrow@caribbean.com";
       user.providerId = "userpasswordid";
       user.password = "$2a$10$ywqls6dRsN4wLr.xNydi2uDVFNkOlmi9WSAfRy.RXdN5sgKKnKhau";
       user.authMethod = "userPassword";
       user.save();
    }
    
    
    Please note that the password that you see above is a hash produced with "Bcrypt" encryption and the value depends on how you have implemented this. See Secure Social Password Plugin for more info.
  3. Now create a class named FunctionalTestHelpers and add the following method:
  4. 
    public static Http.Cookie getFakeCookie(String email){
            User user = User.findByEmail(email);
    
            SocialUser socialUser = new SocialUser(new IdentityId(user.email,user.providerId),
                    user.firstName,
                    user.lastName,
                    String.format("%s %s", user.firstName, user.lastName),
                    Option.apply(user.email),
                    null,
                    new AuthenticationMethod("userPassword"),
                    null,
                    null,
                    Some.apply(new PasswordInfo("bcrypt", user.password, null))
            );
    
            Either either = Authenticator.create(socialUser);
            Authenticator auth = (Authenticator) either.right().get();
            Cookie scalaCookie = auth.toCookie();
    
            return new Http.Cookie(scalaCookie.name(),
                                   scalaCookie.value(),
                                   null,
                                   scalaCookie.path(),
                                   null,
                                   scalaCookie.secure(),
                                   scalaCookie.httpOnly());
    
        }
    
    
  5. Now you can use the code below in your tests to get a fake cookie. The code above basically mimics what SecureSocial does for creating a cookie.
  6.  
    Http.Cookie fakeCookie = FunctionalTestHelpers.getFakeCookie("jack.sparrow@caribbean.com"); 
    
  7. Now lets see it in action:
  8. 
    final Result deleteResult = callAction(controllers.routes.ref.TaskController.removeTask(taskId),fakeRequest().withCookies(fakeCookie).withHeader("Csrf-Token", "nocheck"));
    assertThat(status(deleteResult)).isEqualTo(OK);
    
    

No comments:

Post a Comment