Stage 2
This commit is contained in:
88
src/logic/logic_auth.erl
Normal file
88
src/logic/logic_auth.erl
Normal file
@@ -0,0 +1,88 @@
|
||||
-module(logic_auth).
|
||||
|
||||
-export([hash_password/1, verify_password/2]).
|
||||
-export([generate_jwt/2, verify_jwt/1, extract_claims/1]).
|
||||
-export([generate_refresh_token/1]).
|
||||
|
||||
%% ============ Argon2 хеширование ============
|
||||
hash_password(Password) when is_binary(Password) ->
|
||||
argon2:hash(Password).
|
||||
|
||||
verify_password(Password, Hash) when is_binary(Password), is_binary(Hash) ->
|
||||
argon2:verify(Password, Hash).
|
||||
|
||||
%% ============ JWT с использованием jose ============
|
||||
get_jwt_secret() ->
|
||||
<<"my-super-secret-key-for-jwt-32-bytes!">>.
|
||||
|
||||
get_jwk() ->
|
||||
jose_jwk:from_oct(get_jwt_secret()).
|
||||
|
||||
generate_jwt(UserId, Role) ->
|
||||
JWK = get_jwk(),
|
||||
|
||||
ExpTime = os:system_time(seconds) + 86400, % 24 часа
|
||||
Claims = #{
|
||||
<<"user_id">> => UserId,
|
||||
<<"role">> => Role,
|
||||
<<"exp">> => ExpTime,
|
||||
<<"iat">> => os:system_time(seconds)
|
||||
},
|
||||
|
||||
JWT = jose_jwt:sign(JWK, #{<<"alg">> => <<"HS256">>}, Claims),
|
||||
{_, Token} = jose_jws:compact(JWT),
|
||||
Token.
|
||||
|
||||
verify_jwt(Token) when is_binary(Token) ->
|
||||
try
|
||||
JWK = get_jwk(),
|
||||
case jose_jwt:verify(JWK, Token) of
|
||||
{true, {jose_jwt, Claims}, _} ->
|
||||
case check_expiry(Claims) of
|
||||
true -> {ok, Claims};
|
||||
false -> {error, expired}
|
||||
end;
|
||||
{true, Claims, _} when is_map(Claims) ->
|
||||
case check_expiry(Claims) of
|
||||
true -> {ok, Claims};
|
||||
false -> {error, expired}
|
||||
end;
|
||||
{false, _, _} ->
|
||||
{error, invalid_signature}
|
||||
end
|
||||
catch
|
||||
_:_ -> {error, invalid_token}
|
||||
end.
|
||||
|
||||
extract_claims(Token) when is_binary(Token) ->
|
||||
try
|
||||
JWK = get_jwk(),
|
||||
case jose_jwt:verify(JWK, Token) of
|
||||
{true, {jose_jwt, Claims}, _} ->
|
||||
{ok, Claims};
|
||||
{true, Claims, _} when is_map(Claims) ->
|
||||
{ok, Claims};
|
||||
_ ->
|
||||
{error, invalid_token}
|
||||
end
|
||||
catch
|
||||
_:_ -> {error, invalid_token}
|
||||
end.
|
||||
|
||||
check_expiry(Claims) ->
|
||||
case maps:find(<<"exp">>, Claims) of
|
||||
{ok, Exp} when is_integer(Exp) ->
|
||||
Exp > os:system_time(seconds);
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
%% ============ Refresh Token ============
|
||||
generate_refresh_token(_UserId) ->
|
||||
Token = base64:encode(crypto:strong_rand_bytes(32)),
|
||||
ExpiresAt = calendar:universal_time_to_local_time(
|
||||
calendar:gregorian_seconds_to_datetime(
|
||||
calendar:datetime_to_gregorian_seconds(calendar:universal_time()) + 30 * 86400
|
||||
)
|
||||
),
|
||||
{Token, ExpiresAt}.
|
||||
Reference in New Issue
Block a user