Merge pull request #8867 from lafirest/fix/jwt_exp_v5
fix(jwt): support non-integer timestamp claims
This commit is contained in:
commit
cffdcb4284
|
@ -3,6 +3,7 @@
|
||||||
## Bug fixes
|
## Bug fixes
|
||||||
|
|
||||||
* Fix exhook `client.authorize` never being execauted. [#8780](https://github.com/emqx/emqx/pull/8780)
|
* 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
|
## Enhancements
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,7 @@ do_verify(JWT, [JWK | More], VerifyClaims) ->
|
||||||
try jose_jws:verify(JWK, JWT) of
|
try jose_jws:verify(JWK, JWT) of
|
||||||
{true, Payload, _JWT} ->
|
{true, Payload, _JWT} ->
|
||||||
Claims0 = emqx_json:decode(Payload, [return_maps]),
|
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
|
case verify_claims(Claims, VerifyClaims) of
|
||||||
ok ->
|
ok ->
|
||||||
{ok, Claims};
|
{ok, Claims};
|
||||||
|
@ -403,37 +403,37 @@ verify_claims(Claims, VerifyClaims0) ->
|
||||||
VerifyClaims =
|
VerifyClaims =
|
||||||
[
|
[
|
||||||
{<<"exp">>, fun(ExpireTime) ->
|
{<<"exp">>, fun(ExpireTime) ->
|
||||||
is_integer(ExpireTime) andalso Now < ExpireTime
|
is_number(ExpireTime) andalso Now < ExpireTime
|
||||||
end},
|
end},
|
||||||
{<<"iat">>, fun(IssueAt) ->
|
{<<"iat">>, fun(IssueAt) ->
|
||||||
is_integer(IssueAt) andalso IssueAt =< Now
|
is_number(IssueAt) andalso IssueAt =< Now
|
||||||
end},
|
end},
|
||||||
{<<"nbf">>, fun(NotBefore) ->
|
{<<"nbf">>, fun(NotBefore) ->
|
||||||
is_integer(NotBefore) andalso NotBefore =< Now
|
is_number(NotBefore) andalso NotBefore =< Now
|
||||||
end}
|
end}
|
||||||
] ++ VerifyClaims0,
|
] ++ VerifyClaims0,
|
||||||
do_verify_claims(Claims, VerifyClaims).
|
do_verify_claims(Claims, VerifyClaims).
|
||||||
|
|
||||||
try_convert_to_int(Claims, [Name | Names]) ->
|
try_convert_to_num(Claims, [Name | Names]) ->
|
||||||
case Claims of
|
case Claims of
|
||||||
#{Name := Value} ->
|
#{Name := Value} ->
|
||||||
case Value of
|
case Value of
|
||||||
Int when is_integer(Int) ->
|
Int when is_number(Int) ->
|
||||||
try_convert_to_int(Claims#{Name => Int}, Names);
|
try_convert_to_num(Claims#{Name => Int}, Names);
|
||||||
Bin when is_binary(Bin) ->
|
Bin when is_binary(Bin) ->
|
||||||
case string:to_integer(Bin) of
|
case binary_to_number(Bin) of
|
||||||
{Int, <<>>} ->
|
{ok, Num} ->
|
||||||
try_convert_to_int(Claims#{Name => Int}, Names);
|
try_convert_to_num(Claims#{Name => Num}, Names);
|
||||||
_ ->
|
_ ->
|
||||||
try_convert_to_int(Claims, Names)
|
try_convert_to_num(Claims, Names)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
try_convert_to_int(Claims, Names)
|
try_convert_to_num(Claims, Names)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
try_convert_to_int(Claims, Names)
|
try_convert_to_num(Claims, Names)
|
||||||
end;
|
end;
|
||||||
try_convert_to_int(Claims, []) ->
|
try_convert_to_num(Claims, []) ->
|
||||||
Claims.
|
Claims.
|
||||||
|
|
||||||
do_verify_claims(_Claims, []) ->
|
do_verify_claims(_Claims, []) ->
|
||||||
|
@ -519,3 +519,16 @@ to_binary(B) when is_binary(B) ->
|
||||||
B.
|
B.
|
||||||
|
|
||||||
sc(Type, Meta) -> hoconsc:mk(Type, Meta).
|
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.
|
||||||
|
|
|
@ -408,7 +408,19 @@ t_verify_claims(_) ->
|
||||||
},
|
},
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{ok, #{is_superuser := false}}, emqx_authn_jwt:authenticate(Credential4, State1)
|
{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(_) ->
|
t_jwt_not_allow_empty_claim_name(_) ->
|
||||||
Request = #{
|
Request = #{
|
||||||
|
|
Loading…
Reference in New Issue