fix: create authn jwt with bad public key

This commit is contained in:
JimMoen 2024-07-08 15:35:20 +08:00
parent 29d7a511f1
commit f76444fbf8
No known key found for this signature in database
2 changed files with 49 additions and 21 deletions

View File

@ -18,6 +18,7 @@
-include_lib("emqx_auth/include/emqx_authn.hrl"). -include_lib("emqx_auth/include/emqx_authn.hrl").
-include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/logger.hrl").
-include_lib("jose/include/jose_jwk.hrl").
-export([ -export([
create/2, create/2,
@ -38,7 +39,7 @@ create(_AuthenticatorID, Config) ->
create(Config). create(Config).
create(#{verify_claims := VerifyClaims} = Config) -> create(#{verify_claims := VerifyClaims} = Config) ->
create2(Config#{verify_claims => handle_verify_claims(VerifyClaims)}). do_create(Config#{verify_claims => handle_verify_claims(VerifyClaims)}).
update( update(
#{use_jwks := false} = Config, #{use_jwks := false} = Config,
@ -83,6 +84,7 @@ authenticate(
} }
) -> ) ->
JWT = maps:get(From, Credential), JWT = maps:get(From, Credential),
%% XXX: Only supports single public key
JWKs = [JWK], JWKs = [JWK],
VerifyClaims = replace_placeholder(VerifyClaims0, Credential), VerifyClaims = replace_placeholder(VerifyClaims0, Credential),
verify(JWT, JWKs, VerifyClaims, AclClaimName, DisconnectAfterExpire); verify(JWT, JWKs, VerifyClaims, AclClaimName, DisconnectAfterExpire);
@ -119,7 +121,7 @@ destroy(_) ->
%% Internal functions %% Internal functions
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
create2(#{ do_create(#{
use_jwks := false, use_jwks := false,
algorithm := 'hmac-based', algorithm := 'hmac-based',
secret := Secret0, secret := Secret0,
@ -142,7 +144,8 @@ create2(#{
from => From from => From
}} }}
end; end;
create2(#{ do_create(
#{
use_jwks := false, use_jwks := false,
algorithm := 'public-key', algorithm := 'public-key',
public_key := PublicKey, public_key := PublicKey,
@ -150,8 +153,15 @@ create2(#{
disconnect_after_expire := DisconnectAfterExpire, disconnect_after_expire := DisconnectAfterExpire,
acl_claim_name := AclClaimName, acl_claim_name := AclClaimName,
from := From from := From
}) -> } = Config
JWK = create_jwk_from_public_key(PublicKey), ) ->
case
create_jwk_from_public_key(
maps:get(enable, Config, false),
PublicKey
)
of
{ok, JWK} ->
{ok, #{ {ok, #{
jwk => JWK, jwk => JWK,
verify_claims => VerifyClaims, verify_claims => VerifyClaims,
@ -159,7 +169,10 @@ create2(#{
acl_claim_name => AclClaimName, acl_claim_name => AclClaimName,
from => From from => From
}}; }};
create2( {error, _Reason} = Err ->
Err
end;
do_create(
#{ #{
use_jwks := true, use_jwks := true,
verify_claims := VerifyClaims, verify_claims := VerifyClaims,
@ -183,9 +196,23 @@ create2(
from => From from => From
}}. }}.
create_jwk_from_public_key(PublicKey) when create_jwk_from_public_key(true, PublicKey) when
is_binary(PublicKey); is_list(PublicKey) is_binary(PublicKey); is_list(PublicKey)
-> ->
try do_create_jwk_from_public_key(PublicKey) of
%% XXX: Only supports single public key
#jose_jwk{} = Res ->
{ok, Res};
_ ->
{error, invalid_public_key}
catch
_:_ ->
{error, invalid_public_key}
end;
create_jwk_from_public_key(false, _PublicKey) ->
{ok, []}.
do_create_jwk_from_public_key(PublicKey) ->
case filelib:is_file(PublicKey) of case filelib:is_file(PublicKey) of
true -> true ->
jose_jwk:from_pem_file(PublicKey); jose_jwk:from_pem_file(PublicKey);

1
changes/fix-13432.en.md Normal file
View File

@ -0,0 +1 @@
Fixed the issue where JWT authentication was silently bypassed when an invalid public key (or invalid public key file path) was used.