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,24 +144,35 @@ create2(#{
from => From from => From
}} }}
end; end;
create2(#{ do_create(
use_jwks := false, #{
algorithm := 'public-key', use_jwks := false,
public_key := PublicKey, algorithm := 'public-key',
verify_claims := VerifyClaims, public_key := PublicKey,
disconnect_after_expire := DisconnectAfterExpire, verify_claims := VerifyClaims,
acl_claim_name := AclClaimName, disconnect_after_expire := DisconnectAfterExpire,
from := From acl_claim_name := AclClaimName,
}) -> from := From
JWK = create_jwk_from_public_key(PublicKey), } = Config
{ok, #{ ) ->
jwk => JWK, case
verify_claims => VerifyClaims, create_jwk_from_public_key(
disconnect_after_expire => DisconnectAfterExpire, maps:get(enable, Config, false),
acl_claim_name => AclClaimName, PublicKey
from => From )
}}; of
create2( {ok, JWK} ->
{ok, #{
jwk => JWK,
verify_claims => VerifyClaims,
disconnect_after_expire => DisconnectAfterExpire,
acl_claim_name => AclClaimName,
from => From
}};
{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.