Skip to content

Commit

Permalink
Allow for direct verification.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxstr committed Jan 12, 2017
1 parent 308d2fc commit ecd0417
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
27 changes: 22 additions & 5 deletions src/openid.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,25 @@
%%% Created : 18 Sep 2009 by Brendon Hogger <[email protected]>
%%%-------------------------------------------------------------------
-module(openid).
-behavior(application).
-include("openid.hrl").

-export([discover/1, associate/1, authentication_url/3]).
% Library functions
-export([discover/1, associate/1, authentication_url/3, verify/1]).
% Application
-export([start/2, stop/1]).

-include("openid.hrl").
start(normal, _Args) ->
openid_srv:start_link().

stop(_State) ->
ok.

%% ------------------------------------------------------------
%% Verification
%% ------------------------------------------------------------
verify({UUID, ReturnTo, Fields}) ->
gen_server:call(openid_srv, {verify, UUID, ReturnTo, Fields}).

%% ------------------------------------------------------------
%% Discovery
Expand Down Expand Up @@ -195,8 +208,13 @@ unroll(Bin) when is_binary(Bin) ->
%% ------------------------------------------------------------

authentication_url(AuthReq, ReturnTo, Realm) ->

Assoc = AuthReq#openid_authreq.assoc,

AssocBits = case Assoc of
none -> [];
_ -> [{"openid.assoc_handle", Assoc#openid_assoc.handle}]
end,

IDBits = case AuthReq#openid_authreq.claimedID of
none -> [];
Expand All @@ -206,9 +224,8 @@ authentication_url(AuthReq, ReturnTo, Realm) ->

Params = [{"openid.ns", "http://specs.openid.net/auth/2.0"},
{"openid.mode", "checkid_setup"},
{"openid.assoc_handle", Assoc#openid_assoc.handle},
{"openid.return_to", ReturnTo},
{"openid.realm", Realm}] ++ IDBits,
{"openid.realm", Realm}] ++ IDBits ++ AssocBits,

QueryString = openid_pm:uri_encode(Params),

Expand Down
44 changes: 31 additions & 13 deletions src/openid_srv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
-include("openid.hrl").

%% API
-export([start_link/1]).
-export([start_link/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
Expand All @@ -32,11 +32,8 @@
-define(NONCE_TIMEOUT, 600).


%%====================================================================
%% API
%%====================================================================
start_link(Name) ->
gen_server:start_link({local, Name}, ?MODULE, [], []).
start_link() ->
gen_server:start_link({local, openid_srv}, ?MODULE, [], []).


%%====================================================================
Expand Down Expand Up @@ -186,12 +183,21 @@ verify_return(UUID, ReturnTo, Fields, State) ->
verify_discovered(UUID, Fields, State) ->
GivenHandle = ?GV("openid.assoc_handle", Fields),
case ets:lookup(State#state.pending, UUID) of
[] -> {error, "No pending login"};
[] ->
verify_claimed_id(none, none, Fields, State);
[{UUID, {AuthReq, #openid_assoc{handle=GivenHandle}=Assoc}}] ->
verify_claimed_id(AuthReq, Assoc, Fields, State);
_OtherAssoc -> {error, "Invalid association handle"}
end.

% This is the non-associated (direct verification path)
verify_claimed_id(none, Assoc, Fields, State) ->
case ?GVD("openid.claimed_id", Fields, none) of
none -> {error, "No claimed identifier"};
ClaimedID ->
verify_nonce(ClaimedID, Assoc, Fields, State)
end;
% This is verification through previous association
verify_claimed_id(AuthReq, Assoc, Fields, State) ->
case ?GVD("openid.claimed_id", Fields, none) of
none -> {error, "No claimed identifier"};
Expand Down Expand Up @@ -230,9 +236,9 @@ verify_nonce(ClaimedID, Assoc, Fields, State) ->
end.


verify_nonce2(ClaimedID, Nonce, Assoc, Fields, State) ->
verify_nonce2(ClaimedID, Nonce, Assoc, Fields, State) ->
case ets:lookup(State#state.nonces, Nonce) of
[] ->
[] ->
ets:insert(State#state.nonces, {Nonce, true}),
timer:send_after(?NONCE_TIMEOUT * 1000, {remove_nonce, Nonce}),
verify_signature(ClaimedID, Assoc, Fields);
Expand All @@ -244,20 +250,32 @@ verify_signature(ClaimedID, Assoc, Fields) ->
Invalidate = ?GVD("openid.invalidate_handle", Fields, false),
verify_signature(ClaimedID, Invalidate, Assoc, Fields).

verify_signature(_, _, none, _Fields) ->
{error, "Direct verification not implemented yet"};
% Direct verification
verify_signature(_ClaimedID, _Invalidate, none, Fields) ->
NewParams = proplists:delete("openid.mode", Fields) ++ [{"openid.mode", "check_authentication"}],
ClaimURL = ?GV("openid.op_endpoint", Fields),
BodyString = openid_pm:url_encode(NewParams),
{ok, "200", _Headers, Response} =
ibrowse:send_req(ClaimURL, [{"Content-Type", "application/x-www-form-urlencoded"}], post, BodyString),
TokenizedResponse = string:tokens(Response, "\n"),
ResultPropList =
lists:map(fun(Tokenized) -> [H|[H2|_T]] = string:tokens(Tokenized, ":"), {H, H2} end, TokenizedResponse),
case ?GV("is_valid", ResultPropList) =:= "true" of
true -> {ok, ?GV("openid.claimed_id", Fields)};
false -> {error, "cannot verify"}
end;
verify_signature(_ClaimedID, false, #openid_assoc{}=Assoc, Fields) ->
KV = lists:flatten([[Key,$:,?GV("openid." ++ Key, Fields),$\n]
|| Key <- string:tokens(?GV("openid.signed", Fields), ",")]),
MAC = Assoc#openid_assoc.mac,
Sig = crypto:sha_mac(MAC, KV),
GivenSig = base64:decode(?GV("openid.sig", Fields)),

case Sig =:= GivenSig of
true -> {ok, ?GV("openid.claimed_id", Fields)};
false -> {error, "invalid signature"}
end;
verify_signature(_, _, _, _) ->
verify_signature(_, _, _, _) ->
{error, "Association invalidated, and direct verification not implemented yet"}.


Expand Down

0 comments on commit ecd0417

Please sign in to comment.