mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
JWT-only authentication for some users (#3012)
This commit is contained in:
parent
f48b4124b1
commit
0fe1e40a9d
@ -76,7 +76,7 @@
|
|||||||
{ets_cache:tag(), {ok, password()} | {error, db_failure | not_allowed}}.
|
{ets_cache:tag(), {ok, password()} | {error, db_failure | not_allowed}}.
|
||||||
-callback remove_user(binary(), binary()) -> ok | {error, db_failure | not_allowed}.
|
-callback remove_user(binary(), binary()) -> ok | {error, db_failure | not_allowed}.
|
||||||
-callback user_exists(binary(), binary()) -> {ets_cache:tag(), boolean() | {error, db_failure}}.
|
-callback user_exists(binary(), binary()) -> {ets_cache:tag(), boolean() | {error, db_failure}}.
|
||||||
-callback check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean()}.
|
-callback check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean() | {stop, boolean()}}.
|
||||||
-callback try_register(binary(), binary(), password()) ->
|
-callback try_register(binary(), binary(), password()) ->
|
||||||
{ets_cache:tag(), {ok, password()} | {error, exists | db_failure | not_allowed}}.
|
{ets_cache:tag(), {ok, password()} | {error, exists | db_failure | not_allowed}}.
|
||||||
-callback get_users(binary(), opts()) -> [{binary(), binary()}].
|
-callback get_users(binary(), opts()) -> [{binary(), binary()}].
|
||||||
@ -237,17 +237,20 @@ check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGe
|
|||||||
error ->
|
error ->
|
||||||
false;
|
false;
|
||||||
LAuthzId ->
|
LAuthzId ->
|
||||||
lists:foldl(
|
untag_stop(
|
||||||
fun(Mod, false) ->
|
lists:foldl(
|
||||||
case db_check_password(
|
fun(Mod, false) ->
|
||||||
LUser, LAuthzId, LServer, Password,
|
case db_check_password(
|
||||||
Digest, DigestGen, Mod) of
|
LUser, LAuthzId, LServer, Password,
|
||||||
true -> {true, Mod};
|
Digest, DigestGen, Mod) of
|
||||||
false -> false
|
true -> {true, Mod};
|
||||||
end;
|
false -> false;
|
||||||
(_, Acc) ->
|
{stop, true} -> {stop, {true, Mod}};
|
||||||
Acc
|
{stop, false} -> {stop, false}
|
||||||
end, false, auth_modules(LServer))
|
end;
|
||||||
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, false, auth_modules(LServer)))
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
@ -484,7 +487,11 @@ remove_user(User, Server, Password) ->
|
|||||||
<<"">>, undefined, Mod) of
|
<<"">>, undefined, Mod) of
|
||||||
true ->
|
true ->
|
||||||
db_remove_user(LUser, LServer, Mod);
|
db_remove_user(LUser, LServer, Mod);
|
||||||
|
{stop, true} ->
|
||||||
|
db_remove_user(LUser, LServer, Mod);
|
||||||
false ->
|
false ->
|
||||||
|
{error, not_allowed};
|
||||||
|
{stop, false} ->
|
||||||
{error, not_allowed}
|
{error, not_allowed}
|
||||||
end
|
end
|
||||||
end, {error, not_allowed}, auth_modules(Server)) of
|
end, {error, not_allowed}, auth_modules(Server)) of
|
||||||
@ -654,7 +661,9 @@ db_check_password(User, AuthzId, Server, ProvidedPassword,
|
|||||||
case Mod:check_password(
|
case Mod:check_password(
|
||||||
User, AuthzId, Server, ProvidedPassword) of
|
User, AuthzId, Server, ProvidedPassword) of
|
||||||
{CacheTag, true} -> {CacheTag, {ok, ProvidedPassword}};
|
{CacheTag, true} -> {CacheTag, {ok, ProvidedPassword}};
|
||||||
{CacheTag, false} -> {CacheTag, error}
|
{CacheTag, {stop, true}} -> {CacheTag, {ok, ProvidedPassword}};
|
||||||
|
{CacheTag, false} -> {CacheTag, error};
|
||||||
|
{CacheTag, {stop, false}} -> {CacheTag, error}
|
||||||
end
|
end
|
||||||
end) of
|
end) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
@ -891,6 +900,9 @@ validate_credentials(User, Server, Password) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
untag_stop({stop, Val}) -> Val;
|
||||||
|
untag_stop(Val) -> Val.
|
||||||
|
|
||||||
import_info() ->
|
import_info() ->
|
||||||
[{<<"users">>, 3}].
|
[{<<"users">>, 3}].
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
-export([start/1, stop/1, check_password/4,
|
-export([start/1, stop/1, check_password/4,
|
||||||
store_type/1, plain_password_required/1,
|
store_type/1, plain_password_required/1,
|
||||||
user_exists/2
|
user_exists/2, use_cache/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
@ -55,7 +55,7 @@ plain_password_required(_Host) -> true.
|
|||||||
|
|
||||||
store_type(_Host) -> external.
|
store_type(_Host) -> external.
|
||||||
|
|
||||||
-spec check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean()}.
|
-spec check_password(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), boolean() | {stop, boolean()}}.
|
||||||
check_password(User, AuthzId, Server, Token) ->
|
check_password(User, AuthzId, Server, Token) ->
|
||||||
%% MREMOND: Should we move the AuthzId check at a higher level in
|
%% MREMOND: Should we move the AuthzId check at a higher level in
|
||||||
%% the call stack?
|
%% the call stack?
|
||||||
@ -64,12 +64,23 @@ check_password(User, AuthzId, Server, Token) ->
|
|||||||
true ->
|
true ->
|
||||||
if Token == <<"">> -> {nocache, false};
|
if Token == <<"">> -> {nocache, false};
|
||||||
true ->
|
true ->
|
||||||
{nocache, check_jwt_token(User, Server, Token)}
|
Res = check_jwt_token(User, Server, Token),
|
||||||
|
Rule = ejabberd_option:jwt_auth_only_rule(Server),
|
||||||
|
case acl:match_rule(Server, Rule,
|
||||||
|
jid:make(User, Server, <<"">>)) of
|
||||||
|
deny ->
|
||||||
|
{nocache, Res};
|
||||||
|
allow ->
|
||||||
|
{nocache, {stop, Res}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
user_exists(_User, _Host) -> {nocache, false}.
|
user_exists(_User, _Host) -> {nocache, false}.
|
||||||
|
|
||||||
|
use_cache(_) ->
|
||||||
|
false.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
-export([host_config/0]).
|
-export([host_config/0]).
|
||||||
-export([hosts/0]).
|
-export([hosts/0]).
|
||||||
-export([include_config_file/0, include_config_file/1]).
|
-export([include_config_file/0, include_config_file/1]).
|
||||||
|
-export([jwt_auth_only_rule/0, jwt_auth_only_rule/1]).
|
||||||
-export([jwt_key/0, jwt_key/1]).
|
-export([jwt_key/0, jwt_key/1]).
|
||||||
-export([language/0, language/1]).
|
-export([language/0, language/1]).
|
||||||
-export([ldap_backups/0, ldap_backups/1]).
|
-export([ldap_backups/0, ldap_backups/1]).
|
||||||
@ -424,6 +425,13 @@ include_config_file() ->
|
|||||||
include_config_file(Host) ->
|
include_config_file(Host) ->
|
||||||
ejabberd_config:get_option({include_config_file, Host}).
|
ejabberd_config:get_option({include_config_file, Host}).
|
||||||
|
|
||||||
|
-spec jwt_auth_only_rule() -> atom().
|
||||||
|
jwt_auth_only_rule() ->
|
||||||
|
jwt_auth_only_rule(global).
|
||||||
|
-spec jwt_auth_only_rule(global | binary()) -> atom().
|
||||||
|
jwt_auth_only_rule(Host) ->
|
||||||
|
ejabberd_config:get_option({jwt_auth_only_rule, Host}).
|
||||||
|
|
||||||
-spec jwt_key() -> jose_jwk:key() | 'undefined'.
|
-spec jwt_key() -> jose_jwk:key() | 'undefined'.
|
||||||
jwt_key() ->
|
jwt_key() ->
|
||||||
jwt_key(global).
|
jwt_key(global).
|
||||||
|
@ -409,7 +409,9 @@ opt_type(jwt_key) ->
|
|||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
econf:fail({read_file, Reason, Path})
|
econf:fail({read_file, Reason, Path})
|
||||||
end
|
end
|
||||||
end).
|
end);
|
||||||
|
opt_type(jwt_auth_only_rule) ->
|
||||||
|
econf:atom().
|
||||||
|
|
||||||
%% We only define the types of options that cannot be derived
|
%% We only define the types of options that cannot be derived
|
||||||
%% automatically by tools/opt_type.sh script
|
%% automatically by tools/opt_type.sh script
|
||||||
@ -635,7 +637,8 @@ options() ->
|
|||||||
{websocket_origin, []},
|
{websocket_origin, []},
|
||||||
{websocket_ping_interval, timer:seconds(60)},
|
{websocket_ping_interval, timer:seconds(60)},
|
||||||
{websocket_timeout, timer:minutes(5)},
|
{websocket_timeout, timer:minutes(5)},
|
||||||
{jwt_key, undefined}].
|
{jwt_key, undefined},
|
||||||
|
{jwt_auth_only_rule, none}].
|
||||||
|
|
||||||
-spec globals() -> [atom()].
|
-spec globals() -> [atom()].
|
||||||
globals() ->
|
globals() ->
|
||||||
|
Loading…
Reference in New Issue
Block a user