Skip to content

Commit

Permalink
Merge pull request #14 from ryanramage/hash-algorithm
Browse files Browse the repository at this point in the history
Support alternate hash algorithms
  • Loading branch information
jhs committed Jan 17, 2013
2 parents cbc3b0b + bc0b98d commit a8fa6a9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
1 change: 1 addition & 0 deletions etc/couchdb/default.d/browserid.ini
Expand Up @@ -5,6 +5,7 @@
enabled = false enabled = false
verify_url = https://verifier.login.persona.org/verify verify_url = https://verifier.login.persona.org/verify
audience = http://example.com audience = http://example.com
; hash_algorithm = <choose one of: none, hmac, gravatar. If hmac, set hash_secret below >
; hash_secret = <long crypto-random string, e.g. from https://api.wordpress.org/secret-key/1.1/> ; hash_secret = <long crypto-random string, e.g. from https://api.wordpress.org/secret-key/1.1/>


[httpd_global_handlers] [httpd_global_handlers]
Expand Down
4 changes: 4 additions & 0 deletions priv/main.js
Expand Up @@ -172,6 +172,10 @@ $.couch.browserid.login(function(ev, er, userCtx) {
widget.unbind('click'); widget.unbind('click');


var iurl = 'https://www.gravatar.com/avatar/' + Crypto.MD5($.trim(email).toLowerCase()) + "?s=32"; var iurl = 'https://www.gravatar.com/avatar/' + Crypto.MD5($.trim(email).toLowerCase()) + "?s=32";
if (email.indexOf('@') === -1) {
// it is probably already a gravatar hash
iurl = 'https://www.gravatar.com/avatar/' + email + "?s=32";
}
var gravatar_img = $("<img>").attr('src', iurl); var gravatar_img = $("<img>").attr('src', iurl);
gravatar_img.appendTo($("#browserid .picture")); gravatar_img.appendTo($("#browserid .picture"));


Expand Down
30 changes: 28 additions & 2 deletions src/couch_httpd_browserid.erl
Expand Up @@ -23,15 +23,22 @@
%% * Possibly auto-create user doc in browserid_authentication_handler/1 %% * Possibly auto-create user doc in browserid_authentication_handler/1
%% * Do something sane with providers other than browserid.org %% * Do something sane with providers other than browserid.org


% hash_if_required looks for hash_secret in browserid section of config % hash_if_required looks for hash_algorithm in browserid section of config
% if not found, default to hmac to keep backward compat.
hash_if_required(Email) -> ok
, Algorithm = couch_config:get("browserid", "hash_algorithm", "hmac")
, ?LOG_DEBUG("Algorithm chosen: ~s", [Algorithm])
, hash_if_required(Algorithm, Email).

% hash_if_required (hmac) looks for hash_secret in browserid section of config
% If it exist and isn't an empty string, uses it as hmac key according to code from % If it exist and isn't an empty string, uses it as hmac key according to code from
% http://stackoverflow.com/questions/4193543/erlang-calculating-hmac-sha1-example/4202361#4202361 % http://stackoverflow.com/questions/4193543/erlang-calculating-hmac-sha1-example/4202361#4202361
% If missing or empty (i.e. admin doesn't want to hash usernames), simply returns the argument % If missing or empty (i.e. admin doesn't want to hash usernames), simply returns the argument
% (this is the default) % (this is the default)
% If you use hash_secret, make sure the string is long enough and cryptographically random % If you use hash_secret, make sure the string is long enough and cryptographically random
% Tip: use one of the strings from https://api.wordpress.org/secret-key/1.1/ :) % Tip: use one of the strings from https://api.wordpress.org/secret-key/1.1/ :)


hash_if_required(Email) -> ok hash_if_required("hmac", Email) -> ok
, Hashkey = couch_config:get("browserid", "hash_secret", undefined) , Hashkey = couch_config:get("browserid", "hash_secret", undefined)
, case Hashkey , case Hashkey
of undefined -> ok of undefined -> ok
Expand All @@ -40,8 +47,27 @@ hash_if_required(Email) -> ok
, <<Mac:160/integer>> = crypto:sha_mac(?l2b(Key),Email) , <<Mac:160/integer>> = crypto:sha_mac(?l2b(Key),Email)
, ?l2b(lists:flatten(io_lib:format("~40.16.0b", [Mac]))) , ?l2b(lists:flatten(io_lib:format("~40.16.0b", [Mac])))
end end
;

% hash_if_required (gravatar) looks provides the same hasing as gravatar,
% and is based on the code from https://github.com/kanso/gravatar/blob/master/gravatar.js#L17
hash_if_required("gravatar", Email) -> ok
, Trim = re:replace(Email, "(^\\s+)|(\\s+$)", "", [global,{return,list}])
, Lower = string:to_lower(Trim)
, <<Md5:128/integer>> = crypto:md5(Lower)
, ?l2b(lists:flatten(io_lib:format("~32.16.0b", [Md5])))
;

hash_if_required("none", Email) -> Email;

% hash_if_required (_) returns the Email, and warns user.
hash_if_required(_, Email) -> ok
, Message = <<"No hash_algorithm specified. Not hashing email address.">>
, ?LOG_ERROR("~s", [Message])
, hash_if_required(none, Email)
. .



handle_id_req(#httpd{method='GET'}=Req) -> ok handle_id_req(#httpd{method='GET'}=Req) -> ok
, case code:priv_dir(browserid_couchdb) , case code:priv_dir(browserid_couchdb)
of {error, bad_name} -> ok of {error, bad_name} -> ok
Expand Down

0 comments on commit a8fa6a9

Please sign in to comment.