Permalink
Browse files

Merge pull request #6 from kivra/master

Update to kivra/oauth2 master
  • Loading branch information...
2 parents 331288f + 11b8595 commit e316f221419f288998bfa2b6d2a68ce3c6c5a05f @IvanMartinez IvanMartinez committed May 28, 2013
Showing with 75 additions and 166 deletions.
  1. +4 −0 README.md
  2. +1 −1 src/oauth2.app.src
  3. +27 −60 src/oauth2.erl
  4. +14 −7 src/oauth2_response.erl
  5. +6 −0 test/oauth2_response_tests.erl
  6. +23 −98 test/oauth2_tests.erl
View
@@ -7,6 +7,10 @@ accessing Oauth2 enabled services.
oauth2 is released under the terms of the [MIT](http://en.wikipedia.org/wiki/MIT_License) license
+Current stable version: [0.1.0](https://github.com/kivra/oauth2/tree/0.1.0)
+
+Current α alpha version: [0.2.0](https://github.com/kivra/oauth2)
+
copyright 2012-2013 Kivra
## tl;dr
View
@@ -27,7 +27,7 @@
{application, oauth2,
[
{description, "Erlang OAuth 2.0 implementation"},
- {vsn, "0.1.0"},
+ {vsn, "0.2.0"},
{registered, []},
{applications, [
kernel,
View
@@ -30,8 +30,6 @@
-export([authorize_password/3]).
-export([authorize_client_credentials/3]).
-export([authorize_code_grant/4]).
--export([issue_code_grant/3]).
--export([issue_code_grant/4]).
-export([issue_code_grant/5]).
-export([verify_access_token/1]).
-export([verify_access_code/1]).
@@ -89,70 +87,39 @@ authorize_password(Username, Password, Scope) ->
end.
%% @doc Issue a Code via Access Code Grant
--spec issue_code_grant(ClientId, ResOwner, Scope)
+-spec issue_code_grant(ClientId, RedirectionUri, Username, Password, Scope)
-> {ok, Identity, Response} | {error, Reason} when
- ClientId :: binary(),
- ResOwner :: term(),
- Scope :: scope(),
- Identity :: term(),
- Response :: oauth2_response:response(),
- Reason :: error().
-issue_code_grant(ClientId, ResOwner, Scope) ->
- case ?BACKEND:get_client_identity(ClientId) of
- {ok, Identity} ->
- TTL = oauth2_config:expiry_time(code_grant),
- Response = issue_code(Identity, Scope, ResOwner, TTL),
- {ok, Identity, Response};
- {error, _Reason} ->
- {error, invalid_client}
- end.
-
-%% @doc Issue a Code via Access Code Grant
--spec issue_code_grant(ClientId, RedirectionUri, ResOwner, Scope)
- -> {ok, Identity, Response} | {error, Reason} when
- ClientId :: binary(),
- RedirectionUri :: scope(),
- ResOwner :: term(),
- Scope :: scope(),
- Identity :: term(),
- Response :: oauth2_response:response(),
- Reason :: error().
-issue_code_grant(ClientId, RedirectionUri, ResOwner, Scope) ->
+ ClientId :: binary(),
+ RedirectionUri :: scope(),
+ Username :: binary(),
+ Password :: binary(),
+ Scope :: scope(),
+ Identity :: term(),
+ Response :: oauth2_response:response(),
+ Reason :: error().
+issue_code_grant(ClientId, RedirectionUri, Username, Password, Scope) ->
case ?BACKEND:get_client_identity(ClientId) of
{ok, Identity} ->
case ?BACKEND:verify_redirection_uri(Identity, RedirectionUri) of
ok ->
- TTL = oauth2_config:expiry_time(code_grant),
- Response = issue_code(Identity, Scope, ResOwner, TTL),
- {ok, Identity, Response};
- _ ->
- {error, access_denied}
- end;
- {error, _Reason} ->
- {error, invalid_client}
- end.
-
-%% @doc Issue a Code via Access Code Grant.
--spec issue_code_grant(ClientId, ClientSecret, RedirectionUri, ResOwner, Scope)
- -> {ok, Identity, Response} | {error, Reason} when
- ClientId :: binary(),
- ClientSecret :: binary(),
- RedirectionUri :: scope(),
- ResOwner :: term(),
- Scope :: scope(),
- Identity :: term(),
- Response :: oauth2_response:response(),
- Reason :: error().
-issue_code_grant(ClientId, ClientSecret, RedirectionUri, ResOwner, Scope) ->
- case ?BACKEND:authenticate_client(ClientId, ClientSecret) of
- {ok, Identity} ->
- case ?BACKEND:verify_redirection_uri(Identity, RedirectionUri) of
- ok ->
- TTL = oauth2_config:expiry_time(code_grant),
- Response = issue_code(Identity, Scope, ResOwner, TTL),
- {ok, Identity, Response};
+ case ?BACKEND:verify_client_scope(Identity, Scope) of
+ {ok, VerifiedScope} ->
+ case ?BACKEND:authenticate_username_password(
+ Username, Password) of
+ {ok, ResOwner} ->
+ TTL = oauth2_config:expiry_time(code_grant),
+ Response = issue_code(Identity,
+ VerifiedScope,
+ ResOwner, TTL),
+ {ok, Identity, Response};
+ {error, _Reason} ->
+ {error, access_denied}
+ end;
+ {error, _Reason} ->
+ {error, invalid_scope}
+ end;
_ ->
- {error, access_denied}
+ {error, unauthorized_client}
end;
{error, _Reason} ->
{error, unauthorized_client}
View
@@ -28,6 +28,7 @@
%% Length of binary data to use for token generation.
-define(TOKEN_LENGTH, 32).
+-define(TOKEN_TYPE, <<"bearer">>).
%%% API
-export([new/1]).
@@ -47,16 +48,18 @@
-export([expires_in/2]).
-export([scope/1]).
-export([scope/2]).
+-export([token_type/1]).
-export([to_proplist/1]).
+
-record(response, {
- access_token :: oauth2:token()
- ,access_code :: oauth2:token()
- ,expires_in :: oauth2:lifetime()
- ,resource_owner :: term()
- ,scope :: oauth2:scope()
- ,refresh_token :: oauth2:token()
- ,token_type = <<"bearer">> :: binary()
+ access_token :: oauth2:token()
+ ,access_code :: oauth2:token()
+ ,expires_in :: oauth2:lifetime()
+ ,resource_owner :: term()
+ ,scope :: oauth2:scope()
+ ,refresh_token :: oauth2:token()
+ ,token_type = ?TOKEN_TYPE :: binary()
}).
-type response() :: #response{}.
@@ -183,6 +186,10 @@ resource_owner(#response{resource_owner = ResOwner}) ->
resource_owner(Response, NewResOwner) ->
Response#response{resource_owner = NewResOwner}.
+-spec token_type(response()) -> {ok, binary()}.
+token_type(#response{}) ->
+ {ok, ?TOKEN_TYPE}.
+
-spec to_proplist(response()) -> oauth2:proplist(binary(), binary()).
to_proplist(Response) ->
Keys = lists:map(fun to_binary/1, record_info(fields, response)),
@@ -35,6 +35,8 @@
-define(RESOURCE_OWNER, <<"user">>).
-define(EXPIRY, 3600).
-define(SCOPE, <<"herp derp">>).
+-define(TOKEN_TYPE, <<"bearer">>).
+
%%%===================================================================
%%% Test cases
@@ -155,6 +157,10 @@ resource_owner_test() ->
oauth2_response:new(?ACCESS),
?RESOURCE_OWNER))).
+token_type_test() ->
+ ?assertEqual({ok, ?TOKEN_TYPE},
+ oauth2_response:token_type(oauth2_response:new(?ACCESS))).
+
to_proplist_test() ->
Response = oauth2_response:new(?ACCESS, ?EXPIRY, ?RESOURCE_OWNER, ?SCOPE, ?REFRESH),
?assertEqual([{<<"access_token">>, ?ACCESS},
View
@@ -182,57 +182,35 @@ bad_access_code_test_() ->
fun(_) ->
[
fun() ->
- {error, access_denied} = oauth2:issue_code_grant(
+ {error, unauthorized_client} = oauth2:issue_code_grant(
?CLIENT_ID,
- ?CLIENT_SECRET,
<<"http://in.val.id">>,
- ?RESOURCE_OWNER,
+ ?USER_NAME,
+ ?USER_PASSWORD,
?CLIENT_SCOPE),
{error, unauthorized_client} = oauth2:issue_code_grant(
<<"XoaUdYODRCMyLkdaKkqlmhsl9QQJ4b">>,
- ?CLIENT_SECRET,
?CLIENT_URI,
- ?RESOURCE_OWNER,
- ?CLIENT_SCOPE),
- ?_assertMatch({error, invalid_grant},
- oauth2:verify_access_code(<<"nonexistent_token">>))
- end
- ]
- end}.
-
-bad_access_code_icg3_test_() ->
- {setup,
- fun start/0,
- fun stop/1,
- fun(_) ->
- [
- fun() ->
- {error, invalid_client} = oauth2:issue_code_grant(
- <<"XoaUdYODRCMyLkdaKkqlmhsl9QQJ4b">>,
- ?RESOURCE_OWNER,
+ ?USER_NAME,
+ ?USER_PASSWORD,
?CLIENT_SCOPE),
- ?_assertMatch({error, invalid_grant},
- oauth2:verify_access_code(<<"nonexistent_token">>))
- end
- ]
- end}.
-
-bad_access_code_icg4_test_() ->
- {setup,
- fun start/0,
- fun stop/1,
- fun(_) ->
- [
- fun() ->
+ {error, invalid_scope} = oauth2:issue_code_grant(
+ ?CLIENT_ID,
+ ?CLIENT_URI,
+ ?USER_NAME,
+ ?USER_PASSWORD,
+ <<"bad_scope">>),
{error, access_denied} = oauth2:issue_code_grant(
?CLIENT_ID,
- <<"http://in.val.id">>,
- ?RESOURCE_OWNER,
+ ?CLIENT_URI,
+ <<"herp">>,
+ <<"herp">>,
?CLIENT_SCOPE),
- {error, invalid_client} = oauth2:issue_code_grant(
- <<"XoaUdYODRCMyLkdaKkqlmhsl9QQJ4b">>,
+ {error, access_denied} = oauth2:issue_code_grant(
+ ?CLIENT_ID,
?CLIENT_URI,
- ?RESOURCE_OWNER,
+ <<"derp">>,
+ <<"derp">>,
?CLIENT_SCOPE),
?_assertMatch({error, invalid_grant},
oauth2:verify_access_code(<<"nonexistent_token">>))
@@ -249,65 +227,12 @@ verify_access_code_test_() ->
fun() ->
{ok, _, Response} = oauth2:issue_code_grant(
?CLIENT_ID,
- ?CLIENT_SECRET,
- ?CLIENT_URI,
- ?RESOURCE_OWNER,
- ?CLIENT_SCOPE),
- {ok, Code} = oauth2_response:access_code(Response),
- ?assertMatch({ok, ?RESOURCE_OWNER},
- oauth2_response:resource_owner(Response)),
- ?assertMatch({ok, _}, oauth2:verify_access_code(Code)),
- {ok, _, Response2} = oauth2:authorize_code_grant(
- ?CLIENT_ID,
- ?CLIENT_SECRET,
- Code,
- ?CLIENT_URI),
- {ok, Token} = oauth2_response:access_token(Response2),
- ?assertMatch({ok, _}, oauth2:verify_access_token(Token))
- end
- ]
- end}.
-
-verify_access_code_icg3_test_() ->
- {setup,
- fun start/0,
- fun stop/1,
- fun(_) ->
- [
- fun() ->
- {ok, _, Response} = oauth2:issue_code_grant(
- ?CLIENT_ID,
- ?RESOURCE_OWNER,
- ?CLIENT_SCOPE),
- {ok, Code} = oauth2_response:access_code(Response),
- ?assertMatch({ok, ?RESOURCE_OWNER},
- oauth2_response:resource_owner(Response)),
- ?assertMatch({ok, _}, oauth2:verify_access_code(Code)),
- {ok, _, Response2} = oauth2:authorize_code_grant(
- ?CLIENT_ID,
- ?CLIENT_SECRET,
- Code,
- ?CLIENT_URI),
- {ok, Token} = oauth2_response:access_token(Response2),
- ?assertMatch({ok, _}, oauth2:verify_access_token(Token))
- end
- ]
- end}.
-
-verify_access_code_icg4_test_() ->
- {setup,
- fun start/0,
- fun stop/1,
- fun(_) ->
- [
- fun() ->
- {ok, _, Response} = oauth2:issue_code_grant(
- ?CLIENT_ID,
?CLIENT_URI,
- ?RESOURCE_OWNER,
+ ?USER_NAME,
+ ?USER_PASSWORD,
?CLIENT_SCOPE),
{ok, Code} = oauth2_response:access_code(Response),
- ?assertMatch({ok, ?RESOURCE_OWNER},
+ ?assertMatch({ok, {user, 31337}},
oauth2_response:resource_owner(Response)),
?assertMatch({ok, _}, oauth2:verify_access_code(Code)),
{ok, _, Response2} = oauth2:authorize_code_grant(
@@ -330,9 +255,9 @@ verify_refresh_token_test_() ->
fun() ->
{ok, _, Response} = oauth2:issue_code_grant(
?CLIENT_ID,
- ?CLIENT_SECRET,
?CLIENT_URI,
- ?RESOURCE_OWNER,
+ ?USER_NAME,
+ ?USER_PASSWORD,
?CLIENT_SCOPE),
{ok, Code} = oauth2_response:access_code(Response),
{ok, _, Response2} = oauth2:authorize_code_grant(

0 comments on commit e316f22

Please sign in to comment.