Реализовать кластер-безопасные admin refresh-сессии (фаза 1, #23).
Единая auth_session с refresh JWT, rotation и reuse detection; CI/CD временно на workflow_dispatch. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
-module(core_auth_session_tests).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-include("records.hrl").
|
||||
|
||||
-define(ADMIN_JWT_SECRET, <<"test-admin-secret-key-32-b">>).
|
||||
|
||||
setup() ->
|
||||
mnesia:start(),
|
||||
catch ets:new(eventhub_counters, [named_table, public, set, {write_concurrency, true}]),
|
||||
mnesia:create_table(auth_session, [
|
||||
{attributes, record_info(fields, auth_session)},
|
||||
{ram_copies, [node()]}
|
||||
]),
|
||||
mnesia:add_table_index(auth_session, #auth_session.family_id),
|
||||
mnesia:add_table_index(auth_session, #auth_session.subject_id),
|
||||
application:set_env(eventhub, admin_jwt_secret, ?ADMIN_JWT_SECRET),
|
||||
{ok, _} = application:ensure_all_started(jose),
|
||||
ok.
|
||||
|
||||
cleanup(_) ->
|
||||
mnesia:delete_table(auth_session),
|
||||
catch ets:delete(eventhub_counters),
|
||||
application:unset_env(eventhub, admin_jwt_secret),
|
||||
application:stop(jose),
|
||||
mnesia:stop(),
|
||||
ok.
|
||||
|
||||
core_auth_session_test_() ->
|
||||
{foreach, fun setup/0, fun cleanup/1, [
|
||||
{"Create session", fun test_create/0},
|
||||
{"Rotate session updates jti", fun test_rotate/0},
|
||||
{"Reuse detection", fun test_reuse/0},
|
||||
{"Revoke family", fun test_revoke_family/0}
|
||||
]}.
|
||||
|
||||
test_create() ->
|
||||
{ok, Session} = core_auth_session:create(<<"admin1">>, admin, <<"admin">>),
|
||||
?assertEqual(<<"admin1">>, Session#auth_session.subject_id),
|
||||
?assertEqual(admin, Session#auth_session.subject_type),
|
||||
?assertEqual(false, Session#auth_session.revoked),
|
||||
{ok, Loaded} = core_auth_session:get(Session#auth_session.session_id),
|
||||
?assertEqual(Session#auth_session.session_id, Loaded#auth_session.session_id).
|
||||
|
||||
test_rotate() ->
|
||||
{ok, Session} = core_auth_session:create(<<"admin1">>, admin, <<"admin">>),
|
||||
OldJti = Session#auth_session.current_jti,
|
||||
{ok, NewJti, _} = core_auth_session:rotate(Session#auth_session.session_id, OldJti),
|
||||
?assertNotEqual(OldJti, NewJti),
|
||||
?assertMatch({error, reuse_detected},
|
||||
core_auth_session:rotate(Session#auth_session.session_id, OldJti)).
|
||||
|
||||
test_reuse() ->
|
||||
{ok, Session} = core_auth_session:create(<<"admin1">>, admin, <<"admin">>),
|
||||
Jti = Session#auth_session.current_jti,
|
||||
{ok, _, _} = core_auth_session:rotate(Session#auth_session.session_id, Jti),
|
||||
?assertMatch({error, reuse_detected},
|
||||
core_auth_session:rotate(Session#auth_session.session_id, Jti)).
|
||||
|
||||
test_revoke_family() ->
|
||||
{ok, S1} = core_auth_session:create(<<"admin1">>, admin, <<"admin">>),
|
||||
ok = core_auth_session:revoke_family(S1#auth_session.family_id),
|
||||
?assertMatch({error, revoked},
|
||||
core_auth_session:rotate(S1#auth_session.session_id, S1#auth_session.current_jti)).
|
||||
Reference in New Issue
Block a user