From 8b9494cf4b50bf1420882db48e2e37bd2acada89 Mon Sep 17 00:00:00 2001 From: firest Date: Thu, 1 Sep 2022 18:53:52 +0800 Subject: [PATCH 1/3] fix(jwt): support non-integer timestamp claims fix #8825 --- .../src/simple_authn/emqx_authn_jwt.erl | 43 ++++++++++++------- apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl | 14 +++++- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl index c6f2069ae..c450d838c 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -1,4 +1,4 @@ -%%-------------------------------------------------------------------- +%-------------------------------------------------------------------- %% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); @@ -383,7 +383,7 @@ do_verify(JWT, [JWK | More], VerifyClaims) -> try jose_jws:verify(JWK, JWT) of {true, Payload, _JWT} -> Claims0 = emqx_json:decode(Payload, [return_maps]), - Claims = try_convert_to_int(Claims0, [<<"exp">>, <<"iat">>, <<"nbf">>]), + Claims = try_convert_to_num(Claims0, [<<"exp">>, <<"iat">>, <<"nbf">>]), case verify_claims(Claims, VerifyClaims) of ok -> {ok, Claims}; @@ -403,37 +403,37 @@ verify_claims(Claims, VerifyClaims0) -> VerifyClaims = [ {<<"exp">>, fun(ExpireTime) -> - is_integer(ExpireTime) andalso Now < ExpireTime + is_number(ExpireTime) andalso Now < ExpireTime end}, {<<"iat">>, fun(IssueAt) -> - is_integer(IssueAt) andalso IssueAt =< Now + is_number(IssueAt) andalso IssueAt =< Now end}, {<<"nbf">>, fun(NotBefore) -> - is_integer(NotBefore) andalso NotBefore =< Now + is_number(NotBefore) andalso NotBefore =< Now end} ] ++ VerifyClaims0, do_verify_claims(Claims, VerifyClaims). -try_convert_to_int(Claims, [Name | Names]) -> +try_convert_to_num(Claims, [Name | Names]) -> case Claims of #{Name := Value} -> case Value of - Int when is_integer(Int) -> - try_convert_to_int(Claims#{Name => Int}, Names); + Int when is_number(Int) -> + try_convert_to_num(Claims#{Name => Int}, Names); Bin when is_binary(Bin) -> - case string:to_integer(Bin) of - {Int, <<>>} -> - try_convert_to_int(Claims#{Name => Int}, Names); + case binary_to_number(Bin) of + {ok, Num} -> + try_convert_to_num(Claims#{Name => Num}, Names); _ -> - try_convert_to_int(Claims, Names) + try_convert_to_num(Claims, Names) end; _ -> - try_convert_to_int(Claims, Names) + try_convert_to_num(Claims, Names) end; _ -> - try_convert_to_int(Claims, Names) + try_convert_to_num(Claims, Names) end; -try_convert_to_int(Claims, []) -> +try_convert_to_num(Claims, []) -> Claims. do_verify_claims(_Claims, []) -> @@ -519,3 +519,16 @@ to_binary(B) when is_binary(B) -> B. sc(Type, Meta) -> hoconsc:mk(Type, Meta). + +binary_to_number(Bin) -> + try + {ok, erlang:binary_to_integer(Bin)} + catch + _:_ -> + try + {ok, erlang:binary_to_float(Bin)} + catch + _:_ -> + false + end + end. diff --git a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl index db62775cd..e84f87f0b 100644 --- a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl @@ -408,7 +408,19 @@ t_verify_claims(_) -> }, ?assertMatch( {ok, #{is_superuser := false}}, emqx_authn_jwt:authenticate(Credential4, State1) - ). + ), + + Payload5 = #{ + <<"username">> => <<"myuser">>, + <<"foo">> => <<"myuser">>, + <<"exp">> => erlang:system_time(second) + 10.5 + }, + JWS5 = generate_jws('hmac-based', Payload5, Secret), + Credential5 = #{ + username => <<"myuser">>, + password => JWS5 + }, + ?assertMatch({ok, #{is_superuser := false}}, emqx_authn_jwt:authenticate(Credential5, State1)). t_jwt_not_allow_empty_claim_name(_) -> Request = #{ From 4583d4c0b90d7d637806de70fc0e506fa7c2ec32 Mon Sep 17 00:00:00 2001 From: firest Date: Fri, 2 Sep 2022 10:19:04 +0800 Subject: [PATCH 2/3] chore: update CHANGES-5.0.md --- CHANGES-5.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES-5.0.md b/CHANGES-5.0.md index 1c6c5dc64..e9a9282db 100644 --- a/CHANGES-5.0.md +++ b/CHANGES-5.0.md @@ -3,6 +3,7 @@ ## Bug fixes * Fix exhook `client.authorize` never being execauted. [#8780](https://github.com/emqx/emqx/pull/8780) +* Fix JWT plugin don't support non-integer timestamp claims. [#8867](https://github.com/emqx/emqx/pull/8867) ## Enhancements From a41461ac930a22c4ef515304f5c2e81f87a7ed7b Mon Sep 17 00:00:00 2001 From: JianBo He Date: Fri, 2 Sep 2022 16:17:25 +0800 Subject: [PATCH 3/3] chore: update apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl --- apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl index c450d838c..d41a7fc69 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -1,4 +1,4 @@ -%-------------------------------------------------------------------- +%%-------------------------------------------------------------------- %% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License");