Packages

OAuth2 endpoints for cowboy and snarl.

Current section

Files

Jump to
cowboy_oauth src cowboy_oauth_token.erl
Raw

src/cowboy_oauth_token.erl

-module(cowboy_oauth_token).
-export([init/3]).
-export([handle/2]).
-export([terminate/3]).
-ignore_xref([init/3]).
-ignore_xref([handle/2]).
-ignore_xref([terminate/3]).
-record(token_req, {
grant_type,
code,
client_id,
client_secret,
redirect_uri,
username,
password,
otp,
refresh_token,
scope,
payload
}).
init(_Transport, Req, []) ->
{ok, Req, undefined}.
terminate(_Reason, _Req, _State) ->
ok.
handle(Req, State) ->
{ok, Req3} = case cowboy_req:method(Req) of
{<<"POST">>, Req2} ->
do_post(Req2);
{_, Req2} ->
cowboy_req:reply(405, Req2)
end,
{ok, Req3, State}.
do_post(Req) ->
{ok, PostVals, Req2} = cowboy_req:body_qs(Req),
do_vals(PostVals, Req2).
do_vals(Vals, Req) ->
GrantType = cowboy_oauth:decode_grant_type(
proplists:get_value(<<"grant_type">>, Vals)),
Code = proplists:get_value(<<"code">>, Vals),
RedirectURI = proplists:get_value(<<"redirect_uri">>, Vals),
ClientID = proplists:get_value(<<"client_id">>, Vals),
ClientSecret = proplists:get_value(<<"client_secret">>, Vals),
%% Those are only used for the 4.3.2 Password grand
Username = proplists:get_value(<<"username">>, Vals),
Password = proplists:get_value(<<"password">>, Vals),
OTP = proplists:get_value(<<"fifo_otp">>, Vals),
Scope = proplists:get_value(<<"scope">>, Vals),
%% Used for 6 - refresh access tokens
RefreshToken = proplists:get_value(<<"refresh_token">>, Vals),
TokenReq = #token_req{
grant_type = GrantType,
code = Code,
redirect_uri = RedirectURI,
client_id = ClientID,
client_secret = ClientSecret,
username = Username,
password = Password,
otp = OTP,
scope = Scope,
refresh_token = RefreshToken
},
do_basic_auth(TokenReq, Req).
do_basic_auth(TokenReq, Req) ->
case cowboy_req:parse_header(<<"authorization">>, Req) of
{<<"basic">>, {ClientID, ClientSecret}} ->
TokenReq1 = TokenReq#token_req{client_id = ClientID,
client_secret = ClientSecret},
do_request(TokenReq1, Req);
_ ->
do_request(TokenReq, Req)
end.
do_request(TokenReq = #token_req{grant_type = authorization_code}, Req) ->
do_authorization_code(TokenReq, Req);
%% 4.3.2
do_request(TokenReq = #token_req{grant_type = password}, Req) ->
do_password(TokenReq, Req);
do_request(TokenReq = #token_req{grant_type = client_credentials}, Req) ->
do_client_credentials(TokenReq, Req);
do_request(TokenReq = #token_req{grant_type = refresh_token}, Req) ->
do_refresh_token(TokenReq, Req);
do_request(_, Req) ->
cowboy_oauth:json_error_response(invalid_request, Req).
do_authorization_code(#token_req{code = Code, client_id = ClientId,
client_secret = ClientSecret,
redirect_uri = RedirectURI},
Req) when is_binary(Code),
is_binary(ClientId),
is_binary(ClientSecret) ->
case ls_oauth:authorize_code_grant(
{ClientId, ClientSecret}, Code, RedirectURI) of
{ok, Authorization} ->
{ok, Response} = ls_oauth:issue_token_and_refresh(Authorization),
{ok, AccessToken} = oauth2_response:access_token(Response),
{ok, Type} = oauth2_response:token_type(Response),
{ok, Expires} = oauth2_response:expires_in(Response),
{ok, RefreshToken} = oauth2_response:refresh_token(Response),
{ok, Scope} = oauth2_response:scope(Response),
cowboy_oauth:access_refresh_token_response(
AccessToken, Type, Expires, RefreshToken, Scope, Req);
{error, Error} ->
cowboy_oauth:json_error_response(Error, Req)
end;
do_authorization_code(_, Req) ->
cowboy_oauth:json_error_response(invalid_request, Req).
%% 4.3.2
do_password(#token_req{username = Username, password = Password, scope = Scope,
otp = OTP},
Req)
when is_binary(Username),
is_binary(Password),
is_binary(OTP) ->
do_password({Username, Password, OTP}, Scope, Req);
do_password(#token_req{username = Username, password = Password, scope = Scope},
Req)
when is_binary(Username),
is_binary(Password) ->
do_password({Username, Password}, Scope, Req);
do_password(_, Req) ->
cowboy_oauth:json_error_response(invalid_request, Req).
do_password(User, Scope, Req) ->
case ls_oauth:authorize_password(User, Scope) of
{ok, Authorization} ->
{ok, Response} = ls_oauth:issue_token(Authorization),
{ok, AccessToken} = oauth2_response:access_token(Response),
{ok, Type} = oauth2_response:token_type(Response),
{ok, Expires} = oauth2_response:expires_in(Response),
{ok, VerifiedScope} = oauth2_response:scope(Response),
cowboy_oauth:access_token_response(
AccessToken, Type, Expires, VerifiedScope, Req);
{error, Error} ->
cowboy_oauth:json_error_response(Error, Req)
end.
do_client_credentials(#token_req{client_id = ClientId,
client_secret = ClientSecret,
scope = Scope}, Req)
when is_binary(ClientId),
is_binary(ClientSecret) ->
case ls_oauth:authorize_client_credentials(
{ClientId, ClientSecret}, Scope) of
{ok, Authorization} ->
{ok, Response} = ls_oauth:issue_token(Authorization),
{ok, Token} = oauth2_response:access_token(Response),
{ok, Type} = oauth2_response:token_type(Response),
{ok, Expires} = oauth2_response:expires_in(Response),
{ok, Scope} = oauth2_response:scope(Response),
cowboy_oauth:access_token_response(
Token, Type, Expires, Scope, Req);
{error, Error} ->
cowboy_oauth:json_error_response(Error, Req)
end;
do_client_credentials(_, Req) ->
cowboy_oauth:json_error_response(invalid_request, Req).
do_refresh_token(#token_req{refresh_token = RefreshToken, client_id = ClientId,
client_secret = ClientSecret, scope = Scope}, Req)
when is_binary(ClientId),
is_binary(ClientSecret),
is_binary(RefreshToken) ->
case ls_oauth:refresh_access_token({ClientId, ClientSecret}, RefreshToken,
Scope) of
{ok, Response} ->
{ok, AccessToken} = oauth2_response:access_token(Response),
{ok, Type} = oauth2_response:token_type(Response),
{ok, Expires} = oauth2_response:expires_in(Response),
{ok, ResponseScope} = oauth2_response:scope(Response),
cowboy_oauth:access_token_response(
AccessToken, Type, Expires, ResponseScope, Req);
{error, Error} ->
cowboy_oauth:json_error_response(Error, Req)
end.