Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
Refactor into more modules.
  • Loading branch information
Tim Fletcher committed Aug 24, 2008
1 parent 1427f47 commit 93cd16b406046ab5311131a8243a0d434ddd72ff
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 98 deletions.
@@ -1,15 +1,15 @@
-define(plaintext_signature_test(ConsumerSecret, TokenSecret, ExpectedSignature),
?_assertEqual(ExpectedSignature, oauth_request:plaintext_signature(ConsumerSecret, TokenSecret))
?_assertEqual(ExpectedSignature, oauth_plaintext:signature(ConsumerSecret, TokenSecret))
).

-define(hmac_sha1_normalize_test(ExpectedString, Params),
?_assertEqual(ExpectedString, oauth_request:hmac_sha1_normalize(Params))
-define(hmac_normalize_test(ExpectedString, Params),
?_assertEqual(ExpectedString, oauth_hmac:normalize(Params))
).

-define(hmac_sha1_base_string_test(Method, URL, Params, Expected), fun() ->
?assertEqual(string:join(Expected, ""), oauth_request:hmac_sha1_base_string(Method, URL, Params))
-define(hmac_base_string_test(Method, URL, Params, Expected), fun() ->
?assertEqual(string:join(Expected, ""), oauth_hmac:base_string(Method, URL, Params))
end).

-define(hmac_sha1_signature_test(ExpectedSignature, ConsumerSecret, TokenSecret, BaseString), fun() ->
?assertEqual(ExpectedSignature, oauth_request:hmac_sha1_signature(string:join(BaseString, []), ConsumerSecret, TokenSecret))
-define(hmac_signature_test(ExpectedSignature, ConsumerSecret, TokenSecret, BaseString), fun() ->
?assertEqual(ExpectedSignature, oauth_hmac:signature(string:join(BaseString, []), ConsumerSecret, TokenSecret))
end).
@@ -5,7 +5,6 @@
-export([tokens/1]).
-export([token/1]).
-export([token_secret/1]).
-export([params_from_string/1]).


get(URL, Consumer) ->
@@ -37,7 +36,7 @@ post(URL, Consumer, Tokens, Params) when is_list(Tokens) ->
http:request(post, Request, [], []).

tokens({ok, {_,_,Data}}) ->
{ok, {oauth_tokens, params_from_string(Data)}};
{ok, {oauth_tokens, oauth_params:from_string(Data)}};
tokens(Term) ->
Term.

@@ -46,29 +45,3 @@ token({oauth_tokens, Tokens}) ->

token_secret({oauth_tokens, Tokens}) ->
proplists:get_value(oauth_token_secret, Tokens).

params_from_string(Data) ->
lists:map(fun param_from_string/1, explode($&, Data)).

param_from_string(Data) when is_list(Data) ->
param_from_string(break_at($=, Data));
param_from_string({K, V}) ->
{list_to_atom(oauth_util:percent_decode(K)), oauth_util:percent_decode(V)}.

explode(_Sep, []) ->
[];
explode(Sep, Chars) ->
explode(Sep, break_at(Sep, Chars), []).

explode(_Sep, {Param, []}, Params) ->
lists:reverse([Param|Params]);
explode(Sep, {Param, Etc}, Params) ->
explode(Sep, break_at(Sep, Etc), [Param|Params]).

break_at(Sep, Chars) ->
case lists:splitwith(fun(C) -> C =/= Sep end, Chars) of
Result={_, []} ->
Result;
{Before, [Sep|After]} ->
{Before, After}
end.
@@ -0,0 +1,24 @@
-module(oauth_hmac).

-export([signature/3]).
-export([base_string/3]).
-export([normalize/1]). % for testing


signature(BaseString, ConsumerSecret, TokenSecret) ->
b64(crypto:sha_mac(key(ConsumerSecret, TokenSecret), BaseString)).

base_string(MethodString, URL, Params) ->
string:join(lists:map(fun fmt:percent_encode/1, [MethodString, URL, normalize(Params)]), "&").

normalize(Params) ->
oauth_params:to_string(sort(Params)).

sort(Params) ->
lists:sort(fun({K,X},{K,Y}) -> X < Y; ({A,_},{B,_}) -> A < B end, Params).

key(ConsumerSecret, TokenSecret) ->
fmt:sprintf("%s&%s", [fmt:percent_encode(ConsumerSecret), fmt:percent_encode(TokenSecret)]).

b64(Data) ->
base64:encode_to_string(Data).
@@ -0,0 +1,44 @@
-module(oauth_params).

-export([to_string/1]).
-export([to_header_string/1]).
-export([from_string/1]).

-import(lists, [map/2]).


to_string(Params) when is_list(Params) ->
string:join(map(fun to_string/1, Params), "&");
to_string({K,V}) ->
fmt:sprintf("%s=%s", [fmt:percent_encode(K), fmt:percent_encode(V)]).

to_header_string(Params) when is_list(Params) ->
string:join(map(fun to_header_string/1, Params), ",");
to_header_string({K,V}) ->
fmt:sprintf("%s=\"%s\"", [fmt:percent_encode(K), fmt:percent_encode(V)]).

from_string(Data) ->
map(fun param_from_string/1, explode($&, Data)).

param_from_string(Data) when is_list(Data) ->
param_from_string(break_at($=, Data));
param_from_string({K, V}) ->
{list_to_atom(oauth_util:percent_decode(K)), oauth_util:percent_decode(V)}.

explode(_Sep, []) ->
[];
explode(Sep, Chars) ->
explode(Sep, break_at(Sep, Chars), []).

explode(_Sep, {Param, []}, Params) ->
lists:reverse([Param|Params]);
explode(Sep, {Param, Etc}, Params) ->
explode(Sep, break_at(Sep, Etc), [Param|Params]).

break_at(Sep, Chars) ->
case lists:splitwith(fun(C) -> C =/= Sep end, Chars) of
Result={_, []} ->
Result;
{Before, [Sep|After]} ->
{Before, After}
end.
@@ -0,0 +1,10 @@
-module(oauth_plaintext).

-export([signature/2]).


signature(ConsumerSecret, TokenSecret) ->
encode(fmt:sprintf("%s&%s", [encode(ConsumerSecret), encode(TokenSecret)])).

encode(String) ->
fmt:percent_encode(String).
@@ -4,28 +4,17 @@
-export([url/5]).
-export([header/6]).

% for testing:
-export([plaintext_signature/2]).
-export([hmac_sha1_signature/3]).
-export([hmac_sha1_base_string/3]).
-export([hmac_sha1_normalize/1]).
-export([params_to_header_string/1]).

-import(fmt, [sprintf/2, percent_encode/1]).
-import(lists, [map/2]).


params_string(Method, URL, ExtraParams, Consumer, Tokens) ->
SignedParams = params(Method, URL, ExtraParams, Consumer, Tokens),
params_to_string(SignedParams).
oauth_params:to_string(params(Method, URL, ExtraParams, Consumer, Tokens)).

url(Method, URL, ExtraParams, Consumer, Tokens) ->
SignedParams = params(Method, URL, ExtraParams, Consumer, Tokens),
sprintf("%s?%s", [URL, params_to_string(SignedParams)]).
fmt:sprintf("%s?%s", [URL, oauth_params:to_string(params(Method, URL, ExtraParams, Consumer, Tokens))]).

header(Realm, Method, URL, ExtraParams, Consumer, Tokens) ->
SignedParams = params(Method, URL, ExtraParams, Consumer, Tokens),
sprintf("Authorization: OAuth realm=\"%s\", %s", [Realm, params_to_header_string(SignedParams)]).
HeaderString = oauth_params:to_header_string(SignedParams),
fmt:sprintf("Authorization: OAuth realm=\"%s\", %s", [Realm, HeaderString]).

params(Method, URL, ExtraParams, Consumer, Tokens) ->
{Params, TokenSecret} = oauth_params(Tokens, Consumer, ExtraParams),
@@ -60,39 +49,11 @@ signature(Method, URL, Params, Consumer, TokenSecret) ->
ConsumerSecret = oauth_consumer:secret(Consumer),
case signature_method(Params) of
"PLAINTEXT" ->
plaintext_signature(ConsumerSecret, TokenSecret);
oauth_plaintext:signature(ConsumerSecret, TokenSecret);
"HMAC-SHA1" ->
MethodString = string:to_upper(atom_to_list(Method)),
BaseString = hmac_sha1_base_string(MethodString, URL, Params),
hmac_sha1_signature(BaseString, ConsumerSecret, TokenSecret)
BaseString = oauth_hmac:base_string(string:to_upper(atom_to_list(Method)), URL, Params),
oauth_hmac:signature(BaseString, ConsumerSecret, TokenSecret)
end.

signature_method(Params) ->
proplists:get_value(oauth_signature_method, Params).

plaintext_signature(ConsumerSecret, TokenSecret) ->
percent_encode(sprintf("%s&%s", [percent_encode(ConsumerSecret), percent_encode(TokenSecret)])).

hmac_sha1_signature(BaseString, ConsumerSecret, TokenSecret) ->
base64:encode_to_string(crypto:sha_mac(hmac_sha1_key(ConsumerSecret, TokenSecret), BaseString)).

hmac_sha1_key(ConsumerSecret, TokenSecret) ->
sprintf("%s&%s", [percent_encode(ConsumerSecret), percent_encode(TokenSecret)]).

hmac_sha1_base_string(MethodString, URL, Params) ->
string:join(map(fun fmt:percent_encode/1, [MethodString, URL, hmac_sha1_normalize(Params)]), "&").

hmac_sha1_normalize(Params) ->
params_to_string(lists:sort(fun({K,X},{K,Y}) -> X < Y; ({A,_},{B,_}) -> A < B end, Params)).

params_to_string(Params) ->
string:join(map(fun param_to_string/1, Params), "&").

param_to_string({K,V}) ->
sprintf("%s=%s", [percent_encode(K), percent_encode(V)]).

params_to_header_string(Params) ->
string:join(map(fun param_to_header_string/1, Params), ",").

param_to_header_string({K,V}) ->
sprintf("%s=\"%s\"", [percent_encode(K), percent_encode(V)]).
@@ -20,7 +20,7 @@ test(Consumer, {ok, RequestTokenPair}) ->
test(Consumer, {ok, AccessTokenPair}, EchoParams) ->
EchoURL = "http://term.ie/oauth/example/echo_api.php",
{ok, {_,_,Data}} = tee(oauth:get(EchoURL, Consumer, AccessTokenPair, EchoParams)),
tee(lists:keysort(1, oauth:params_from_string(Data))).
tee(lists:keysort(1, oauth_params:from_string(Data))).

tee(X) ->
error_logger:info_msg("~p~n~n", [X]), X.
@@ -6,7 +6,7 @@

params_from_string_test_() ->
% cf. http://oauth.net/core/1.0/#response_parameters (5.3)
Params = oauth:params_from_string("oauth_token=ab3cd9j4ks73hf7g&oauth_token_secret=xyz4992k83j47x0b"), [
Params = oauth_params:from_string("oauth_token=ab3cd9j4ks73hf7g&oauth_token_secret=xyz4992k83j47x0b"), [
?_assertEqual("ab3cd9j4ks73hf7g", proplists:get_value(oauth_token, Params)),
?_assertEqual("xyz4992k83j47x0b", proplists:get_value(oauth_token_secret, Params))
].
@@ -15,7 +15,7 @@ params_to_header_string_test_() ->
% cf. http://oauth.net/core/1.0/#auth_header_authorization (5.4.1)
Params = [{oauth_consumer_key, "0685bd9184jfhq22"}, {oauth_token, "ad180jjd733klru7"}],
String = "oauth_consumer_key=\"0685bd9184jfhq22\",oauth_token=\"ad180jjd733klru7\"", [
?_assertEqual(String, oauth_request:params_to_header_string(Params))
?_assertEqual(String, oauth_params:to_header_string(Params))
].

plaintext_signature_test_() -> [
@@ -25,19 +25,19 @@ plaintext_signature_test_() -> [
?plaintext_signature_test("djr9rjt0jd78jf88", "", "djr9rjt0jd78jf88%26")
].

hmac_sha1_normalize_test_() -> [
hmac_normalize_test_() -> [
% cf. http://wiki.oauth.net/TestCases
?hmac_sha1_normalize_test("name=", [{name,undefined}]),
?hmac_sha1_normalize_test("a=b", [{a,b}]),
?hmac_sha1_normalize_test("a=b&c=d", [{a,b},{c,d}]),
?hmac_sha1_normalize_test("a=x%20y&a=x%21y", [{a,"x!y"},{a,"x y"}]),
?hmac_sha1_normalize_test("x=a&x%21y=a", [{"x!y",a},{x,a}])
?hmac_normalize_test("name=", [{name,undefined}]),
?hmac_normalize_test("a=b", [{a,b}]),
?hmac_normalize_test("a=b&c=d", [{a,b},{c,d}]),
?hmac_normalize_test("a=x%20y&a=x%21y", [{a,"x!y"},{a,"x y"}]),
?hmac_normalize_test("x=a&x%21y=a", [{"x!y",a},{x,a}])
].

hmac_sha1_base_string_test_() -> [
hmac_base_string_test_() -> [
% cf. http://wiki.oauth.net/TestCases
?hmac_sha1_base_string_test("GET", "http://example.com", [{n,v}], ["GET&http%3A%2F%2Fexample.com&n%3Dv"]),
?hmac_sha1_base_string_test("POST", "https://photos.example.net/request_token", [
?hmac_base_string_test("GET", "http://example.com", [{n,v}], ["GET&http%3A%2F%2Fexample.com&n%3Dv"]),
?hmac_base_string_test("POST", "https://photos.example.net/request_token", [
{oauth_version, "1.0"},
{oauth_consumer_key, "dpf43f3p2l4k3l03"},
{oauth_timestamp, "1191242090"},
@@ -48,7 +48,7 @@ hmac_sha1_base_string_test_() -> [
"%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method",
"%3DPLAINTEXT%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0"
]),
?hmac_sha1_base_string_test("GET", "http://photos.example.net/photos", [
?hmac_base_string_test("GET", "http://photos.example.net/photos", [
{file, "vacation.jpg"},
{size, "original"},
{oauth_version, "1.0"},
@@ -65,11 +65,11 @@ hmac_sha1_base_string_test_() -> [
])
].

hmac_sha1_signature_test_() -> [
hmac_signature_test_() -> [
% cf. http://wiki.oauth.net/TestCases
?hmac_sha1_signature_test("egQqG5AJep5sJ7anhXju1unge2I=", "cs", "", ["bs"]),
?hmac_sha1_signature_test("VZVjXceV7JgPq/dOTnNmEfO0Fv8=", "cs", "ts", ["bs"]),
?hmac_sha1_signature_test("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", "kd94hf93k423kf44", "pfkkdhi9sl3r4s00", [
?hmac_signature_test("egQqG5AJep5sJ7anhXju1unge2I=", "cs", "", ["bs"]),
?hmac_signature_test("VZVjXceV7JgPq/dOTnNmEfO0Fv8=", "cs", "ts", ["bs"]),
?hmac_signature_test("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", "kd94hf93k423kf44", "pfkkdhi9sl3r4s00", [
"GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26",
"oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26",
"oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26",

0 comments on commit 93cd16b

Please sign in to comment.