1 note &
Login with Facebook clojure/java
I spend a couple of days trying to implement OAuth2 (aka Login with -{facebook, twitter, google, & more}) in clojure when I finally gave up.
There are several libraries out there but honestly I don’t like any of those, or they don’t work.
Even worse I didn’t find any patter to follow, even if I didn’t look very careful and this is why I am writing this micro-post.
First of all I am gonna use a java library, scribe it’s looks like it is widely used in the java community but I didn’t know its existence before, its look like an amazing library for OAuth and I didn’t spend to much time experimenting at the REPL thanks to the amazing documentation and examples.
Ok, let’s go into something more interesting, how “Login with Facebook” works ?
First of all you need to make an app on facebook, it’s not difficult, remember to put the real domain when they ask for, the App ID and the App Secret are very important but they won’t go away so…
Then it’s pretty simple, your user click the button and you redirect him to an URL that FB gave to you which lead to the FB page where the user can login in facebook and authorized the app, when everything is done, so the user has authorized your app, facebook re-direct the user to your domain in a specific URL passing via GET a huge string, now you exchange that string with a token and finally the token with the info that you need, stuff like name, email, where the user live and more — a lot more even if I asked only the basic information.
Ok, I am boring… Let’s go straight to the code:
The model
(ns morgan.models.social
(:require [clj-http.client :as client])
(:import [org.scribe.oauth OAuthService]
[org.scribe.builder ServiceBuilder]
[org.scribe.model Token Verifier OAuthRequest Verb])
(:import [org.scribe.builder.api FacebookApi TwitterApi]))
(def facebook-service
(-> (doto
(ServiceBuilder.)
(.provider (FacebookApi.))
(.apiKey “your api key”)
(.apiSecret “your api secret”)
(.callback “URL where FB is gonna re-direct your user”))
(.build))) ;;It’s necessary to call .build outside the doto,
;;otherwise we would get a ServiceBuilder and not a OAuthService…
(def facebook-url
(.getAuthorizationUrl facebook-service nil))
(defn get-info-facebook [code]
(let [verifier (Verifier. code)
token (.getAccessToken facebook-service nil verifier)
request (OAuthRequest. (Verb/GET) “https://graph.facebook.com/me”)]
(do
(.signRequest facebook-service token request))
(.getBody (.send request))))
(ns morgan.views.social(:use [noir.core :only [defpage]][noir.response :only [redirect]][morgan.models.social]))(defpage “/facebook” [](redirect facebook-url))(defpage “/fb” {:keys [code]}(get-info-facebook code))