Skip to content
Browse files

added facebook provider

  • Loading branch information...
1 parent 9f94b57 commit 1ab3941fdad111da53e9a2997aa8b805e8d6fe78 @dvv committed
Showing with 91 additions and 3 deletions.
  1. +1 −0 README.md
  2. +1 −2 src/cowboy_request.erl
  3. +13 −1 src/cowboy_social.erl
  4. +76 −0 src/cowboy_social_facebook.erl
View
1 README.md
@@ -32,6 +32,7 @@ Router configuration
Supported providers
--------------
+- Facebook
- Github
- Google
- Mail.ru
View
3 src/cowboy_request.erl
@@ -77,8 +77,7 @@ parse({ok, JSON}) ->
case jsx:decode(JSON, [{error_handler, fun(_, _, _) -> {error, badarg} end}])
of
{error, _} ->
- % {ok, cowboy_http:x_www_form_urlencoded(JSON)};
- {error, badarg};
+ {ok, cowboy_http:x_www_form_urlencoded(JSON)};
Hash ->
{ok, Hash}
end;
View
14 src/cowboy_social.erl
@@ -15,6 +15,7 @@
%%
init(_Transport, Req, Opts) ->
+% pecypc_log:info({url, cowboy_req:get([path, qs_vals], Req)}),
% compose full redirect URI
case key(callback_uri, Opts) of
<< "http://", _/binary >> -> {ok, Req, Opts};
@@ -40,6 +41,7 @@ handle(Req, Opts) ->
%% to our next handler
%%
handle_request(<<"login">>, Req, Opts) ->
+% pecypc_log:info({login, cowboy_req:get([path, qs_vals], Req), Opts}),
cowboy_req:reply(302, [
{<<"location">>, (key(provider, Opts)):get_authorize_url(Opts)}
], <<>>, Req);
@@ -48,10 +50,12 @@ handle_request(<<"login">>, Req, Opts) ->
%% provider redirected back to us with authorization code
%%
handle_request(<<"callback">>, Req, Opts) ->
+% pecypc_log:info({callback, cowboy_req:get([path, qs_vals], Req), Opts}),
case cowboy_req:qs_val(<<"code">>, Req) of
{undefined, Req2} ->
finish({error, nocode}, Req2, Opts);
{Code, Req2} ->
+ % get_access_token(Code, Req2, Opts)
try get_access_token(Code, Req2, Opts) of
Result -> Result
catch _:_ ->
@@ -85,7 +89,15 @@ get_user_profile(Auth, Req, Opts) ->
%%
finish(Status, Req, Opts) ->
{M, F} = key(handler, Opts),
- M:F(Status, Req).
+ {session, Session, SessionOpts} = lists:keyfind(session, 1, Opts),
+ Session2 = case Status of
+ {ok, Auth, Profile} ->
+ [{access_token, key(access_token, Auth)}, {profile, Profile}];
+ {error, _Reason} ->
+ undefined
+ end,
+ Req2 = cowboy_cookie_session:set_session(Session2, SessionOpts, Req),
+ M:F(Status, Req2).
%%
%%------------------------------------------------------------------------------
View
76 src/cowboy_social_facebook.erl
@@ -0,0 +1,76 @@
+%%
+%% @doc Handler for social login via Facebook.
+%%
+
+-module(cowboy_social_facebook).
+-author('Vladimir Dronnikov <dronnikov@gmail.com>').
+
+-export([
+ get_authorize_url/1,
+ get_access_token/2,
+ get_user_profile/2
+ ]).
+
+%%
+%%------------------------------------------------------------------------------
+%% OAUTH2 Application flow
+%%------------------------------------------------------------------------------
+%%
+
+%%
+%% get URL of provider authorization page
+%%
+get_authorize_url(Opts) ->
+ << "https://www.facebook.com/dialog/oauth", $?,
+ (cowboy_request:urlencode([
+ {client_id, key(client_id, Opts)},
+ {redirect_uri, key(callback_uri, Opts)},
+ {scope, key(scope, Opts)}
+ ]))/binary >>.
+
+%%
+%% exchange authorization code for auth token
+%%
+get_access_token(Code, Opts) ->
+ % NB: facebook uses GET
+ {ok, Auth} = cowboy_request:get_json(
+ <<"https://graph.facebook.com/oauth/access_token">>, [
+ {code, Code},
+ {client_id, key(client_id, Opts)},
+ {client_secret, key(client_secret, Opts)},
+ {redirect_uri, key(callback_uri, Opts)}
+ ]),
+ {ok, [
+ {access_token, key(<<"access_token">>, Auth)},
+ {token_type, <<"Bearer">>},
+ {expires, key(<<"expires">>, Auth)}
+ ]}.
+
+%%
+%% extract info from user profile
+%%
+get_user_profile(Auth, _Opts) ->
+ {ok, Profile} = cowboy_request:get_json(
+ <<"https://graph.facebook.com/me">>, [
+ {access_token, key(access_token, Auth)},
+ {fields, <<"id,email,name,picture,gender,locale">>}
+ ]),
+ {ok, [
+ {id, << "facebook:", (key(<<"id">>, Profile))/binary >>},
+ {provider, <<"facebook">>},
+ % {email, key(<<"email">>, Profile)},
+ {name, key(<<"name">>, Profile)},
+ {avatar, key(<<"url">>, key(<<"data">>, key(<<"picture">>, Profile)))},
+ {gender, key(<<"gender">>, Profile)},
+ {locale, key(<<"locale">>, Profile)}
+ ]}.
+
+%%
+%%------------------------------------------------------------------------------
+%% Helpers
+%%------------------------------------------------------------------------------
+%%
+
+key(Key, List) ->
+ {_, Value} = lists:keyfind(Key, 1, List),
+ Value.

0 comments on commit 1ab3941

Please sign in to comment.
Something went wrong with that request. Please try again.