Skip to content

Commit 3fc6d34

Browse files
Add function that resolves expiration tine
1 parent 2e35e72 commit 3fc6d34

File tree

5 files changed

+72
-20
lines changed

5 files changed

+72
-20
lines changed

deps/oauth2_client/include/oauth2_client.hrl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@
6666
-record(successful_access_token_response, {
6767
access_token :: binary(),
6868
token_type :: binary(),
69-
refresh_token :: option(binary()),
69+
refresh_token :: option(binary()), % A refresh token SHOULD NOT be included
70+
% .. for client-credentials flow.
71+
% https://www.rfc-editor.org/rfc/rfc6749#section-4.4.3
7072
expires_in :: option(integer())
7173
}).
7274

deps/oauth2_client/src/jwt_helper.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
%%
77
-module(jwt_helper).
88

9-
-export([decode/1, get_expiration/1]).
9+
-export([decode/1, get_expiration_time/1]).
1010

1111
-include_lib("jose/include/jose_jwt.hrl").
1212

@@ -18,5 +18,5 @@ decode(Token) ->
1818
{error, {invalid_token, Type, Err, Stacktrace}}
1919
end.
2020

21-
get_expiration(#{<<"exp">> := Exp}) when is_integer(Exp) -> {ok, Exp};
22-
get_expiration(#{}) -> {error, missing_exp_field}.
21+
get_expiration_time(#{<<"exp">> := Exp}) when is_integer(Exp) -> {ok, Exp};
22+
get_expiration_time(#{}) -> {error, missing_exp_field}.

deps/oauth2_client/src/oauth2_client.erl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
66
%%
77
-module(oauth2_client).
8-
-export([get_access_token/2,
8+
-export([get_access_token/2, get_expiration_time/1,
99
refresh_access_token/2,
1010
get_oauth_provider/1, get_oauth_provider/2,
1111
extract_ssl_options_as_list/1
@@ -71,6 +71,14 @@ get_openid_configuration(IssuerURI, OpenIdConfigurationPath, TLSOptions) ->
7171
get_openid_configuration(IssuerURI, TLSOptions) ->
7272
get_openid_configuration(IssuerURI, ?DEFAULT_OPENID_CONFIGURATION_PATH, TLSOptions).
7373

74+
-spec get_expiration_time(successful_access_token_response()) -> {ok, integer()} | {error, missing_exp_field}.
75+
get_expiration_time(#successful_access_token_response{expires_in = ExpiresIn,
76+
access_token = AccessToken}) ->
77+
case ExpiresIn of
78+
undefined -> jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken));
79+
_ -> {ok, ExpiresIn}
80+
end.
81+
7482
update_oauth_provider_endpoints_configuration(OAuthProvider) ->
7583
LockId = lock(),
7684
try do_update_oauth_provider_endpoints_configuration(OAuthProvider) of

deps/oauth2_client/test/oauth2_client_test_util.erl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ expirable_token(Seconds) ->
6666
%% expiration is a timestamp with precision in seconds
6767
TokenPayload#{<<"exp">> := os:system_time(seconds) + Seconds}.
6868

69+
expirable_token_with_expiration_time(ExpiresIn) ->
70+
TokenPayload = fixture_token(),
71+
%% expiration is a timestamp with precision in seconds
72+
TokenPayload#{<<"exp">> := ExpiresIn}.
73+
6974
expired_token() ->
7075
expired_token_with_scopes(full_permission_scopes()).
7176

deps/oauth2_client/test/unit_SUITE.erl

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515

1616
-compile(export_all).
1717

18+
-define(UTIL_MOD, oauth2_client_test_util).
1819

1920
all() ->
2021
[
21-
{group, ssl_options}
22+
{group, ssl_options},
23+
{group, get_expiration_time}
2224
].
2325

2426
groups() ->
@@ -27,42 +29,77 @@ groups() ->
2729
no_ssl_options_triggers_verify_peer,
2830
peer_verification_verify_none,
2931
peer_verification_verify_peer_with_cacertfile
32+
]},
33+
{get_expiration_time, [], [
34+
access_token_response_without_expiration_time,
35+
access_token_response_with_expires_in,
36+
access_token_response_with_exp_in_access_token
3037
]}
3138
].
3239

40+
3341
no_ssl_options_triggers_verify_peer(_) ->
34-
?assertMatch([
42+
[
3543
{verify, verify_peer},
3644
{depth, 10},
3745
{crl_check,false},
3846
{fail_if_no_peer_cert,false},
3947
{cacerts, _CaCerts}
40-
], oauth2_client:extract_ssl_options_as_list(#{})).
48+
] = oauth2_client:extract_ssl_options_as_list(#{ }).
4149

4250
peer_verification_verify_none(_) ->
43-
Expected1 = [
51+
[
4452
{verify, verify_none}
45-
],
46-
?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list(#{peer_verification => verify_none})),
47-
48-
Expected2 = [
53+
] = oauth2_client:extract_ssl_options_as_list(#{ peer_verification => verify_none }),
54+
[
4955
{verify, verify_none}
50-
],
51-
?assertEqual(Expected2, oauth2_client:extract_ssl_options_as_list(#{
56+
] = oauth2_client:extract_ssl_options_as_list(#{
5257
peer_verification => verify_none,
5358
cacertfile => "/tmp"
54-
})).
59+
}).
5560

5661

5762
peer_verification_verify_peer_with_cacertfile(_) ->
58-
Expected = [
63+
[
5964
{verify, verify_peer},
6065
{depth, 10},
6166
{crl_check,false},
6267
{fail_if_no_peer_cert,false},
6368
{cacertfile, "/tmp"}
64-
],
65-
?assertEqual(Expected, oauth2_client:extract_ssl_options_as_list(#{
69+
] = oauth2_client:extract_ssl_options_as_list(#{
6670
cacertfile => "/tmp",
6771
peer_verification => verify_peer
68-
})).
72+
}).
73+
74+
75+
access_token_response_with_expires_in(_) ->
76+
Jwk = ?UTIL_MOD:fixture_jwk(),
77+
ExpiresIn = os:system_time(seconds),
78+
AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn),
79+
{_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk),
80+
AccessTokenResponse = #successful_access_token_response{
81+
access_token = EncodedToken,
82+
expires_in = ExpiresIn
83+
},
84+
?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)).
85+
86+
access_token_response_with_exp_in_access_token(_) ->
87+
Jwk = ?UTIL_MOD:fixture_jwk(),
88+
ExpiresIn = os:system_time(seconds),
89+
AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn),
90+
{_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk),
91+
AccessTokenResponse = #successful_access_token_response{
92+
access_token = EncodedToken
93+
},
94+
?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)).
95+
96+
access_token_response_without_expiration_time(_) ->
97+
Jwk = ?UTIL_MOD:fixture_jwk(),
98+
AccessToken = maps:remove(<<"exp">>, ?UTIL_MOD:fixture_token()),
99+
ct:log("AccesToken ~p", [AccessToken]),
100+
{_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk),
101+
AccessTokenResponse = #successful_access_token_response{
102+
access_token = EncodedToken
103+
},
104+
ct:log("AccessTokenResponse ~p", [AccessTokenResponse]),
105+
?assertEqual({error, missing_exp_field}, oauth2_client:get_expiration_time(AccessTokenResponse)).

0 commit comments

Comments
 (0)