Skip to content

Commit

Permalink
Cache Header max-age=0 fix (#371)
Browse files Browse the repository at this point in the history
Fixes #370
  • Loading branch information
maennchen authored Aug 12, 2024
1 parent 9bba708 commit 31c7f3d
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 35 deletions.
33 changes: 33 additions & 0 deletions src/oidcc_http_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

-export([basic_auth_header/2]).
-export([bearer_auth_header/1]).
-export([headers_to_cache_deadline/2]).
-export([request/4]).

-export_type([
Expand Down Expand Up @@ -170,3 +171,35 @@ fetch_content_type(Headers) ->
_Other ->
unknown
end.

-spec headers_to_cache_deadline(Headers, DefaultExpiry) -> pos_integer() when
Headers :: [{Header :: binary(), Value :: binary()}], DefaultExpiry :: non_neg_integer().
headers_to_cache_deadline(Headers, DefaultExpiry) ->
case proplists:lookup("cache-control", Headers) of
{"cache-control", Cache} ->
try
cache_deadline(Cache, DefaultExpiry)
catch
_:_ ->
DefaultExpiry
end;
none ->
DefaultExpiry
end.

-spec cache_deadline(Cache :: iodata(), Fallback :: pos_integer()) -> pos_integer().
cache_deadline(Cache, Fallback) ->
Entries =
binary:split(iolist_to_binary(Cache), [<<",">>, <<"=">>, <<" ">>], [global, trim_all]),
MaxAge =
fun
(<<"0">>, true) ->
Fallback;
(Entry, true) ->
erlang:convert_time_unit(binary_to_integer(Entry), second, millisecond);
(<<"max-age">>, _) ->
true;
(_, Res) ->
Res
end,
lists:foldl(MaxAge, Fallback, Entries).
41 changes: 6 additions & 35 deletions src/oidcc_provider_configuration.erl
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,12 @@ load_configuration(Issuer0, Opts) ->
% this quirk is deprecated, but we keep the support for backwards compatibility.
AllowIssuerMismatch = maps:get(allow_issuer_mismatch, Quirks, false),

DefaultExpiry = maps:get(fallback_expiry, Opts, ?DEFAULT_CONFIG_EXPIRY),

maybe
{ok, {{json, ConfigurationMap}, Headers}} ?=
oidcc_http_util:request(get, Request, TelemetryOpts, RequestOpts),
Expiry = headers_to_deadline(Headers, Opts),
Expiry = oidcc_http_util:headers_to_cache_deadline(Headers, DefaultExpiry),
{ok, #oidcc_provider_configuration{issuer = ConfigIssuer} = Configuration} ?=
decode_configuration(ConfigurationMap, #{quirks => Quirks}),
case ConfigIssuer of
Expand Down Expand Up @@ -259,10 +261,12 @@ load_jwks(JwksUri, Opts) ->
TelemetryOpts = #{topic => [oidcc, load_jwks], extra_meta => #{jwks_uri => JwksUri}},
RequestOpts = maps:get(request_opts, Opts, #{}),

DefaultExpiry = maps:get(fallback_expiry, Opts, ?DEFAULT_CONFIG_EXPIRY),

maybe
{ok, {{json, JwksBinary}, Headers}} ?=
oidcc_http_util:request(get, {JwksUri, []}, TelemetryOpts, RequestOpts),
Expiry = headers_to_deadline(Headers, Opts),
Expiry = oidcc_http_util:headers_to_cache_deadline(Headers, DefaultExpiry),
Jwks = jose_jwk:from(JwksBinary),
{ok, {Jwks, Expiry}}
else
Expand Down Expand Up @@ -569,39 +573,6 @@ decode_configuration(Configuration0, Opts) ->
Configuration :: map().
decode_configuration(Configuration) -> decode_configuration(Configuration, #{}).

-spec headers_to_deadline(Headers, Opts) -> pos_integer() when
Headers :: [{Header :: binary(), Value :: binary()}], Opts :: opts().
headers_to_deadline(Headers, Opts) ->
DefaultExpiry = maps:get(fallback_expiry, Opts, ?DEFAULT_CONFIG_EXPIRY),
case proplists:lookup("cache-control", Headers) of
{"cache-control", Cache} ->
try
cache_deadline(Cache, DefaultExpiry)
catch
_:_ ->
DefaultExpiry
end;
none ->
DefaultExpiry
end.

-spec cache_deadline(Cache :: iodata(), Fallback :: pos_integer()) -> pos_integer().
cache_deadline(Cache, Fallback) ->
Entries =
binary:split(iolist_to_binary(Cache), [<<",">>, <<"=">>, <<" ">>], [global, trim_all]),
MaxAge =
fun
(<<"0">>, Res) ->
Res;
(Entry, true) ->
erlang:convert_time_unit(binary_to_integer(Entry), second, millisecond);
(<<"max-age">>, _) ->
true;
(_, Res) ->
Res
end,
lists:foldl(MaxAge, Fallback, Entries).

-spec parse_scopes_supported(Setting :: term(), Field :: atom()) ->
{ok, [binary()]} | {error, error()}.
parse_scopes_supported(Setting, Field) ->
Expand Down
23 changes: 23 additions & 0 deletions test/oidcc_http_util_test.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-module(oidcc_http_util_test).

-include_lib("eunit/include/eunit.hrl").

headers_to_cache_deadline_test() ->
?assertEqual(
1000,
oidcc_http_util:headers_to_cache_deadline([], 1000)
),
?assertEqual(
timer:seconds(300),
oidcc_http_util:headers_to_cache_deadline(
[{"cache-control", "no-store, no-cache, max-age=300"}], 1000
)
),
?assertEqual(
1000,
oidcc_http_util:headers_to_cache_deadline(
[{"cache-control", "no-store, no-cache, max-age=0"}], 1000
)
),

ok.

0 comments on commit 31c7f3d

Please sign in to comment.