-
Notifications
You must be signed in to change notification settings - Fork 0
Step 9 authentication
Purpose: in this step we will see how our user can authenticate themselves using facebook or twitter.
cd ~/devel/apps
git clone git://github.com/opensas/play-demo.git
cd play-demo
git checkout origin/09-authentication
First of all you'll need to register your app at twitter. Go to https://dev.twitter.com/apps, sign in with your twitter account, click on Create a new application
Name: play-demo
Description: Play framework demonstration app
Web site: play-demo.appspot.com
Callback url: http://127.0.0.1/oautht
For more info about signing in with your twitter account see here.
After this, you'll see a page with the following info
Consumer key kkkkkkkkkkkkkkkkkk
Consumer secret ssssssssssssssssssssssssssssss
Request token URL https://api.twitter.com/oauth/request_token
Authorize URL https://api.twitter.com/oauth/authorize
Access token URL https://api.twitter.com/oauth/access_token
Now go to your application.conf and create the following entries:
[...]
twitter.requestTokenURL=http://twitter.com/oauth/request_token
twitter.accessTokenURL=http://twitter.com/oauth/access_token
twitter.authorizationURL=http://twitter.com/oauth/authenticate
twitter.consumerKey=kkkkkkkkkkkkkkkkkk
twitter.consumerSecret=ssssssssssssssssssssssssssssss
Now we'll create a new User model to store user credentials
model.User
@Entity
public class User extends Model {
public String name;
public String avatarUrl;
// Twitter
public String token;
public String secret;
// Facebook
public String accessToken;
}
Add the following routes to the routes file
conf/routes
[...]
#
# Authentication
#
GET /oauthtw Secure.oauthTwitter
GET /oauthfb Secure.oauthFacebook
GET /login Secure.login
GET /logout Secure.logout
Now we'll create the controller that will take care of interacting with twitter and facebook
controllers.Secure
public class Secure extends Controller {
private final static String USER_COOKIE = "user";
private final static OAuth.ServiceInfo TWITTER = new OAuth.ServiceInfo(
Play.configuration.getProperty("twitter.requestTokenURL"),
Play.configuration.getProperty("twitter.accessTokenURL"),
Play.configuration.getProperty("twitter.authorizationURL"),
Play.configuration.getProperty("twitter.consumerKey"),
Play.configuration.getProperty("twitter.consumerSecret")
);
public static void login() {
render();
}
public static void logout() {
session.clear();
Application.list();
}
}
We will add the action that will authentication with twitter
public static void oauthTwitter() {
// first time the request comes here
// the user has just pushed the "sign in with twitter button"
if (!OAuth.isVerifierResponse()) {
final OAuth twitter = OAuth.service(TWITTER);
final OAuth.Response response = twitter.retrieveRequestToken();
if (response.error==null) {
final User user = new User();
user.token = response.token;
user.secret = response.secret;
user.save();
session.put("userId", user.id);
redirect(twitter.redirectUrl(response.token));
} else {
Logger.error("Error contacting twitter: " + response.error);
login();
}
// the user has been redirected by twitter
// OAuth.isVerifierResponse() == true
} else {
// user has not authorized access
if (params.get("denied")!=null) login();
// user authorized access
final String userId = session.get("userId");
if(userId==null) login();
session.remove("userId");
final User user = User.findById(Long.valueOf(userId));
final OAuth.Response response = OAuth.service(TWITTER).retrieveAccessToken(user.token, user.secret);
if (response.error==null) {
// replace old token and secret with new ones
user.token = response.token;
user.secret = response.secret;
// get user info
JsonObject twitterUser =
WS.url("http://api.twitter.com/1/account/verify_credentials.json")
.oauth(TWITTER, user.token, user.secret).get().getJson().getAsJsonObject();
if (twitterUser.get("error") != null) {
// error fetching user info, probably the token has expired
Logger.error("Twitter authentication error: %s", twitterUser.get("error"));
login();
}
user.name = twitterUser.get("name").getAsString();
user.avatarUrl = twitterUser.get("profile_image_url").getAsString();
user.save();
session.put(USER_COOKIE, user.id);
}
Application.list();
}
}
And now we'll create the login view.
views/Secure/login.html
#{extends 'main.html' /}
#{set title:'Login' /}
<div class="alert-message block-message error">
<h3>&{'login.legend'}</h3>
<p style="padding-top:5px;">
<a href="@{Secure.oauthTwitter}"><img src="@{'/public/images/sign-in-with-twitter.png'}"/></a>
<a href="@{Secure.oauthFacebook}"><img style="padding-bottom:1px;" src="@{'/public/images/sign-in-with-facebook.png'}"/></a>
</p>
</div>
We can give it a try
After that, go to facebook developer's page, register the app, and implement the action that will authenticate us with facebook. So add the following action to Secure controller:
controllers.Secure
[...]
public static OAuth2 FACEBOOK = new OAuth2(
Play.configuration.getProperty("facebook.authorizationURL"),
Play.configuration.getProperty("facebook.accessTokenURL"),
Play.configuration.getProperty("facebook.clientid"),
Play.configuration.getProperty("facebook.secret")
);
[...]
public static void oauthFacebook() throws Throwable
{
if ( params.get("error") != null ) {
// El usuario no autorizo el acceso
// error_reason y error_description traen mas info
login();
}
final String authUrl = play.mvc.Router.getFullUrl("Secure.oauthFacebook");
if (OAuth2.isCodeResponse()) {
// El usuario autorizo el acceso desde Facebook
OAuth2.Response response = FACEBOOK.retrieveAccessToken(authUrl);
User user = User.find("accessToken = ?", response.accessToken).first();
if ( user == null ) {
user = new User();
user.accessToken = response.accessToken;
}
JsonObject me = WS.url("https://graph.facebook.com/me?fields=name,picture&access_token=%s", WS.encode(user.accessToken)).get().getJson().getAsJsonObject();
user.name = me.get("name").getAsString();
user.avatarUrl = me.get("picture").getAsString();
user.save();
session.put(USER_COOKIE, user.id);
Application.list();
}
FACEBOOK.retrieveVerificationCode(authUrl);
}
[...]
Now we are going to Step 10 - authorization.