mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
JWT enhancement (#3460)
* ref: run the default JWT verifier as hook callback * ref: add system timestamp to JWT debug log
This commit is contained in:
parent
bd08f408ca
commit
c056002f7c
@ -33,6 +33,8 @@
|
|||||||
store_type/1, plain_password_required/1,
|
store_type/1, plain_password_required/1,
|
||||||
user_exists/2, use_cache/1
|
user_exists/2, use_cache/1
|
||||||
]).
|
]).
|
||||||
|
%% 'ejabberd_hooks' callback:
|
||||||
|
-export([check_decoded_jwt/5]).
|
||||||
|
|
||||||
-include_lib("xmpp/include/xmpp.hrl").
|
-include_lib("xmpp/include/xmpp.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -41,6 +43,12 @@
|
|||||||
%%% API
|
%%% API
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
start(Host) ->
|
start(Host) ->
|
||||||
|
%% We add our default JWT verifier with hook priority 100.
|
||||||
|
%% So if you need to check or verify your custom JWT before the
|
||||||
|
%% default verifier, It's better to use this hook with priority
|
||||||
|
%% little than 100 and return bool() or {stop, bool()} in your own
|
||||||
|
%% callback function.
|
||||||
|
ejabberd_hooks:add(check_decoded_jwt, Host, ?MODULE, check_decoded_jwt, 100),
|
||||||
case ejabberd_option:jwt_key(Host) of
|
case ejabberd_option:jwt_key(Host) of
|
||||||
undefined ->
|
undefined ->
|
||||||
?ERROR_MSG("Option jwt_key is not configured for ~ts: "
|
?ERROR_MSG("Option jwt_key is not configured for ~ts: "
|
||||||
@ -49,7 +57,8 @@ start(Host) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
stop(_Host) -> ok.
|
stop(Host) ->
|
||||||
|
ejabberd_hooks:delete(check_decoded_jwt, Host, ?MODULE, check_decoded_jwt, 100).
|
||||||
|
|
||||||
plain_password_required(_Host) -> true.
|
plain_password_required(_Host) -> true.
|
||||||
|
|
||||||
@ -81,36 +90,47 @@ user_exists(_User, _Host) -> {nocache, false}.
|
|||||||
use_cache(_) ->
|
use_cache(_) ->
|
||||||
false.
|
false.
|
||||||
|
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
%%% 'ejabberd_hooks' callback
|
||||||
|
%%%----------------------------------------------------------------------
|
||||||
|
check_decoded_jwt(true, Fields, _Signature, Server, User) ->
|
||||||
|
JidField = ejabberd_option:jwt_jid_field(Server),
|
||||||
|
case maps:find(JidField, Fields) of
|
||||||
|
{ok, SJid} when is_binary(SJid) ->
|
||||||
|
try
|
||||||
|
JID = jid:decode(SJid),
|
||||||
|
JID#jid.luser == User andalso JID#jid.lserver == Server
|
||||||
|
catch error:{bad_jid, _} ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
_ -> % error | {ok, _UnknownType}
|
||||||
|
false
|
||||||
|
end;
|
||||||
|
check_decoded_jwt(Acc, _, _, _, _) ->
|
||||||
|
Acc.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
check_jwt_token(User, Server, Token) ->
|
check_jwt_token(User, Server, Token) ->
|
||||||
JWK = ejabberd_option:jwt_key(Server),
|
JWK = ejabberd_option:jwt_key(Server),
|
||||||
JidField = ejabberd_option:jwt_jid_field(Server),
|
|
||||||
try jose_jwt:verify(JWK, Token) of
|
try jose_jwt:verify(JWK, Token) of
|
||||||
{true, {jose_jwt, Fields}, Signature} ->
|
{true, {jose_jwt, Fields}, Signature} ->
|
||||||
?DEBUG("jwt verify: ~p - ~p~n", [Fields, Signature]),
|
Now = erlang:system_time(second),
|
||||||
|
?DEBUG("jwt verify at system timestamp ~p: ~p - ~p~n", [Now, Fields, Signature]),
|
||||||
case maps:find(<<"exp">>, Fields) of
|
case maps:find(<<"exp">>, Fields) of
|
||||||
error ->
|
error ->
|
||||||
%% No expiry in token => We consider token invalid:
|
%% No expiry in token => We consider token invalid:
|
||||||
false;
|
false;
|
||||||
{ok, Exp} ->
|
{ok, Exp} ->
|
||||||
Now = erlang:system_time(second),
|
|
||||||
if
|
if
|
||||||
Exp > Now ->
|
Exp > Now ->
|
||||||
case maps:find(JidField, Fields) of
|
ejabberd_hooks:run_fold(
|
||||||
error ->
|
check_decoded_jwt,
|
||||||
false;
|
Server,
|
||||||
{ok, SJID} ->
|
true,
|
||||||
try jid:decode(SJID) of
|
[Fields, Signature, Server, User]
|
||||||
JID ->
|
);
|
||||||
(JID#jid.luser == User) andalso
|
|
||||||
(JID#jid.lserver == Server) andalso
|
|
||||||
ejabberd_hooks:run_fold(check_decoded_jwt, Server, true, [Fields, Signature, User])
|
|
||||||
catch error:{bad_jid, _} ->
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
true ->
|
true ->
|
||||||
%% return false, if token has expired
|
%% return false, if token has expired
|
||||||
false
|
false
|
||||||
@ -122,4 +142,3 @@ check_jwt_token(User, Server, Token) ->
|
|||||||
error:{badarg, _} ->
|
error:{badarg, _} ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user