Permalink
Browse files

first commit

  • Loading branch information...
murz committed Nov 18, 2010
0 parents commit ac27a144f20e02cad454d492caafec04de75084c
@@ -0,0 +1,78 @@
+# play-fbconnect
+
+Easily integrate Facebook authentication into any Play application.
+
+## Demo
+
+[http://play-lists-fbconnect.appspot.com/](http://play-lists-fbconnect.appspot.com/) is an instance of Guillaume's lists-with-gae demo, modified to utilize this module for Facebook based authentication. The source code of the modified demo can be found in the `samples-and-tests` folder.
+
+## Prerequisites
+
+Before you can use Facebook authentication, you have to [register your application with Facebook](http://www.facebook.com/developers/createapp.php). Be sure to note your Application ID, API Key, and Application Secret.
+
+## Installation
+
+### Install the module
+
+Install the fbconnect module from the modules repository:
+
+ play install fbconnect
+
+### Enable the module
+
+After installing the module, add the following to your `application.conf` to enable it:
+
+ module.fbconnect=${play.path}/modules/fbconnect
+
+### Configure the module
+
+And finally, you need to configure the module by setting these properties in your `application.conf`:
+
+ # Facebook Connect
+ # ~~~~~
+ fbconnect.id=YOUR_APP_ID_HERE
+ fbconnect.apiKey=YOUR_API_KEY_HERE
+ fbconnect.secret=YOUR_APP_SECRET_HERE
+ fbconnect.model=models.User
+ fbconnect.landUrl=/home
+
+All of the properties are required except for `fbconnect.landUrl`, which will default to `/` (Note: `fbconnect.landUrl` can be a URL like `/home` or a controller action like `Application.index`).
+
+## Usage
+
+### Define your OAuth callback
+
+The first step is to implement a method called `facebookOAuthCallback` on the class that you specified as `fbconnect.model`. After a user has authenticated using Facebook, the module will call this method with a JsonObject that contains data about the user. This is your opportunity to add the user to your database, add the user to your session, or do anything else you want to do with the authentic data Facebook provides.
+
+ public static void facebookOAuthCallback(JsonObject data){
+ String email = data.get("email").getAsString();
+ User user = findByEmail(email);
+ if(user == null){
+ user = new User();
+ user.email = email;
+ user.insert();
+ }
+ Session.current().put("user", user.email);
+ }
+
+### Use the `fbconnect.button` tag in your view
+
+The module provides a tag called `fbconnect.button`. The tag outputs a link that will prompt your users to authenticate with Facebook when it is clicked.
+
+ #{fbconnect.button label:'Login using your facebook account.' /}
+
+The tag takes two optional parameters. `label` which defaults to *Sign in with Facebook*, and `cssClass` which defaults to *play-fbconnect-button*.
+
+### Add some style
+
+You are welcome to style the button however you like (heck, you can leave it as a plain link for all I care), but the fbconnect module provides some default styles that you can use to get a decent looking Facebook Connect button.
+
+#### Before
+
+![before](http://play-lists-fbconnect.appspot.com/assets/images/before.jpg)
+
+#### After
+
+![after](http://play-lists-fbconnect.appspot.com/assets/images/after.jpg)
+
+These styles are in a file called `play-fbconnect.min.css` and they can be found in the module's `lib` directory. I should note that the styles will not work if you specify a custom `cssClass` when using the `fbconnect.button` tag.
@@ -0,0 +1,73 @@
+package controllers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import play.Play;
+import play.exceptions.UnexpectedException;
+import play.libs.WS;
+import play.libs.WS.HttpResponse;
+import play.modules.fbconnect.FBConnectPlugin;
+import play.modules.fbconnect.FBConnectSession;
+import play.mvc.*;
+
+public class FBConnect extends Controller {
+
+ public static void callback() {
+ FBConnectPlugin fbplugin = Play.plugin(FBConnectPlugin.class);
+ FBConnectSession fbsession = fbplugin.session();
+ String code = params.get("code");
+ if(code != null && !code.isEmpty()){
+ String authUrl = fbsession.getAuthUrl(code);
+ String response = WS.url(authUrl).get().getString();
+ String accessToken = null;
+ Integer expires = null;
+ String[] pairs = response.split("&");
+ for (String pair : pairs) {
+ String[] kv = pair.split("=");
+ if (kv.length != 2) {
+ throw new UnexpectedException("Module fbconnect got an unexpected auth response from facebook");
+ } else {
+ if (kv[0].equals("access_token")) {
+ accessToken = kv[1];
+ }
+ if (kv[0].equals("expires")) {
+ expires = Integer.valueOf(kv[1]);
+ }
+ }
+ }
+ if (accessToken != null && expires != null) {
+ try{
+ Class model = Class.forName(fbsession.getModel());
+ Class[] paramTypes = new Class[1];
+ paramTypes[0] = JsonObject.class;
+ Method method = model.getMethod("facebookOAuthCallback", paramTypes);
+ if(Modifier.isStatic(method.getModifiers())){
+ String uri = "https://graph.facebook.com/me?access_token="+accessToken;
+ JsonObject jsonData = WS.url(uri).get().getJson().getAsJsonObject();
+ method.invoke(null, jsonData);
+ }else{
+ throw new UnexpectedException("Module fbconnect expects your facebookOAuthCallback method to be static");
+ }
+ }catch(ClassNotFoundException e){
+ throw new UnexpectedException("Module fbconnect cannot find your model class "+fbsession.getModel());
+ }catch(NoSuchMethodException e){
+ throw new UnexpectedException("Module fbconnect requires that your model class "+fbsession.getModel()+" must provide a method with this signature: [public static void facebookOAuthCallback(JsonObject data)]");
+ }catch(IllegalAccessException e){
+ throw new UnexpectedException("Module fbconnect does not have access to call your model's findForFacebookOAuth");
+ }catch(InvocationTargetException e){
+ throw new UnexpectedException("Module fbconnect could not call your model's findForFacebookOAuth: "+e.getMessage());
+ }
+ } else {
+ throw new UnexpectedException("Module fbconnect could not find access token and expires in facebook callback");
+ }
+ }
+ redirect(fbsession.getLandUrl());
+ }
+
+
+}
@@ -0,0 +1,28 @@
+package tags.fbconnect;
+
+import groovy.lang.Closure;
+
+import java.io.PrintWriter;
+import java.util.Map;
+
+import controllers.FBConnect;
+
+import play.Play;
+import play.modules.fbconnect.FBConnectPlugin;
+import play.mvc.Router;
+import play.templates.FastTags;
+import play.templates.GroovyTemplate.ExecutableTemplate;
+
+@FastTags.Namespace("fbconnect")
+public class FBConnectTags extends FastTags {
+
+ public static void _button(Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) {
+ Object labelArg = args.get("label");
+ Object classArg = args.get("cssClass");
+ String label = labelArg != null ? labelArg.toString() : "Sign in with Facebook";
+ String className = classArg != null ? classArg.toString() : "play-fbconnect-button";
+ String url = Play.plugin(FBConnectPlugin.class).session().getLoginUrl();
+ out.println("<a href='"+url+"' class='"+className+"'>"+label+"</a>");
+ }
+
+}
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="fbconnect" default="build" basedir=".">
+
+ <path id="project.classpath">
+ <pathelement path="${play.path}/framework/classes"/>
+ <fileset dir="${play.path}/framework/lib">
+ <include name="*.jar"/>
+ </fileset>
+ <fileset dir="${play.path}/framework">
+ <include name="*.jar"/>
+ </fileset>
+ <fileset dir="lib">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <target name="build" depends="compile">
+
+ <copy todir="tmp/classes">
+ <fileset dir="src">
+ <include name="**/*.properties"/>
+ <include name="**/*.xml"/>
+ <include name="**/play.plugins"/>
+ <include name="**/play.static"/>
+ </fileset>
+ </copy>
+ <jar destfile="lib/play-fbconnect.jar" basedir="tmp/classes">
+ <manifest>
+ <section name="Play-module">
+ <attribute name="Specification-Title" value="fbconnect"/>
+ </section>
+ </manifest>
+ </jar>
+ <delete dir="tmp" />
+ </target>
+
+ <target name="compile">
+ <mkdir dir="tmp/classes" />
+ <javac srcdir="src" destdir="tmp/classes" target="1.5" debug="true">
+ <classpath refid="project.classpath" />
+ </javac>
+ </target>
+
+</project>
Oops, something went wrong.

0 comments on commit ac27a14

Please sign in to comment.