From f74e6dde57e9f663515d52a1ead07d05a6d1403d Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 5 Jul 2022 15:31:53 +0200 Subject: [PATCH] fix: allow for exp field to optional to keep backwards compat with 4.X --- CHANGES-5.0.md | 5 ++-- apps/emqx_authn/src/emqx_authn.app.src | 2 +- apps/emqx_authn/src/emqx_authn.appup.src | 12 ++-------- .../src/simple_authn/emqx_authn_jwt.erl | 10 +++++--- apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl | 24 +++++++++++++++++-- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/CHANGES-5.0.md b/CHANGES-5.0.md index 269115c93..76cbae1da 100644 --- a/CHANGES-5.0.md +++ b/CHANGES-5.0.md @@ -5,6 +5,7 @@ * Websocket listener failed to read headers `X-Forwared-For` and `X-Forwarded-Port` [8415](https://github.com/emqx/emqx/pull/8415) * Deleted `cluster_singleton` from MQTT bridge config document. This config is no longer applicable in 5.0 [8407](https://github.com/emqx/emqx/pull/8407) * Fix `emqx/emqx:latest` docker image publish to use the Erlang flavor, but not Elixir flavor [8414](https://github.com/emqx/emqx/pull/8414) +* Changed the `exp` field in JWT auth to be optional rather than required to fix backwards compatability with 4.X releases. [8425](https://github.com/emqx/emqx/pull/8425) # 5.0.2 @@ -14,14 +15,14 @@ Going forward, it will be an enterprise only feature. Main reason: relup requires carefully crafted upgrade instructions from ALL previous versions. For example, 4.3 is now at 4.3.16, we have `4.3.0->4.3.16`, `4.3.1->4.3.16`, ... 16 such upgrade paths in total to maintain. -This had been the biggest obstacle for EMQX team to act agile enought in deliverying enhancements and fixes. +This had been the biggest obstacle for EMQX team to act agile enough in deliverying enhancements and fixes. ## Enhancements ## Bug fixes * Fixed a typo in `bin/emqx` which affects MacOs release when trying to enable Erlang distribution over TLS [8398](https://github.com/emqx/emqx/pull/8398) -* Ristricted shell was accidentally disabled in 5.0.1, it has been added back. [8396]{https://github.com/emqx/emqx/pull/8396) +* Restricted shell was accidentally disabled in 5.0.1, it has been added back. [8396](https://github.com/emqx/emqx/pull/8396) # 5.0.1 diff --git a/apps/emqx_authn/src/emqx_authn.app.src b/apps/emqx_authn/src/emqx_authn.app.src index 09ccfb358..eebd3d90e 100644 --- a/apps/emqx_authn/src/emqx_authn.app.src +++ b/apps/emqx_authn/src/emqx_authn.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_authn, [ {description, "EMQX Authentication"}, - {vsn, "0.1.1"}, + {vsn, "0.1.2"}, {modules, []}, {registered, [emqx_authn_sup, emqx_authn_registry]}, {applications, [kernel, stdlib, emqx_resource, ehttpc, epgsql, mysql, jose]}, diff --git a/apps/emqx_authn/src/emqx_authn.appup.src b/apps/emqx_authn/src/emqx_authn.appup.src index 9dcf55950..04bf1f428 100644 --- a/apps/emqx_authn/src/emqx_authn.appup.src +++ b/apps/emqx_authn/src/emqx_authn.appup.src @@ -1,13 +1,5 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"0.1.0", - [{load_module,emqx_authn_http,brutal_purge,soft_purge,[]}, - {load_module,emqx_authn_utils,brutal_purge,soft_purge,[]}, - {load_module,emqx_authn_redis,brutal_purge,soft_purge,[]}]}, - {<<".*">>,[]}], - [{"0.1.0", - [{load_module,emqx_authn_http,brutal_purge,soft_purge,[]}, - {load_module,emqx_authn_utils,brutal_purge,soft_purge,[]}, - {load_module,emqx_authn_redis,brutal_purge,soft_purge,[]}]}, - {<<".*">>,[]}]}. + [{<<".*">>,[]}], + [{<<".*">>,[]}]}. 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 6b62cec34..31c8d8a8a 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -380,7 +380,9 @@ replace_placeholder([{Name, {placeholder, PL}} | More], Variables, Acc) -> Value = maps:get(PL, Variables), replace_placeholder(More, Variables, [{Name, Value} | Acc]); replace_placeholder([{Name, Value} | More], Variables, Acc) -> - replace_placeholder(More, Variables, [{Name, Value} | Acc]). + replace_placeholder(More, Variables, [{Name, Value} | Acc]); +replace_placeholder([{_Name, _Required, _Fun} = Claim | More], Variables, Acc) -> + replace_placeholder(More, Variables, [Claim | Acc]). verify(undefined, _, _, _) -> ignore; @@ -432,7 +434,7 @@ verify_claims(Claims, VerifyClaims0) -> Now = os:system_time(seconds), VerifyClaims = [ - {<<"exp">>, required, fun(ExpireTime) -> + {<<"exp">>, optional, fun(ExpireTime) -> is_integer(ExpireTime) andalso Now < ExpireTime end}, {<<"iat">>, optional, fun(IssueAt) -> @@ -528,7 +530,9 @@ handle_verify_claims([], Acc) -> Acc; handle_verify_claims([{Name, Expected0} | More], Acc) -> Expected = handle_placeholder(Expected0), - handle_verify_claims(More, [{Name, Expected} | Acc]). + handle_verify_claims(More, [{Name, Expected} | Acc]); +handle_verify_claims([{_Name, _Required, _Fun} = Claim | More], Acc) -> + handle_verify_claims(More, [Claim | Acc]). handle_placeholder(Placeholder0) -> case re:run(Placeholder0, "^\\$\\{[a-z0-9\\-]+\\}$", [{capture, all}]) of diff --git a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl index e5d56aa1f..61c15881e 100644 --- a/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl @@ -399,7 +399,27 @@ t_verify_claims(_) -> }, ?assertMatch({ok, #{is_superuser := false}}, emqx_authn_jwt:authenticate(Credential3, State1)), - %% No exp + %% No exp treated as unexpired + Payload4 = #{<<"username">> => <<"myuser">>, <<"foo">> => <<"myuser">>}, + JWS4 = generate_jws('hmac-based', Payload4, Secret), + Credential4 = #{ + username => <<"myuser">>, + password => JWS4 + }, + ?assertMatch( + {ok, #{is_superuser := false}}, emqx_authn_jwt:authenticate(Credential4, State1) + ), + + %% No exp when required + Now = os:system_time(seconds), + Config2 = Config1#{ + verify_claims => [ + {<<"exp">>, required, fun(ExpireTime) -> + is_integer(ExpireTime) andalso Now < ExpireTime + end} + ] + }, + {ok, State2} = emqx_authn_jwt:update(Config2, State1), Payload4 = #{<<"username">> => <<"myuser">>, <<"foo">> => <<"myuser">>}, JWS4 = generate_jws('hmac-based', Payload4, Secret), Credential4 = #{ @@ -407,7 +427,7 @@ t_verify_claims(_) -> password => JWS4 }, ?assertEqual( - {error, bad_username_or_password}, emqx_authn_jwt:authenticate(Credential4, State1) + {error, bad_username_or_password}, emqx_authn_jwt:authenticate(Credential4, State2) ). t_jwt_not_allow_empty_claim_name(_) ->