fix(jwt): change `request_jwks` to be called after initialization

If called in `init/1`, the module-enabled API may have inconsistent state due to timeout
This commit is contained in:
firest 2022-08-16 10:48:48 +08:00
parent f944e74440
commit 719f6cfb2c
1 changed files with 35 additions and 25 deletions

View File

@ -73,8 +73,9 @@ verify(JwsCompacted) when is_binary(JwsCompacted) ->
init([Options]) -> init([Options]) ->
ok = jose:json_module(jiffy), ok = jose:json_module(jiffy),
_ = ets:new(?TAB, [set, protected, named_table]), _ = ets:new(?TAB, [set, protected, named_table]),
{Static, Remote} = do_init_jwks(Options), Static = do_init_jwks(Options),
true = ets:insert(?TAB, [{static, Static}, {remote, Remote}]), to_request_jwks(Options),
true = ets:insert(?TAB, [{static, Static}, {remote, undefined}]),
Intv = proplists:get_value(interval, Options, ?INTERVAL), Intv = proplists:get_value(interval, Options, ?INTERVAL),
{ok, reset_timer( {ok, reset_timer(
#state{ #state{
@ -83,29 +84,13 @@ init([Options]) ->
%% @private %% @private
do_init_jwks(Options) -> do_init_jwks(Options) ->
K2J = fun(K, F) -> OctJwk = key2jwt_value(secret,
case proplists:get_value(K, Options) of fun(V) ->
undefined -> undefined; jose_jwk:from_oct(list_to_binary(V))
V -> end,
try F(V) of Options),
{error, Reason} -> PemJwk = key2jwt_value(pubkey, fun jose_jwk:from_pem_file/1, Options),
?LOG(warning, "Build ~p JWK ~p failed: {error, ~p}~n", [J ||J <- [OctJwk, PemJwk], J /= undefined].
[K, V, Reason]),
undefined;
J -> J
catch T:R ->
?LOG(warning, "Build ~p JWK ~p failed: {~p, ~p}~n",
[K, V, T, R]),
undefined
end
end
end,
OctJwk = K2J(secret, fun(V) ->
jose_jwk:from_oct(list_to_binary(V))
end),
PemJwk = K2J(pubkey, fun jose_jwk:from_pem_file/1),
Remote = K2J(jwks_addr, fun request_jwks/1),
{[J ||J <- [OctJwk, PemJwk], J /= undefined], Remote}.
handle_call(_Req, _From, State) -> handle_call(_Req, _From, State) ->
{reply, ok, State}. {reply, ok, State}.
@ -122,6 +107,11 @@ handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) ->
end, end,
{noreply, reset_timer(NState)}; {noreply, reset_timer(NState)};
handle_info({request_jwks, Options}, State) ->
Remote = key2jwt_value(jwks_addr, fun request_jwks/1, Options),
true = ets:insert(?TAB, {remote, Remote}),
{noreply, State};
handle_info(_Info, State) -> handle_info(_Info, State) ->
{noreply, State}. {noreply, State}.
@ -249,3 +239,23 @@ do_check_claim([{K, F}|More], Claims) ->
_ -> _ ->
do_check_claim(More, Claims) do_check_claim(More, Claims)
end. end.
to_request_jwks(Options) ->
erlang:send(self(), {request_jwks, Options}).
key2jwt_value(Key, Func, Options) ->
case proplists:get_value(Key, Options) of
undefined -> undefined;
V ->
try Func(V) of
{error, Reason} ->
?LOG(warning, "Build ~p JWK ~p failed: {error, ~p}~n",
[Key, V, Reason]),
undefined;
J -> J
catch T:R ->
?LOG(warning, "Build ~p JWK ~p failed: {~p, ~p}~n",
[Key, V, T, R]),
undefined
end
end.