Add support for multi-host to the authentication module.

main
absc 2024-09-15 13:23:38 +00:00
parent f51847fe97
commit b1c4ab8e16
1 changed files with 24 additions and 14 deletions

View File

@ -23,7 +23,7 @@ Here lives all the functions for the APIs needed to handle users authentication.
-include_lib("dudeswave_backend/include/defines.hrl"). -include_lib("dudeswave_backend/include/defines.hrl").
-include_lib("storage/include/storage.hrl"). -include_lib("storage/include/storage.hrl").
-export([authenticate/3, logout/2]). -export([authenticate/4, logout/3]).
-doc """ -doc """
Verify a session with an existing cookie. Verify a session with an existing cookie.
@ -31,9 +31,10 @@ Verify a session with an existing cookie.
Spec: Spec:
``` ```
-spec authenticate(Type, User, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when -spec authenticate(Type, User, Host, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
Type :: cookie | password, Type :: cookie | password,
User :: binary(), User :: binary(),
Host :: binary(),
Auth :: {cookie, binary()} | {password, binary()}, Auth :: {cookie, binary()} | {password, binary()},
Cookie :: binary(), Cookie :: binary(),
Validity :: pos_integer(), Validity :: pos_integer(),
@ -46,15 +47,18 @@ after authenticating with `Password`.
If `Cookie` is valid, the function returns `true`. If the authentication is denied If `Cookie` is valid, the function returns `true`. If the authentication is denied
returns `false` returns `false`
""". """.
-spec authenticate(Type, User, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when -spec authenticate(Type, User, Host, Auth) -> true | false | {true, Cookie, Validity} | {error, Reason} when
Type :: cookie | password, Type :: cookie | password,
User :: binary(), User :: binary(),
Host :: binary(),
Auth :: {cookie, binary()} | {password, binary()}, Auth :: {cookie, binary()} | {password, binary()},
Cookie :: binary(), Cookie :: binary(),
Validity :: pos_integer(), Validity :: pos_integer(),
Reason :: term(). Reason :: term().
authenticate(cookie, User, Cookie) -> authenticate(cookie, User, Host, Cookie) ->
ComplUser = <<User/binary, "@", Host/binary>>,
case storage:read(?COOKIESBUCK, Cookie) of case storage:read(?COOKIESBUCK, Cookie) of
{ok, [R]} -> {ok, [R]} ->
CurTime = calendar:now_to_universal_time(erlang:timestamp()), CurTime = calendar:now_to_universal_time(erlang:timestamp()),
@ -64,7 +68,7 @@ authenticate(cookie, User, Cookie) ->
if if
CookieTime >= CurTime -> CookieTime >= CurTime ->
if if
User =:= CookieUser -> true; ComplUser =:= CookieUser -> true;
true -> false true -> false
end; end;
true -> false true -> false
@ -73,8 +77,10 @@ authenticate(cookie, User, Cookie) ->
{error, _} -> {error, service_unavailable} {error, _} -> {error, service_unavailable}
end; end;
authenticate(password, User, Password) -> authenticate(password, User, Host, Password) ->
case storage:read(?USERSBUCK, User) of ComplUser = <<User/binary, "@", Host/binary>>,
case storage:read(?USERSBUCK, ComplUser) of
{ok, [R]} -> {ok, [R]} ->
Validity = case application:get_env(cookie_validity) of Validity = case application:get_env(cookie_validity) of
{ok, Value} -> {ok, Value} ->
@ -83,8 +89,8 @@ authenticate(password, User, Password) ->
erlang:system_time(seconds) + ?DEFVALIDITY * 86400 erlang:system_time(seconds) + ?DEFVALIDITY * 86400
end, end,
{hash, Hash} = proplists:lookup(hash, R#object.metadata), {hash, Hash} = proplists:lookup(hash, R#object.value),
{salt, Salt} = proplists:lookup(salt, R#object.metadata), {salt, Salt} = proplists:lookup(salt, R#object.value),
{approved, Appr} = proplists:lookup(approved, R#object.metadata), {approved, Appr} = proplists:lookup(approved, R#object.metadata),
Auth = crypto:hash(sha256, <<Password/binary, Salt/binary>>), Auth = crypto:hash(sha256, <<Password/binary, Salt/binary>>),
@ -94,7 +100,7 @@ authenticate(password, User, Password) ->
Auth =:= Hash -> Auth =:= Hash ->
Cookie = base64:encode(rand:bytes(64)), Cookie = base64:encode(rand:bytes(64)),
case storage:write(?COOKIESBUCK, <<Cookie/binary>>, case storage:write(?COOKIESBUCK, <<Cookie/binary>>,
Validity, [{user, User}]) of Validity, [{user, ComplUser}]) of
ok -> {true, Cookie, Validity}; ok -> {true, Cookie, Validity};
{error, Reason} -> {error, Reason} {error, Reason} -> {error, Reason}
end; end;
@ -110,23 +116,27 @@ Close an existing session
Spec: Spec:
``` ```
-spec logout(User, Cookie) -> ok | {error, Reason} when -spec logout(User, Host, Cookie) -> ok | {error, Reason} when
User :: binary(), User :: binary(),
Host :: binary(),
Cookie :: binary(), Cookie :: binary(),
Reason :: term(). Reason :: term().
``` ```
Invalidate and delete `Cookie` associated with `User` from the system. Invalidate and delete `Cookie` associated with `User` from the system.
""". """.
-spec logout(User, Cookie) -> ok | {error, Reason} when -spec logout(User, Host, Cookie) -> ok | {error, Reason} when
User :: binary(), User :: binary(),
Host :: binary(),
Cookie :: binary(), Cookie :: binary(),
Reason :: term(). Reason :: term().
logout(User, Cookie) -> logout(User, Host, Cookie) ->
ComplUser = <<User/binary, "@", Host/binary>>,
case storage:read(?COOKIESBUCK, Cookie) of case storage:read(?COOKIESBUCK, Cookie) of
{ok, [R]} -> {ok, [R]} ->
{user, User} = proplists:lookup(user, R#object.metadata), {user, ComplUser} = proplists:lookup(user, R#object.metadata),
storage:delete(?COOKIESBUCK, Cookie); storage:delete(?COOKIESBUCK, Cookie);
{ok, []} -> {ok, []} ->
{error, not_found}; {error, not_found};