From 13fb2d25973c8cdf003ea267185a7cb92ccab4b5 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Thu, 29 Feb 2024 11:12:21 +0100 Subject: [PATCH 1/8] Add token helper functions Such as those to decode and extract the expiration time (cherry picked from commit d53957e34aea9e4d1d4c35e8e7cb673a175e3e65) --- deps/oauth2_client/BUILD.bazel | 12 +- deps/oauth2_client/app.bzl | 23 ++- deps/oauth2_client/src/jwt_helper.erl | 22 +++ .../test/oauth2_client_test_util.erl | 149 ++++++++++++++++++ 4 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 deps/oauth2_client/src/jwt_helper.erl create mode 100644 deps/oauth2_client/test/oauth2_client_test_util.erl diff --git a/deps/oauth2_client/BUILD.bazel b/deps/oauth2_client/BUILD.bazel index 623c10a2a401..ad40f8c55de6 100644 --- a/deps/oauth2_client/BUILD.bazel +++ b/deps/oauth2_client/BUILD.bazel @@ -47,7 +47,10 @@ rabbitmq_app( ], license_files = [":license_files"], priv = [":priv"], - deps = ["//deps/rabbit_common:erlang_app"], + deps = [ + "//deps/rabbit_common:erlang_app", + "@jose//:erlang_app", + ], ) xref( @@ -77,7 +80,9 @@ dialyze( eunit( name = "eunit", - compiled_suites = [":test_oauth_http_mock_beam"], + compiled_suites = [ + ":test_oauth_http_mock_beam", + ":test_oauth2_client_test_util_beam"], target = ":test_erlang_app", ) @@ -112,6 +117,9 @@ rabbitmq_integration_suite( rabbitmq_suite( name = "unit_SUITE", size = "small", + additional_beam = [ + "test/oauth2_client_test_util.beam", + ], ) assert_suites() diff --git a/deps/oauth2_client/app.bzl b/deps/oauth2_client/app.bzl index 433627671bc2..a8790d8dcced 100644 --- a/deps/oauth2_client/app.bzl +++ b/deps/oauth2_client/app.bzl @@ -8,11 +8,15 @@ def all_beam_files(name = "all_beam_files"): ) erlang_bytecode( name = "other_beam", - srcs = ["src/oauth2_client.erl"], + srcs = ["src/oauth2_client.erl", + "src/jwt_helper.erl"], hdrs = [":public_and_private_hdrs"], app_name = "oauth2_client", dest = "ebin", erlc_opts = "//:erlc_opts", + deps = [ + "@jose//:erlang_app" + ], ) def all_test_beam_files(name = "all_test_beam_files"): @@ -24,11 +28,15 @@ def all_test_beam_files(name = "all_test_beam_files"): erlang_bytecode( name = "test_other_beam", testonly = True, - srcs = ["src/oauth2_client.erl"], + srcs = ["src/oauth2_client.erl", + "src/jwt_helper.erl"], hdrs = [":public_and_private_hdrs"], app_name = "oauth2_client", dest = "test", erlc_opts = "//:test_erlc_opts", + deps = [ + "@jose//:erlang_app" + ], ) def all_srcs(name = "all_srcs"): @@ -46,7 +54,8 @@ def all_srcs(name = "all_srcs"): filegroup( name = "srcs", - srcs = ["src/oauth2_client.erl"], + srcs = ["src/oauth2_client.erl", + "src/jwt_helper.erl"], ) filegroup( name = "private_hdrs", @@ -90,3 +99,11 @@ def test_suite_beam_files(name = "test_suite_beam_files"): app_name = "oauth2_client", erlc_opts = "//:test_erlc_opts", ) + erlang_bytecode( + name = "test_oauth2_client_test_util_beam", + testonly = True, + srcs = ["test/oauth2_client_test_util.erl"], + outs = ["test/oauth2_client_test_util.beam"], + app_name = "oauth2_client", + erlc_opts = "//:test_erlc_opts", + ) diff --git a/deps/oauth2_client/src/jwt_helper.erl b/deps/oauth2_client/src/jwt_helper.erl new file mode 100644 index 000000000000..260add5fa643 --- /dev/null +++ b/deps/oauth2_client/src/jwt_helper.erl @@ -0,0 +1,22 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved. +%% +-module(jwt_helper). + +-export([decode/1, get_expiration/1]). + +-include_lib("jose/include/jose_jwt.hrl"). + +decode(Token) -> + try + #jose_jwt{fields = Fields} = jose_jwt:peek_payload(Token), + Fields + catch Type:Err:Stacktrace -> + {error, {invalid_token, Type, Err, Stacktrace}} + end. + +get_expiration(#{<<"exp">> := Exp}) when is_integer(Exp) -> {ok, Exp}; +get_expiration(#{}) -> {error, missing_exp_field}. diff --git a/deps/oauth2_client/test/oauth2_client_test_util.erl b/deps/oauth2_client/test/oauth2_client_test_util.erl new file mode 100644 index 000000000000..c3f55a47ed0e --- /dev/null +++ b/deps/oauth2_client/test/oauth2_client_test_util.erl @@ -0,0 +1,149 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved. +%% +-module(oauth2_client_test_util). + +-compile(export_all). + +-define(DEFAULT_EXPIRATION_IN_SECONDS, 2). + +%% +%% API +%% + +sign_token_hs(Token, #{<<"kid">> := TokenKey} = Jwk) -> + sign_token_hs(Token, Jwk, TokenKey). + +sign_token_hs(Token, Jwk, TokenKey) -> + Jws = #{ + <<"alg">> => <<"HS256">>, + <<"kid">> => TokenKey + }, + sign_token(Token, Jwk, Jws). + +sign_token_rsa(Token, Jwk, TokenKey) -> + Jws = #{ + <<"alg">> => <<"RS256">>, + <<"kid">> => TokenKey + }, + sign_token(Token, Jwk, Jws). + +sign_token_no_kid(Token, Jwk) -> + Signed = jose_jwt:sign(Jwk, Token), + jose_jws:compact(Signed). + +sign_token(Token, Jwk, Jws) -> + Signed = jose_jwt:sign(Jwk, Jws, Token), + jose_jws:compact(Signed). + +fixture_jwk() -> + fixture_jwk(<<"token-key">>). + +fixture_jwk(TokenKey) -> + fixture_jwk(TokenKey, <<"dG9rZW5rZXk">>). + +fixture_jwk(TokenKey, K) -> + #{<<"alg">> => <<"HS256">>, + <<"k">> => K, + <<"kid">> => TokenKey, + <<"kty">> => <<"oct">>, + <<"use">> => <<"sig">>, + <<"value">> => TokenKey}. + +full_permission_scopes() -> + [<<"rabbitmq.configure:*/*">>, + <<"rabbitmq.write:*/*">>, + <<"rabbitmq.read:*/*">>]. + +expirable_token() -> + expirable_token(?DEFAULT_EXPIRATION_IN_SECONDS). + +expirable_token(Seconds) -> + TokenPayload = fixture_token(), + %% expiration is a timestamp with precision in seconds + TokenPayload#{<<"exp">> := os:system_time(seconds) + Seconds}. + +expired_token() -> + expired_token_with_scopes(full_permission_scopes()). + +expired_token_with_scopes(Scopes) -> + token_with_scopes_and_expiration(Scopes, seconds_in_the_past(10)). + +fixture_token_with_scopes(Scopes) -> + token_with_scopes_and_expiration(Scopes, default_expiration_moment()). + +token_with_scopes_and_expiration(Scopes, Expiration) -> + %% expiration is a timestamp with precision in seconds + #{<<"exp">> => Expiration, + <<"iss">> => <<"unit_test">>, + <<"foo">> => <<"bar">>, + <<"aud">> => [<<"rabbitmq">>], + <<"scope">> => Scopes}. + +token_without_scopes() -> + %% expiration is a timestamp with precision in seconds + #{ + <<"iss">> => <<"unit_test">>, + <<"foo">> => <<"bar">>, + <<"aud">> => [<<"rabbitmq">>] + }. + +fixture_token() -> + fixture_token([]). + +token_with_sub(TokenFixture, Sub) -> + maps:put(<<"sub">>, Sub, TokenFixture). +token_with_scopes(TokenFixture, Scopes) -> + maps:put(<<"scope">>, Scopes, TokenFixture). + +fixture_token(ExtraScopes) -> + Scopes = [<<"rabbitmq.configure:vhost/foo">>, + <<"rabbitmq.write:vhost/foo">>, + <<"rabbitmq.read:vhost/foo">>, + <<"rabbitmq.read:vhost/bar">>, + <<"rabbitmq.read:vhost/bar/%23%2Ffoo">>] ++ ExtraScopes, + fixture_token_with_scopes(Scopes). + +fixture_token_with_full_permissions() -> + fixture_token_with_scopes(full_permission_scopes()). + +plain_token_without_scopes_and_aud() -> + %% expiration is a timestamp with precision in seconds + #{<<"exp">> => default_expiration_moment(), + <<"iss">> => <<"unit_test">>, + <<"foo">> => <<"bar">>}. + +token_with_scope_alias_in_scope_field(Value) -> + %% expiration is a timestamp with precision in seconds + #{<<"exp">> => default_expiration_moment(), + <<"iss">> => <<"unit_test">>, + <<"foo">> => <<"bar">>, + <<"aud">> => [<<"rabbitmq">>], + <<"scope">> => Value}. + +token_with_scope_alias_in_claim_field(Claims, Scopes) -> + %% expiration is a timestamp with precision in seconds + #{<<"exp">> => default_expiration_moment(), + <<"iss">> => <<"unit_test">>, + <<"foo">> => <<"bar">>, + <<"aud">> => [<<"rabbitmq">>], + <<"scope">> => Scopes, + <<"claims">> => Claims}. + +seconds_in_the_future() -> + seconds_in_the_future(30). + +seconds_in_the_future(N) -> + os:system_time(seconds) + N. + +seconds_in_the_past() -> + seconds_in_the_past(10). + +seconds_in_the_past(N) -> + os:system_time(seconds) - N. + +default_expiration_moment() -> + seconds_in_the_future(30). From 30e4514026614124cf84059e687372b971f093ec Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Thu, 29 Feb 2024 15:11:50 +0100 Subject: [PATCH 2/8] Add function that resolves expiration tine (cherry picked from commit 407e9d997c449c91398328cbeed675d03ee56934) --- deps/oauth2_client/include/oauth2_client.hrl | 4 +- deps/oauth2_client/src/jwt_helper.erl | 6 +-- deps/oauth2_client/src/oauth2_client.erl | 10 ++++- .../test/oauth2_client_test_util.erl | 5 +++ deps/oauth2_client/test/unit_SUITE.erl | 42 ++++++++++++++++++- 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/deps/oauth2_client/include/oauth2_client.hrl b/deps/oauth2_client/include/oauth2_client.hrl index f571cfc3e763..bfb5f7eeed57 100644 --- a/deps/oauth2_client/include/oauth2_client.hrl +++ b/deps/oauth2_client/include/oauth2_client.hrl @@ -66,7 +66,9 @@ -record(successful_access_token_response, { access_token :: binary(), token_type :: binary(), - refresh_token :: option(binary()), + refresh_token :: option(binary()), % A refresh token SHOULD NOT be included + % .. for client-credentials flow. + % https://www.rfc-editor.org/rfc/rfc6749#section-4.4.3 expires_in :: option(integer()) }). diff --git a/deps/oauth2_client/src/jwt_helper.erl b/deps/oauth2_client/src/jwt_helper.erl index 260add5fa643..88a70c787070 100644 --- a/deps/oauth2_client/src/jwt_helper.erl +++ b/deps/oauth2_client/src/jwt_helper.erl @@ -6,7 +6,7 @@ %% -module(jwt_helper). --export([decode/1, get_expiration/1]). +-export([decode/1, get_expiration_time/1]). -include_lib("jose/include/jose_jwt.hrl"). @@ -18,5 +18,5 @@ decode(Token) -> {error, {invalid_token, Type, Err, Stacktrace}} end. -get_expiration(#{<<"exp">> := Exp}) when is_integer(Exp) -> {ok, Exp}; -get_expiration(#{}) -> {error, missing_exp_field}. +get_expiration_time(#{<<"exp">> := Exp}) when is_integer(Exp) -> {ok, Exp}; +get_expiration_time(#{}) -> {error, missing_exp_field}. diff --git a/deps/oauth2_client/src/oauth2_client.erl b/deps/oauth2_client/src/oauth2_client.erl index fbd7ab1fd5fb..ea3ca739b484 100644 --- a/deps/oauth2_client/src/oauth2_client.erl +++ b/deps/oauth2_client/src/oauth2_client.erl @@ -5,7 +5,7 @@ %% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved. %% -module(oauth2_client). --export([get_access_token/2, +-export([get_access_token/2, get_expiration_time/1, refresh_access_token/2, get_oauth_provider/1, get_oauth_provider/2, extract_ssl_options_as_list/1 @@ -71,6 +71,14 @@ get_openid_configuration(IssuerURI, OpenIdConfigurationPath, TLSOptions) -> get_openid_configuration(IssuerURI, TLSOptions) -> get_openid_configuration(IssuerURI, ?DEFAULT_OPENID_CONFIGURATION_PATH, TLSOptions). +-spec get_expiration_time(successful_access_token_response()) -> {ok, integer()} | {error, missing_exp_field}. +get_expiration_time(#successful_access_token_response{expires_in = ExpiresIn, + access_token = AccessToken}) -> + case ExpiresIn of + undefined -> jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken)); + _ -> {ok, ExpiresIn} + end. + update_oauth_provider_endpoints_configuration(OAuthProvider) -> LockId = lock(), try do_update_oauth_provider_endpoints_configuration(OAuthProvider) of diff --git a/deps/oauth2_client/test/oauth2_client_test_util.erl b/deps/oauth2_client/test/oauth2_client_test_util.erl index c3f55a47ed0e..761814d2dd98 100644 --- a/deps/oauth2_client/test/oauth2_client_test_util.erl +++ b/deps/oauth2_client/test/oauth2_client_test_util.erl @@ -66,6 +66,11 @@ expirable_token(Seconds) -> %% expiration is a timestamp with precision in seconds TokenPayload#{<<"exp">> := os:system_time(seconds) + Seconds}. +expirable_token_with_expiration_time(ExpiresIn) -> + TokenPayload = fixture_token(), + %% expiration is a timestamp with precision in seconds + TokenPayload#{<<"exp">> := ExpiresIn}. + expired_token() -> expired_token_with_scopes(full_permission_scopes()). diff --git a/deps/oauth2_client/test/unit_SUITE.erl b/deps/oauth2_client/test/unit_SUITE.erl index a84682ed7fa9..1a2b7d87faa8 100644 --- a/deps/oauth2_client/test/unit_SUITE.erl +++ b/deps/oauth2_client/test/unit_SUITE.erl @@ -15,10 +15,12 @@ -compile(export_all). +-define(UTIL_MOD, oauth2_client_test_util). all() -> [ - {group, ssl_options} + {group, ssl_options}, + {group, get_expiration_time} ]. groups() -> @@ -30,6 +32,11 @@ groups() -> peer_verification_set_to_verify_none, peer_verification_set_to_verify_peer_with_cacertfile, verify_set_to_verify_peer_with_cacertfile + ]}, + {get_expiration_time, [], [ + access_token_response_without_expiration_time, + access_token_response_with_expires_in, + access_token_response_with_exp_in_access_token ]} ]. @@ -105,3 +112,36 @@ verify_set_to_verify_peer_with_cacertfile(_) -> cacertfile => "/tmp", verify => verify_peer })). + +access_token_response_with_expires_in(_) -> + Jwk = ?UTIL_MOD:fixture_jwk(), + ExpiresIn = os:system_time(seconds), + AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken, + expires_in = ExpiresIn + }, + ?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)). + +access_token_response_with_exp_in_access_token(_) -> + Jwk = ?UTIL_MOD:fixture_jwk(), + ExpiresIn = os:system_time(seconds), + AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken + }, + ?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)). + +access_token_response_without_expiration_time(_) -> + Jwk = ?UTIL_MOD:fixture_jwk(), + AccessToken = maps:remove(<<"exp">>, ?UTIL_MOD:fixture_token()), + ct:log("AccesToken ~p", [AccessToken]), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken + }, + ct:log("AccessTokenResponse ~p", [AccessTokenResponse]), + ?assertEqual({error, missing_exp_field}, oauth2_client:get_expiration_time(AccessTokenResponse)). + From c5c8dc4266b3ab6bf5adacc94602a4266a6bc612 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Wed, 6 Mar 2024 13:26:08 +0100 Subject: [PATCH 3/8] Add constant (cherry picked from commit e520ae2f529da03ab0a6853ec728a408c35b685c) --- deps/oauth2_client/include/oauth2_client.hrl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deps/oauth2_client/include/oauth2_client.hrl b/deps/oauth2_client/include/oauth2_client.hrl index bfb5f7eeed57..7553b0b04a18 100644 --- a/deps/oauth2_client/include/oauth2_client.hrl +++ b/deps/oauth2_client/include/oauth2_client.hrl @@ -9,6 +9,10 @@ % define access token request common constants -define(DEFAULT_HTTP_TIMEOUT, 60000). + +% Refresh tome this number of seconds before expires_in token's attribute +-define(REFRESH_IN_BEFORE_EXPIRES_IN, 5). + -define(DEFAULT_OPENID_CONFIGURATION_PATH, "/.well-known/openid-configuration"). % define access token request constants From e0497919a9b49e9ebf5cd2842e32531e251b79dc Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 26 Apr 2024 17:20:20 +0200 Subject: [PATCH 4/8] Return expires_in or exp depending on whats available (cherry picked from commit fd895aafb7d6c9815f1d1d0bc9e9b25365be5b49) --- deps/oauth2_client/src/oauth2_client.erl | 15 ++++++++++----- deps/oauth2_client/test/unit_SUITE.erl | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/deps/oauth2_client/src/oauth2_client.erl b/deps/oauth2_client/src/oauth2_client.erl index ea3ca739b484..69bd4207dab3 100644 --- a/deps/oauth2_client/src/oauth2_client.erl +++ b/deps/oauth2_client/src/oauth2_client.erl @@ -71,12 +71,17 @@ get_openid_configuration(IssuerURI, OpenIdConfigurationPath, TLSOptions) -> get_openid_configuration(IssuerURI, TLSOptions) -> get_openid_configuration(IssuerURI, ?DEFAULT_OPENID_CONFIGURATION_PATH, TLSOptions). --spec get_expiration_time(successful_access_token_response()) -> {ok, integer()} | {error, missing_exp_field}. -get_expiration_time(#successful_access_token_response{expires_in = ExpiresIn, +-spec get_expiration_time(successful_access_token_response()) -> + {ok, [{expires_in, integer() }| {exp, integer() }]} | {error, missing_exp_field}. +get_expiration_time(#successful_access_token_response{expires_in = ExpiresInSec, access_token = AccessToken}) -> - case ExpiresIn of - undefined -> jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken)); - _ -> {ok, ExpiresIn} + case ExpiresInSec of + undefined -> + case jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken)) of + {ok, Exp} -> {ok, [{exp, Exp}]}; + {error, _} = Error -> Error + end; + _ -> {ok, [{expires_in, ExpiresInSec}]} end. update_oauth_provider_endpoints_configuration(OAuthProvider) -> diff --git a/deps/oauth2_client/test/unit_SUITE.erl b/deps/oauth2_client/test/unit_SUITE.erl index 1a2b7d87faa8..bd9d0a1c462f 100644 --- a/deps/oauth2_client/test/unit_SUITE.erl +++ b/deps/oauth2_client/test/unit_SUITE.erl @@ -122,7 +122,7 @@ access_token_response_with_expires_in(_) -> access_token = EncodedToken, expires_in = ExpiresIn }, - ?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)). + ?assertEqual({ok, [{exoires_in, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). access_token_response_with_exp_in_access_token(_) -> Jwk = ?UTIL_MOD:fixture_jwk(), @@ -132,7 +132,7 @@ access_token_response_with_exp_in_access_token(_) -> AccessTokenResponse = #successful_access_token_response{ access_token = EncodedToken }, - ?assertEqual({ok, ExpiresIn}, oauth2_client:get_expiration_time(AccessTokenResponse)). + ?assertEqual({ok, [{exp, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). access_token_response_without_expiration_time(_) -> Jwk = ?UTIL_MOD:fixture_jwk(), From 50b63769406c06794b99afc9444f77dd6f6069f2 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 26 Apr 2024 17:36:41 +0200 Subject: [PATCH 5/8] Add jose dependency (cherry picked from commit 32e58ce52d3edd8a04508a8ada8255c19dea9f15) --- deps/oauth2_client/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/oauth2_client/Makefile b/deps/oauth2_client/Makefile index 684458c82677..3efe51e407ca 100644 --- a/deps/oauth2_client/Makefile +++ b/deps/oauth2_client/Makefile @@ -3,7 +3,7 @@ PROJECT_DESCRIPTION = OAuth2 client from the RabbitMQ Project PROJECT_MOD = oauth2_client_app BUILD_DEPS = rabbit -DEPS = rabbit_common +DEPS = rabbit_common jose TEST_DEPS = rabbitmq_ct_helpers cowboy LOCAL_DEPS = ssl inets crypto public_key From b82e7fdffeb7dba4ae0c7895a94ea4e409e8a793 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Fri, 26 Apr 2024 17:50:23 +0200 Subject: [PATCH 6/8] Fix test (cherry picked from commit e5cfebe0ddfbabbe53c89e288647b4c4c6c175bc) --- deps/oauth2_client/test/unit_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/oauth2_client/test/unit_SUITE.erl b/deps/oauth2_client/test/unit_SUITE.erl index bd9d0a1c462f..0fce5c37bba5 100644 --- a/deps/oauth2_client/test/unit_SUITE.erl +++ b/deps/oauth2_client/test/unit_SUITE.erl @@ -122,7 +122,7 @@ access_token_response_with_expires_in(_) -> access_token = EncodedToken, expires_in = ExpiresIn }, - ?assertEqual({ok, [{exoires_in, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). + ?assertEqual({ok, [{expires_in, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). access_token_response_with_exp_in_access_token(_) -> Jwk = ?UTIL_MOD:fixture_jwk(), From 283ce9156de195b8175adcf3f6a1e36446a9a254 Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Mon, 6 May 2024 15:33:02 +0200 Subject: [PATCH 7/8] Improve formatting (cherry picked from commit 562b824e8601216d3a7ed2409602ac0c52960f4a) --- deps/oauth2_client/src/oauth2_client.erl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/deps/oauth2_client/src/oauth2_client.erl b/deps/oauth2_client/src/oauth2_client.erl index 69bd4207dab3..c7cee120e8a1 100644 --- a/deps/oauth2_client/src/oauth2_client.erl +++ b/deps/oauth2_client/src/oauth2_client.erl @@ -74,15 +74,15 @@ get_openid_configuration(IssuerURI, TLSOptions) -> -spec get_expiration_time(successful_access_token_response()) -> {ok, [{expires_in, integer() }| {exp, integer() }]} | {error, missing_exp_field}. get_expiration_time(#successful_access_token_response{expires_in = ExpiresInSec, - access_token = AccessToken}) -> - case ExpiresInSec of - undefined -> - case jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken)) of - {ok, Exp} -> {ok, [{exp, Exp}]}; - {error, _} = Error -> Error - end; - _ -> {ok, [{expires_in, ExpiresInSec}]} - end. + access_token = AccessToken}) -> + case ExpiresInSec of + undefined -> + case jwt_helper:get_expiration_time(jwt_helper:decode(AccessToken)) of + {ok, Exp} -> {ok, [{exp, Exp}]}; + {error, _} = Error -> Error + end; + _ -> {ok, [{expires_in, ExpiresInSec}]} + end. update_oauth_provider_endpoints_configuration(OAuthProvider) -> LockId = lock(), From 6435d404a67c1cfd4b2b8ea71d11cc08bb9372bc Mon Sep 17 00:00:00 2001 From: Marcial Rosales Date: Mon, 6 May 2024 15:48:02 +0200 Subject: [PATCH 8/8] Format using 4 spaces (cherry picked from commit 367dba9189d6e34e4b9b22d4bcdfcc99378898d6) --- deps/oauth2_client/test/oauth_http_mock.erl | 65 +- deps/oauth2_client/test/system_SUITE.erl | 744 ++++++++++---------- deps/oauth2_client/test/unit_SUITE.erl | 190 ++--- 3 files changed, 506 insertions(+), 493 deletions(-) diff --git a/deps/oauth2_client/test/oauth_http_mock.erl b/deps/oauth2_client/test/oauth_http_mock.erl index 7b57a6bb738b..4381b8a604b4 100644 --- a/deps/oauth2_client/test/oauth_http_mock.erl +++ b/deps/oauth2_client/test/oauth_http_mock.erl @@ -14,45 +14,46 @@ %%% CALLBACKS init(Req, #{request := ExpectedRequest, response := ExpectedResponse} = Expected) -> - ct:log("init oauth_http_mock Req:~p", [Req]), - match_request(Req, ExpectedRequest), - {Code, Headers, JsonPayload} = produce_expected_response(ExpectedResponse), - {ok, case JsonPayload of - undefined -> cowboy_req:reply(Code, Req); - _ -> cowboy_req:reply(Code, Headers, JsonPayload, Req) - end, Expected}. + ct:log("init oauth_http_mock Req:~p", [Req]), + match_request(Req, ExpectedRequest), + {Code, Headers, JsonPayload} = produce_expected_response(ExpectedResponse), + {ok, case JsonPayload of + undefined -> cowboy_req:reply(Code, Req); + _ -> cowboy_req:reply(Code, Headers, JsonPayload, Req) + end, Expected}. match_request_parameters_in_body(Req, #{parameters := Parameters}) -> - ?assertEqual(true, cowboy_req:has_body(Req)), - {ok, KeyValues, _Req2} = cowboy_req:read_urlencoded_body(Req), - [ ?assertEqual(Value, proplists:get_value(list_to_binary(Parameter), KeyValues)) - || {Parameter, Value} <- Parameters]. + ?assertEqual(true, cowboy_req:has_body(Req)), + {ok, KeyValues, _Req2} = cowboy_req:read_urlencoded_body(Req), + [ ?assertEqual(Value, proplists:get_value(list_to_binary(Parameter), KeyValues)) + || {Parameter, Value} <- Parameters]. match_request(Req, #{method := Method} = ExpectedRequest) -> - ?assertEqual(Method, maps:get(method, Req)), - case maps:is_key(parameters, ExpectedRequest) of - true -> match_request_parameters_in_body(Req, ExpectedRequest); - false -> ok - end. + ?assertEqual(Method, maps:get(method, Req)), + case maps:is_key(parameters, ExpectedRequest) of + true -> match_request_parameters_in_body(Req, ExpectedRequest); + false -> ok + end. produce_expected_response(ExpectedResponse) -> - case proplists:is_defined(content_type, ExpectedResponse) of - true -> - Payload = proplists:get_value(payload, ExpectedResponse), - case is_proplist(Payload) of + case proplists:is_defined(content_type, ExpectedResponse) of true -> - { proplists:get_value(code, ExpectedResponse), - #{<<"content-type">> => proplists:get_value(content_type, ExpectedResponse)}, - rabbit_json:encode(Payload) - }; - _ -> - { proplists:get_value(code, ExpectedResponse), - #{<<"content-type">> => proplists:get_value(content_type, ExpectedResponse)}, - Payload - } - end; - false -> {proplists:get_value(code, ExpectedResponse), undefined, undefined} - end. + Payload = proplists:get_value(payload, ExpectedResponse), + case is_proplist(Payload) of + true -> + { proplists:get_value(code, ExpectedResponse), + #{<<"content-type">> => proplists:get_value(content_type, ExpectedResponse)}, + rabbit_json:encode(Payload) + }; + _ -> + { proplists:get_value(code, ExpectedResponse), + #{<<"content-type">> => proplists:get_value(content_type, ExpectedResponse)}, + Payload + } + end; + false -> + {proplists:get_value(code, ExpectedResponse), undefined, undefined} + end. is_proplist([{_Key, _Val}|_] = List) -> lists:all(fun({_K, _V}) -> true; (_) -> false end, List); diff --git a/deps/oauth2_client/test/system_SUITE.erl b/deps/oauth2_client/test/system_SUITE.erl index 83704e4061b2..c59392de0519 100644 --- a/deps/oauth2_client/test/system_SUITE.erl +++ b/deps/oauth2_client/test/system_SUITE.erl @@ -17,513 +17,525 @@ -define(MOCK_TOKEN_ENDPOINT, <<"/token">>). -define(AUTH_PORT, 8000). -define(GRANT_ACCESS_TOKEN, -#{request => #{ - method => <<"POST">>, - path => ?MOCK_TOKEN_ENDPOINT, - parameters => [ - {?REQUEST_CLIENT_ID, <<"guest">>}, - {?REQUEST_CLIENT_SECRET, <<"password">>} - ] - }, - response => [ - {code, 200}, - {content_type, ?CONTENT_JSON}, - {payload, [ - {access_token, <<"some access token">>}, - {token_type, <<"Bearer">>} - ]} +#{request => + #{ + method => <<"POST">>, + path => ?MOCK_TOKEN_ENDPOINT, + parameters => [ + {?REQUEST_CLIENT_ID, <<"guest">>}, + {?REQUEST_CLIENT_SECRET, <<"password">>} + ] + }, + response => [ + {code, 200}, + {content_type, ?CONTENT_JSON}, + {payload, [ + {access_token, <<"some access token">>}, + {token_type, <<"Bearer">>} + ]} ] }). -define(DENIES_ACCESS_TOKEN, -#{request => #{ - method => <<"POST">>, - path => ?MOCK_TOKEN_ENDPOINT, - parameters => [ - {?REQUEST_CLIENT_ID, <<"invalid_client">>}, - {?REQUEST_CLIENT_SECRET, <<"password">>} +#{request => + #{ + method => <<"POST">>, + path => ?MOCK_TOKEN_ENDPOINT, + parameters => [ + {?REQUEST_CLIENT_ID, <<"invalid_client">>}, + {?REQUEST_CLIENT_SECRET, <<"password">>} + ] + }, + response => [ + {code, 400}, + {content_type, ?CONTENT_JSON}, + {payload, [ + {error, <<"invalid_client">>}, + {error_description, <<"invalid client found">>} + ]} ] - }, - response => [ - {code, 400}, - {content_type, ?CONTENT_JSON}, - {payload, [ - {error, <<"invalid_client">>}, - {error_description, <<"invalid client found">>} - ]} - ] }). -define(AUTH_SERVER_ERROR, -#{request => #{ - method => <<"POST">>, - path => ?MOCK_TOKEN_ENDPOINT, - parameters => [ - {?REQUEST_CLIENT_ID, <<"guest">>}, - {?REQUEST_CLIENT_SECRET, <<"password">>} +#{request => + #{ + method => <<"POST">>, + path => ?MOCK_TOKEN_ENDPOINT, + parameters => [ + {?REQUEST_CLIENT_ID, <<"guest">>}, + {?REQUEST_CLIENT_SECRET, <<"password">>} + ] + }, + response => [ + {code, 500} ] - }, - response => [ - {code, 500} - ] }). -define(NON_JSON_PAYLOAD, -#{request => #{ - method => <<"POST">>, - path => ?MOCK_TOKEN_ENDPOINT, - parameters => [ - {?REQUEST_CLIENT_ID, <<"guest">>}, - {?REQUEST_CLIENT_SECRET, <<"password">>} +#{request => + #{ + method => <<"POST">>, + path => ?MOCK_TOKEN_ENDPOINT, + parameters => [ + {?REQUEST_CLIENT_ID, <<"guest">>}, + {?REQUEST_CLIENT_SECRET, <<"password">>} + ] + }, + response => [ + {code, 400}, + {content_type, ?CONTENT_JSON}, + {payload, <<"{ some illegal json}">>} ] - }, - response => [ - {code, 400}, - {content_type, ?CONTENT_JSON}, - {payload, <<"{ some illegal json}">>} - ] }). -define(GET_OPENID_CONFIGURATION, -#{request => #{ - method => <<"GET">>, - path => ?DEFAULT_OPENID_CONFIGURATION_PATH - }, - response => [ - {code, 200}, - {content_type, ?CONTENT_JSON}, - {payload, [ - {issuer, build_issuer("http") }, - {authorization_endpoint, <<"http://localhost:8000/authorize">>}, - {token_endpoint, build_token_endpoint_uri("http")}, - {jwks_uri, build_jwks_uri("http")} - ]} +#{request => + #{ + method => <<"GET">>, + path => ?DEFAULT_OPENID_CONFIGURATION_PATH + }, + response => [ + {code, 200}, + {content_type, ?CONTENT_JSON}, + {payload, [ + {issuer, build_issuer("http") }, + {authorization_endpoint, <<"http://localhost:8000/authorize">>}, + {token_endpoint, build_token_endpoint_uri("http")}, + {jwks_uri, build_jwks_uri("http")} + ]} ] }). -define(GET_OPENID_CONFIGURATION_WITH_SSL, -#{request => #{ - method => <<"GET">>, - path => ?DEFAULT_OPENID_CONFIGURATION_PATH - }, - response => [ - {code, 200}, - {content_type, ?CONTENT_JSON}, - {payload, [ - {issuer, build_issuer("https") }, - {authorization_endpoint, <<"https://localhost:8000/authorize">>}, - {token_endpoint, build_token_endpoint_uri("https")}, - {jwks_uri, build_jwks_uri("https")} - ]} - ] +#{request => + #{ + method => <<"GET">>, + path => ?DEFAULT_OPENID_CONFIGURATION_PATH + }, + response => [ + {code, 200}, + {content_type, ?CONTENT_JSON}, + {payload, [ + {issuer, build_issuer("https") }, + {authorization_endpoint, <<"https://localhost:8000/authorize">>}, + {token_endpoint, build_token_endpoint_uri("https")}, + {jwks_uri, build_jwks_uri("https")} + ]} + ] }). -define(GRANTS_REFRESH_TOKEN, -#{request => #{ - method => <<"POST">>, - path => ?MOCK_TOKEN_ENDPOINT, - parameters => [ - {?REQUEST_CLIENT_ID, <<"guest">>}, - {?REQUEST_CLIENT_SECRET, <<"password">>}, - {?REQUEST_REFRESH_TOKEN, <<"some refresh token">>} + #{request => #{ + method => <<"POST">>, + path => ?MOCK_TOKEN_ENDPOINT, + parameters => [ + {?REQUEST_CLIENT_ID, <<"guest">>}, + {?REQUEST_CLIENT_SECRET, <<"password">>}, + {?REQUEST_REFRESH_TOKEN, <<"some refresh token">>} + ] + }, + response => [ + {code, 200}, + {content_type, ?CONTENT_JSON}, + {payload, [ + {access_token, <<"some refreshed access token">>}, + {token_type, <<"Bearer">>} + ]} ] - }, - response => [ - {code, 200}, - {content_type, ?CONTENT_JSON}, - {payload, [ - {access_token, <<"some refreshed access token">>}, - {token_type, <<"Bearer">>} - ]} - ] }). all() -> [ - {group, http_up} - ,{group, http_down} - ,{group, https} + {group, http_up}, + {group, http_down}, + {group, https} ]. groups() -> [ - {http_up, [], [ - {group, verify_access_token}, - {group, with_all_oauth_provider_settings}, - {group, without_all_oauth_providers_settings} - ]}, - {with_all_oauth_provider_settings, [], [ - {group, verify_get_oauth_provider} - ]}, - {without_all_oauth_providers_settings, [], [ - {group, verify_get_oauth_provider} - ]}, - {verify_access_token, [], [ - grants_access_token, - denies_access_token, - auth_server_error, - non_json_payload, - grants_refresh_token, - grants_access_token_using_oauth_provider_id - ]}, - {verify_get_oauth_provider, [], [ - get_oauth_provider, - get_oauth_provider_given_oauth_provider_id - ]}, - - {http_down, [], [ - connection_error - ]}, - {https, [], [ - grants_access_token, - grants_refresh_token, - ssl_connection_error, - {group, with_all_oauth_provider_settings}, - {group, without_all_oauth_providers_settings} - ]} + {http_up, [], [ + {group, verify_access_token}, + {group, with_all_oauth_provider_settings}, + {group, without_all_oauth_providers_settings} + ]}, + {with_all_oauth_provider_settings, [], [ + {group, verify_get_oauth_provider} + ]}, + {without_all_oauth_providers_settings, [], [ + {group, verify_get_oauth_provider} + ]}, + {verify_access_token, [], [ + grants_access_token, + denies_access_token, + auth_server_error, + non_json_payload, + grants_refresh_token, + grants_access_token_using_oauth_provider_id + ]}, + {verify_get_oauth_provider, [], [ + get_oauth_provider, + get_oauth_provider_given_oauth_provider_id + ]}, + + {http_down, [], [ + connection_error + ]}, + {https, [], [ + grants_access_token, + grants_refresh_token, + ssl_connection_error, + {group, with_all_oauth_provider_settings}, + {group, without_all_oauth_providers_settings} + ]} ]. init_per_suite(Config) -> - [ - {denies_access_token, [ {token_endpoint, ?DENIES_ACCESS_TOKEN} ]}, - {auth_server_error, [ {token_endpoint, ?AUTH_SERVER_ERROR} ]}, - {non_json_payload, [ {token_endpoint, ?NON_JSON_PAYLOAD} ]}, - {grants_refresh_token, [ {token_endpoint, ?GRANTS_REFRESH_TOKEN} ]} - + [ + {denies_access_token, [ {token_endpoint, ?DENIES_ACCESS_TOKEN} ]}, + {auth_server_error, [ {token_endpoint, ?AUTH_SERVER_ERROR} ]}, + {non_json_payload, [ {token_endpoint, ?NON_JSON_PAYLOAD} ]}, + {grants_refresh_token, [ {token_endpoint, ?GRANTS_REFRESH_TOKEN} ]} | Config]. end_per_suite(Config) -> - Config. + Config. init_per_group(https, Config) -> - {ok, _} = application:ensure_all_started(ssl), - application:ensure_all_started(cowboy), - Config0 = rabbit_ct_helpers:run_setup_steps(Config), - CertsDir = ?config(rmq_certsdir, Config0), - CaCertFile = filename:join([CertsDir, "testca", "cacert.pem"]), - WrongCaCertFile = filename:join([CertsDir, "server", "server.pem"]), - [{group, https}, - {oauth_provider_id, <<"uaa">>}, - {oauth_provider, build_https_oauth_provider(CaCertFile)}, - {oauth_provider_with_issuer, keep_only_issuer_and_ssl_options(build_https_oauth_provider(CaCertFile))}, - {issuer, build_issuer("https")}, - {oauth_provider_with_wrong_ca, build_https_oauth_provider(WrongCaCertFile)} | - Config0]; + {ok, _} = application:ensure_all_started(ssl), + application:ensure_all_started(cowboy), + Config0 = rabbit_ct_helpers:run_setup_steps(Config), + CertsDir = ?config(rmq_certsdir, Config0), + CaCertFile = filename:join([CertsDir, "testca", "cacert.pem"]), + WrongCaCertFile = filename:join([CertsDir, "server", "server.pem"]), + [{group, https}, + {oauth_provider_id, <<"uaa">>}, + {oauth_provider, build_https_oauth_provider(CaCertFile)}, + {oauth_provider_with_issuer, keep_only_issuer_and_ssl_options(build_https_oauth_provider(CaCertFile))}, + {issuer, build_issuer("https")}, + {oauth_provider_with_wrong_ca, build_https_oauth_provider(WrongCaCertFile)} | + Config0]; init_per_group(http_up, Config) -> - {ok, _} = application:ensure_all_started(inets), - application:ensure_all_started(cowboy), - [{group, http_up}, - {oauth_provider_id, <<"uaa">>}, - {issuer, build_issuer("http")}, - {oauth_provider_with_issuer, keep_only_issuer_and_ssl_options(build_http_oauth_provider())}, - {oauth_provider, build_http_oauth_provider()} | Config]; + {ok, _} = application:ensure_all_started(inets), + application:ensure_all_started(cowboy), + [{group, http_up}, + {oauth_provider_id, <<"uaa">>}, + {issuer, build_issuer("http")}, + {oauth_provider_with_issuer, keep_only_issuer_and_ssl_options(build_http_oauth_provider())}, + {oauth_provider, build_http_oauth_provider()} | Config]; init_per_group(http_down, Config) -> - [{issuer, build_issuer("http")}, - {oauth_provider_id, <<"uaa">>}, - {oauth_provider, build_http_oauth_provider()} | Config]; + [{issuer, build_issuer("http")}, + {oauth_provider_id, <<"uaa">>}, + {oauth_provider, build_http_oauth_provider()} | Config]; init_per_group(with_all_oauth_provider_settings, Config) -> - [{with_all_oauth_provider_settings, true} | Config]; + [{with_all_oauth_provider_settings, true} | Config]; init_per_group(without_all_oauth_providers_settings, Config) -> - [{with_all_oauth_provider_settings, false} | Config]; + [{with_all_oauth_provider_settings, false} | Config]; init_per_group(_, Config) -> - Config. + Config. get_http_oauth_server_expectations(TestCase, Config) -> - case ?config(TestCase, Config) of - undefined -> case ?config(group, Config) of - https -> [ + case ?config(TestCase, Config) of + undefined -> + case ?config(group, Config) of + https -> [ {token_endpoint, ?GRANT_ACCESS_TOKEN}, {get_openid_configuration, ?GET_OPENID_CONFIGURATION_WITH_SSL } ]; - _ -> [ + _ -> [ {token_endpoint, ?GRANT_ACCESS_TOKEN}, {get_openid_configuration, ?GET_OPENID_CONFIGURATION } - ] - end; - Expectations -> Expectations - end. + ] + end; + Expectations -> Expectations + end. lookup_expectation(Endpoint, Config) -> - proplists:get_value(Endpoint, ?config(oauth_server_expectations, Config)). + proplists:get_value(Endpoint, ?config(oauth_server_expectations, Config)). configure_all_oauth_provider_settings(Config) -> - OAuthProvider = ?config(oauth_provider, Config), - OAuthProviders = #{ ?config(oauth_provider_id, Config) => oauth_provider_to_proplist(OAuthProvider) }, - - application:set_env(rabbitmq_auth_backend_oauth2, issuer, OAuthProvider#oauth_provider.issuer), - application:set_env(rabbitmq_auth_backend_oauth2, oauth_providers, OAuthProviders), - application:set_env(rabbitmq_auth_backend_oauth2, token_endpoint, OAuthProvider#oauth_provider.token_endpoint), - KeyConfig = [ { jwks_url, OAuthProvider#oauth_provider.jwks_uri } ] ++ - case OAuthProvider#oauth_provider.ssl_options of - undefined -> []; - _ -> [ {peer_verification, proplists:get_value(verify, OAuthProvider#oauth_provider.ssl_options) }, - {cacertfile, proplists:get_value(cacertfile, OAuthProvider#oauth_provider.ssl_options) } ] - end, - application:set_env(rabbitmq_auth_backend_oauth2, key_config, KeyConfig). + OAuthProvider = ?config(oauth_provider, Config), + OAuthProviders = #{ ?config(oauth_provider_id, Config) => oauth_provider_to_proplist(OAuthProvider) }, + + application:set_env(rabbitmq_auth_backend_oauth2, issuer, OAuthProvider#oauth_provider.issuer), + application:set_env(rabbitmq_auth_backend_oauth2, oauth_providers, OAuthProviders), + application:set_env(rabbitmq_auth_backend_oauth2, token_endpoint, OAuthProvider#oauth_provider.token_endpoint), + KeyConfig = [ { jwks_url, OAuthProvider#oauth_provider.jwks_uri } ] ++ + case OAuthProvider#oauth_provider.ssl_options of + undefined -> + []; + _ -> + [ {peer_verification, proplists:get_value(verify, OAuthProvider#oauth_provider.ssl_options) }, + {cacertfile, proplists:get_value(cacertfile, OAuthProvider#oauth_provider.ssl_options) } ] + end, + application:set_env(rabbitmq_auth_backend_oauth2, key_config, KeyConfig). configure_minimum_oauth_provider_settings(Config) -> - OAuthProvider = ?config(oauth_provider_with_issuer, Config), - OAuthProviders = #{ ?config(oauth_provider_id, Config) => oauth_provider_to_proplist(OAuthProvider) }, - application:set_env(rabbitmq_auth_backend_oauth2, oauth_providers, OAuthProviders), - application:set_env(rabbitmq_auth_backend_oauth2, issuer, OAuthProvider#oauth_provider.issuer), - KeyConfig = - case OAuthProvider#oauth_provider.ssl_options of - undefined -> []; - _ -> [ {peer_verification, proplists:get_value(verify, OAuthProvider#oauth_provider.ssl_options) }, - {cacertfile, proplists:get_value(cacertfile, OAuthProvider#oauth_provider.ssl_options) } ] - end, - application:set_env(rabbitmq_auth_backend_oauth2, key_config, KeyConfig). + OAuthProvider = ?config(oauth_provider_with_issuer, Config), + OAuthProviders = #{ ?config(oauth_provider_id, Config) => oauth_provider_to_proplist(OAuthProvider) }, + application:set_env(rabbitmq_auth_backend_oauth2, oauth_providers, OAuthProviders), + application:set_env(rabbitmq_auth_backend_oauth2, issuer, OAuthProvider#oauth_provider.issuer), + KeyConfig = + case OAuthProvider#oauth_provider.ssl_options of + undefined -> + []; + _ -> + [ {peer_verification, proplists:get_value(verify, OAuthProvider#oauth_provider.ssl_options) }, + {cacertfile, proplists:get_value(cacertfile, OAuthProvider#oauth_provider.ssl_options) } ] + end, + application:set_env(rabbitmq_auth_backend_oauth2, key_config, KeyConfig). init_per_testcase(TestCase, Config) -> - application:set_env(rabbitmq_auth_backend_oauth2, use_global_locks, false), - - case ?config(with_all_oauth_provider_settings, Config) of - false -> configure_minimum_oauth_provider_settings(Config); - true -> configure_all_oauth_provider_settings(Config); - undefined -> configure_all_oauth_provider_settings(Config) - end, - - HttpOauthServerExpectations = get_http_oauth_server_expectations(TestCase, Config), - ListOfExpectations = maps:values(proplists:to_map(HttpOauthServerExpectations)), - - case ?config(group, Config) of - http_up -> - start_http_oauth_server(?AUTH_PORT, ListOfExpectations); - https -> - start_https_oauth_server(?AUTH_PORT, ?config(rmq_certsdir, Config), ListOfExpectations); - _ -> ok - end, - [{oauth_server_expectations, HttpOauthServerExpectations} | Config ]. + application:set_env(rabbitmq_auth_backend_oauth2, use_global_locks, false), + + case ?config(with_all_oauth_provider_settings, Config) of + false -> configure_minimum_oauth_provider_settings(Config); + true -> configure_all_oauth_provider_settings(Config); + undefined -> configure_all_oauth_provider_settings(Config) + end, + + HttpOauthServerExpectations = get_http_oauth_server_expectations(TestCase, Config), + ListOfExpectations = maps:values(proplists:to_map(HttpOauthServerExpectations)), + + case ?config(group, Config) of + http_up -> + start_http_oauth_server(?AUTH_PORT, ListOfExpectations); + https -> + start_https_oauth_server(?AUTH_PORT, ?config(rmq_certsdir, Config), ListOfExpectations); + _ -> + ok + end, + [{oauth_server_expectations, HttpOauthServerExpectations} | Config ]. end_per_testcase(_, Config) -> - application:unset_env(rabbitmq_auth_backend_oauth2, oauth_providers), - application:unset_env(rabbitmq_auth_backend_oauth2, issuer), - application:unset_env(rabbitmq_auth_backend_oauth2, token_endpoint), - application:unset_env(rabbitmq_auth_backend_oauth2, key_config), - case ?config(group, Config) of - http_up -> - stop_http_auth_server(); - https -> - stop_http_auth_server(); - _ -> ok - end, - Config. + application:unset_env(rabbitmq_auth_backend_oauth2, oauth_providers), + application:unset_env(rabbitmq_auth_backend_oauth2, issuer), + application:unset_env(rabbitmq_auth_backend_oauth2, token_endpoint), + application:unset_env(rabbitmq_auth_backend_oauth2, key_config), + case ?config(group, Config) of + http_up -> + stop_http_auth_server(); + https -> + stop_http_auth_server(); + _ -> + ok + end, + Config. end_per_group(https_and_rabbitmq_node, Config) -> - rabbit_ct_helpers:run_steps(Config, rabbit_ct_broker_helpers:teardown_steps()); + rabbit_ct_helpers:run_steps(Config, rabbit_ct_broker_helpers:teardown_steps()); end_per_group(_, Config) -> - Config. + Config. grants_access_token_dynamically_resolving_oauth_provider(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } = lookup_expectation(token_endpoint, Config), + #{request := #{parameters := Parameters}, + response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } = lookup_expectation(token_endpoint, Config), - {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = - oauth2_client:get_access_token(?config(oauth_provider_id, Config), build_access_token_request(Parameters)), + {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = + oauth2_client:get_access_token(?config(oauth_provider_id, Config), build_access_token_request(Parameters)), - ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), - ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). + ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), + ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). grants_access_token_using_oauth_provider_id(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } = lookup_expectation(token_endpoint, Config), + #{request := #{parameters := Parameters}, + response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } = lookup_expectation(token_endpoint, Config), - {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = - oauth2_client:get_access_token(?config(oauth_provider_id, Config), build_access_token_request(Parameters)), - ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), - ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). + {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = + oauth2_client:get_access_token(?config(oauth_provider_id, Config), build_access_token_request(Parameters)), + ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), + ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). grants_access_token(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } - = lookup_expectation(token_endpoint, Config), + #{request := #{parameters := Parameters}, + response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } + = lookup_expectation(token_endpoint, Config), - {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = - oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)), - ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), - ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). + {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = + oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)), + ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), + ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). grants_refresh_token(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } - = lookup_expectation(token_endpoint, Config), + #{request := #{parameters := Parameters}, + response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } + = lookup_expectation(token_endpoint, Config), - {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = - oauth2_client:refresh_access_token(?config(oauth_provider, Config), build_refresh_token_request(Parameters)), - ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), - ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). + {ok, #successful_access_token_response{access_token = AccessToken, token_type = TokenType} } = + oauth2_client:refresh_access_token(?config(oauth_provider, Config), build_refresh_token_request(Parameters)), + ?assertEqual(proplists:get_value(token_type, JsonPayload), TokenType), + ?assertEqual(proplists:get_value(access_token, JsonPayload), AccessToken). denies_access_token(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 400}, {content_type, _CT}, {payload, JsonPayload}] } - = lookup_expectation(token_endpoint, Config), - {error, #unsuccessful_access_token_response{error = Error, error_description = ErrorDescription} } = - oauth2_client:get_access_token(?config(oauth_provider, Config),build_access_token_request(Parameters)), - ?assertEqual(proplists:get_value(error, JsonPayload), Error), - ?assertEqual(proplists:get_value(error_description, JsonPayload), ErrorDescription). + #{request := #{parameters := Parameters}, + response := [ {code, 400}, {content_type, _CT}, {payload, JsonPayload}] } + = lookup_expectation(token_endpoint, Config), + {error, #unsuccessful_access_token_response{error = Error, error_description = ErrorDescription} } = + oauth2_client:get_access_token(?config(oauth_provider, Config),build_access_token_request(Parameters)), + ?assertEqual(proplists:get_value(error, JsonPayload), Error), + ?assertEqual(proplists:get_value(error_description, JsonPayload), ErrorDescription). auth_server_error(Config) -> - #{request := #{parameters := Parameters}, - response := [ {code, 500} ] } = lookup_expectation(token_endpoint, Config), - {error, "Internal Server Error"} = - oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)). + #{request := #{parameters := Parameters}, + response := [ {code, 500} ] } = lookup_expectation(token_endpoint, Config), + {error, "Internal Server Error"} = + oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)). non_json_payload(Config) -> - #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), - {error, {failed_to_decode_json, _ErrorArgs}} = - oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)). + #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), + {error, {failed_to_decode_json, _ErrorArgs}} = + oauth2_client:get_access_token(?config(oauth_provider, Config), build_access_token_request(Parameters)). connection_error(Config) -> - #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), - {error, {failed_connect, _ErrorArgs} } = oauth2_client:get_access_token( - ?config(oauth_provider, Config), build_access_token_request(Parameters)). + #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), + {error, {failed_connect, _ErrorArgs} } = oauth2_client:get_access_token( + ?config(oauth_provider, Config), build_access_token_request(Parameters)). ssl_connection_error(Config) -> - #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), + #{request := #{parameters := Parameters}} = lookup_expectation(token_endpoint, Config), - {error, {failed_connect, _} } = oauth2_client:get_access_token( - ?config(oauth_provider_with_wrong_ca, Config), build_access_token_request(Parameters)). + {error, {failed_connect, _} } = oauth2_client:get_access_token( + ?config(oauth_provider_with_wrong_ca, Config), build_access_token_request(Parameters)). get_oauth_provider(Config) -> - #{response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } - = lookup_expectation(get_openid_configuration, Config), + #{response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } + = lookup_expectation(get_openid_configuration, Config), - {ok, #oauth_provider{issuer = Issuer, token_endpoint = TokenEndPoint, jwks_uri = Jwks_uri}} = - oauth2_client:get_oauth_provider([issuer, token_endpoint, jwks_uri]), + {ok, #oauth_provider{issuer = Issuer, token_endpoint = TokenEndPoint, jwks_uri = Jwks_uri}} = + oauth2_client:get_oauth_provider([issuer, token_endpoint, jwks_uri]), - ?assertEqual(proplists:get_value(issuer, JsonPayload), Issuer), - ?assertEqual(proplists:get_value(token_endpoint, JsonPayload), TokenEndPoint), - ?assertEqual(proplists:get_value(jwks_uri, JsonPayload), Jwks_uri). + ?assertEqual(proplists:get_value(issuer, JsonPayload), Issuer), + ?assertEqual(proplists:get_value(token_endpoint, JsonPayload), TokenEndPoint), + ?assertEqual(proplists:get_value(jwks_uri, JsonPayload), Jwks_uri). get_oauth_provider_given_oauth_provider_id(Config) -> - #{response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } - = lookup_expectation(get_openid_configuration, Config), + #{response := [ {code, 200}, {content_type, _CT}, {payload, JsonPayload}] } + = lookup_expectation(get_openid_configuration, Config), - ct:log("get_oauth_provider ~p", [?config(oauth_provider_id, Config)]), - {ok, #oauth_provider{issuer = Issuer, token_endpoint = TokenEndPoint, jwks_uri = Jwks_uri}} = - oauth2_client:get_oauth_provider(?config(oauth_provider_id, Config), [issuer, token_endpoint, jwks_uri]), + ct:log("get_oauth_provider ~p", [?config(oauth_provider_id, Config)]), + {ok, #oauth_provider{issuer = Issuer, token_endpoint = TokenEndPoint, jwks_uri = Jwks_uri}} = + oauth2_client:get_oauth_provider(?config(oauth_provider_id, Config), [issuer, token_endpoint, jwks_uri]), - ?assertEqual(proplists:get_value(issuer, JsonPayload), Issuer), - ?assertEqual(proplists:get_value(token_endpoint, JsonPayload), TokenEndPoint), - ?assertEqual(proplists:get_value(jwks_uri, JsonPayload), Jwks_uri). + ?assertEqual(proplists:get_value(issuer, JsonPayload), Issuer), + ?assertEqual(proplists:get_value(token_endpoint, JsonPayload), TokenEndPoint), + ?assertEqual(proplists:get_value(jwks_uri, JsonPayload), Jwks_uri). %%% HELPERS build_issuer(Scheme) -> - uri_string:recompose(#{scheme => Scheme, + uri_string:recompose(#{scheme => Scheme, host => "localhost", port => rabbit_data_coercion:to_integer(?AUTH_PORT), path => ""}). build_token_endpoint_uri(Scheme) -> - uri_string:recompose(#{scheme => Scheme, + uri_string:recompose(#{scheme => Scheme, host => "localhost", port => rabbit_data_coercion:to_integer(?AUTH_PORT), path => "/token"}). build_jwks_uri(Scheme) -> - uri_string:recompose(#{scheme => Scheme, + uri_string:recompose(#{scheme => Scheme, host => "localhost", port => rabbit_data_coercion:to_integer(?AUTH_PORT), path => "/certs"}). build_access_token_request(Request) -> - #access_token_request { - client_id = proplists:get_value(?REQUEST_CLIENT_ID, Request), - client_secret = proplists:get_value(?REQUEST_CLIENT_SECRET, Request) - }. + #access_token_request { + client_id = proplists:get_value(?REQUEST_CLIENT_ID, Request), + client_secret = proplists:get_value(?REQUEST_CLIENT_SECRET, Request) + }. build_refresh_token_request(Request) -> - #refresh_token_request{ - client_id = proplists:get_value(?REQUEST_CLIENT_ID, Request), - client_secret = proplists:get_value(?REQUEST_CLIENT_SECRET, Request), - refresh_token = proplists:get_value(?REQUEST_REFRESH_TOKEN, Request) - }. + #refresh_token_request{ + client_id = proplists:get_value(?REQUEST_CLIENT_ID, Request), + client_secret = proplists:get_value(?REQUEST_CLIENT_SECRET, Request), + refresh_token = proplists:get_value(?REQUEST_REFRESH_TOKEN, Request) + }. build_http_oauth_provider() -> - #oauth_provider { - issuer = build_issuer("http"), - token_endpoint = build_token_endpoint_uri("http"), - jwks_uri = build_jwks_uri("http") - }. + #oauth_provider { + issuer = build_issuer("http"), + token_endpoint = build_token_endpoint_uri("http"), + jwks_uri = build_jwks_uri("http") + }. keep_only_issuer_and_ssl_options(OauthProvider) -> #oauth_provider { issuer = OauthProvider#oauth_provider.issuer, ssl_options = OauthProvider#oauth_provider.ssl_options }. build_https_oauth_provider(CaCertFile) -> - #oauth_provider { - issuer = build_issuer("https"), - token_endpoint = build_token_endpoint_uri("https"), - jwks_uri = build_jwks_uri("https"), - ssl_options = ssl_options(verify_peer, false, CaCertFile) - }. + #oauth_provider { + issuer = build_issuer("https"), + token_endpoint = build_token_endpoint_uri("https"), + jwks_uri = build_jwks_uri("https"), + ssl_options = ssl_options(verify_peer, false, CaCertFile) + }. oauth_provider_to_proplist(#oauth_provider{ issuer = Issuer, token_endpoint = TokenEndpoint, - ssl_options = SslOptions, jwks_uri = Jwks_url}) -> - [ { issuer, Issuer}, - {token_endpoint, TokenEndpoint}, - { https, - case SslOptions of - undefined -> []; - Value -> Value - end}, - {jwks_url, Jwks_url} ]. + ssl_options = SslOptions, jwks_uri = Jwks_url}) -> + [ { issuer, Issuer}, + {token_endpoint, TokenEndpoint}, + { https, + case SslOptions of + undefined -> []; + Value -> Value + end}, + {jwks_url, Jwks_url} ]. start_http_oauth_server(Port, Expectations) when is_list(Expectations) -> - Dispatch = cowboy_router:compile([ - {'_', [{Path, oauth_http_mock, Expected} || #{request := #{path := Path}} = Expected <- Expectations ]} - ]), - ct:log("start_http_oauth_server with expectation list : ~p -> dispatch: ~p", [Expectations, Dispatch]), - {ok, _} = cowboy:start_clear(mock_http_auth_listener,[ {port, Port} ], - #{env => #{dispatch => Dispatch}}); + Dispatch = cowboy_router:compile([ + {'_', [{Path, oauth_http_mock, Expected} || #{request := #{path := Path}} = Expected <- Expectations ]} + ]), + ct:log("start_http_oauth_server with expectation list : ~p -> dispatch: ~p", [Expectations, Dispatch]), + {ok, _} = cowboy:start_clear(mock_http_auth_listener,[ {port, Port} ], + #{env => #{dispatch => Dispatch}}); start_http_oauth_server(Port, #{request := #{path := Path}} = Expected) -> - Dispatch = cowboy_router:compile([ - {'_', [{Path, oauth_http_mock, Expected}]} - ]), - ct:log("start_http_oauth_server with expectation : ~p -> dispatch: ~p ", [Expected, Dispatch]), - {ok, _} = cowboy:start_clear( - mock_http_auth_listener, - [{port, Port} - ], - #{env => #{dispatch => Dispatch}}). + Dispatch = cowboy_router:compile([ + {'_', [{Path, oauth_http_mock, Expected}]} + ]), + ct:log("start_http_oauth_server with expectation : ~p -> dispatch: ~p ", [Expected, Dispatch]), + {ok, _} = cowboy:start_clear( + mock_http_auth_listener, + [{port, Port} + ], + #{env => #{dispatch => Dispatch}}). start_https_oauth_server(Port, CertsDir, Expectations) when is_list(Expectations) -> - Dispatch = cowboy_router:compile([ - {'_', [{Path, oauth_http_mock, Expected} || #{request := #{path := Path}} = Expected <- Expectations ]} - ]), - ct:log("start_https_oauth_server with expectation list : ~p -> dispatch: ~p", [Expectations, Expectations]), - {ok, _} = cowboy:start_tls( - mock_http_auth_listener, - [{port, Port}, - {certfile, filename:join([CertsDir, "server", "cert.pem"])}, - {keyfile, filename:join([CertsDir, "server", "key.pem"])} - ], - #{env => #{dispatch => Dispatch}}); + Dispatch = cowboy_router:compile([ + {'_', [{Path, oauth_http_mock, Expected} || #{request := #{path := Path}} = Expected <- Expectations ]} + ]), + ct:log("start_https_oauth_server with expectation list : ~p -> dispatch: ~p", [Expectations, Expectations]), + {ok, _} = cowboy:start_tls( + mock_http_auth_listener, + [{port, Port}, + {certfile, filename:join([CertsDir, "server", "cert.pem"])}, + {keyfile, filename:join([CertsDir, "server", "key.pem"])} + ], + #{env => #{dispatch => Dispatch}}); start_https_oauth_server(Port, CertsDir, #{request := #{path := Path}} = Expected) -> - Dispatch = cowboy_router:compile([{'_', [{Path, oauth_http_mock, Expected}]}]), - ct:log("start_https_oauth_server with expectation : ~p -> dispatch: ~p", [Expected, Dispatch]), - {ok, _} = cowboy:start_tls( - mock_http_auth_listener, - [{port, Port}, - {certfile, filename:join([CertsDir, "server", "cert.pem"])}, - {keyfile, filename:join([CertsDir, "server", "key.pem"])} - ], - #{env => #{dispatch => Dispatch}}). + Dispatch = cowboy_router:compile([{'_', [{Path, oauth_http_mock, Expected}]}]), + ct:log("start_https_oauth_server with expectation : ~p -> dispatch: ~p", [Expected, Dispatch]), + {ok, _} = cowboy:start_tls( + mock_http_auth_listener, + [{port, Port}, + {certfile, filename:join([CertsDir, "server", "cert.pem"])}, + {keyfile, filename:join([CertsDir, "server", "key.pem"])} + ], + #{env => #{dispatch => Dispatch}}). stop_http_auth_server() -> - cowboy:stop_listener(mock_http_auth_listener). + cowboy:stop_listener(mock_http_auth_listener). -spec ssl_options(ssl:verify_type(), boolean(), file:filename()) -> list(). ssl_options(PeerVerification, FailIfNoPeerCert, CaCertFile) -> - [{verify, PeerVerification}, - {depth, 10}, - {fail_if_no_peer_cert, FailIfNoPeerCert}, - {crl_check, false}, - {crl_cache, {ssl_crl_cache, {internal, [{http, 10000}]}}}, - {cacertfile, CaCertFile}]. + [{verify, PeerVerification}, + {depth, 10}, + {fail_if_no_peer_cert, FailIfNoPeerCert}, + {crl_check, false}, + {crl_cache, {ssl_crl_cache, {internal, [{http, 10000}]}}}, + {cacertfile, CaCertFile}]. diff --git a/deps/oauth2_client/test/unit_SUITE.erl b/deps/oauth2_client/test/unit_SUITE.erl index 0fce5c37bba5..0ffa6304ad14 100644 --- a/deps/oauth2_client/test/unit_SUITE.erl +++ b/deps/oauth2_client/test/unit_SUITE.erl @@ -25,123 +25,123 @@ all() -> groups() -> [ - {ssl_options, [], [ - no_ssl_options_triggers_verify_peer, - choose_verify_over_peer_verification, - verify_set_to_verify_none, - peer_verification_set_to_verify_none, - peer_verification_set_to_verify_peer_with_cacertfile, - verify_set_to_verify_peer_with_cacertfile - ]}, - {get_expiration_time, [], [ - access_token_response_without_expiration_time, - access_token_response_with_expires_in, - access_token_response_with_exp_in_access_token - ]} + {ssl_options, [], [ + no_ssl_options_triggers_verify_peer, + choose_verify_over_peer_verification, + verify_set_to_verify_none, + peer_verification_set_to_verify_none, + peer_verification_set_to_verify_peer_with_cacertfile, + verify_set_to_verify_peer_with_cacertfile + ]}, + {get_expiration_time, [], [ + access_token_response_without_expiration_time, + access_token_response_with_expires_in, + access_token_response_with_exp_in_access_token + ]} ]. no_ssl_options_triggers_verify_peer(_) -> - ?assertMatch([ - {verify, verify_peer}, - {depth, 10}, - {crl_check,false}, - {fail_if_no_peer_cert,false}, - {cacerts, _CaCerts} - ], oauth2_client:extract_ssl_options_as_list(#{})). + ?assertMatch([ + {verify, verify_peer}, + {depth, 10}, + {crl_check,false}, + {fail_if_no_peer_cert,false}, + {cacerts, _CaCerts} + ], oauth2_client:extract_ssl_options_as_list(#{})). choose_verify_over_peer_verification(_) -> - Expected1 = [ - {verify, verify_none} - ], - ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list( - #{verify => verify_none, peer_verification => verify_peer })). + Expected1 = [ + {verify, verify_none} + ], + ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list( + #{verify => verify_none, peer_verification => verify_peer })). verify_set_to_verify_none(_) -> - Expected1 = [ - {verify, verify_none} - ], - ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list(#{verify => verify_none})), + Expected1 = [ + {verify, verify_none} + ], + ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list(#{verify => verify_none})), - Expected2 = [ - {verify, verify_none} - ], - ?assertEqual(Expected2, oauth2_client:extract_ssl_options_as_list(#{ - verify => verify_none, - cacertfile => "/tmp" - })). + Expected2 = [ + {verify, verify_none} + ], + ?assertEqual(Expected2, oauth2_client:extract_ssl_options_as_list(#{ + verify => verify_none, + cacertfile => "/tmp" + })). peer_verification_set_to_verify_none(_) -> - Expected1 = [ - {verify, verify_none} - ], - ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list(#{peer_verification => verify_none})), + Expected1 = [ + {verify, verify_none} + ], + ?assertEqual(Expected1, oauth2_client:extract_ssl_options_as_list(#{peer_verification => verify_none})), - Expected2 = [ - {verify, verify_none} - ], - ?assertEqual(Expected2, oauth2_client:extract_ssl_options_as_list(#{ - peer_verification => verify_none, - cacertfile => "/tmp" - })). + Expected2 = [ + {verify, verify_none} + ], + ?assertEqual(Expected2, oauth2_client:extract_ssl_options_as_list(#{ + peer_verification => verify_none, + cacertfile => "/tmp" + })). peer_verification_set_to_verify_peer_with_cacertfile(_) -> - Expected = [ - {verify, verify_peer}, - {depth, 10}, - {crl_check,false}, - {fail_if_no_peer_cert,false}, - {cacertfile, "/tmp"} - ], - ?assertEqual(Expected, oauth2_client:extract_ssl_options_as_list(#{ - cacertfile => "/tmp", - peer_verification => verify_peer - })). + Expected = [ + {verify, verify_peer}, + {depth, 10}, + {crl_check,false}, + {fail_if_no_peer_cert,false}, + {cacertfile, "/tmp"} + ], + ?assertEqual(Expected, oauth2_client:extract_ssl_options_as_list(#{ + cacertfile => "/tmp", + peer_verification => verify_peer + })). verify_set_to_verify_peer_with_cacertfile(_) -> - Expected = [ - {verify, verify_peer}, - {depth, 10}, - {crl_check,false}, - {fail_if_no_peer_cert,false}, - {cacertfile, "/tmp"} - ], - ?assertEqual(Expected, oauth2_client:extract_ssl_options_as_list(#{ - cacertfile => "/tmp", - verify => verify_peer - })). + Expected = [ + {verify, verify_peer}, + {depth, 10}, + {crl_check,false}, + {fail_if_no_peer_cert,false}, + {cacertfile, "/tmp"} + ], + ?assertEqual(Expected, oauth2_client:extract_ssl_options_as_list(#{ + cacertfile => "/tmp", + verify => verify_peer + })). access_token_response_with_expires_in(_) -> - Jwk = ?UTIL_MOD:fixture_jwk(), - ExpiresIn = os:system_time(seconds), - AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), - {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), - AccessTokenResponse = #successful_access_token_response{ - access_token = EncodedToken, - expires_in = ExpiresIn - }, - ?assertEqual({ok, [{expires_in, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). + Jwk = ?UTIL_MOD:fixture_jwk(), + ExpiresIn = os:system_time(seconds), + AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken, + expires_in = ExpiresIn + }, + ?assertEqual({ok, [{expires_in, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). access_token_response_with_exp_in_access_token(_) -> - Jwk = ?UTIL_MOD:fixture_jwk(), - ExpiresIn = os:system_time(seconds), - AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), - {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), - AccessTokenResponse = #successful_access_token_response{ - access_token = EncodedToken - }, - ?assertEqual({ok, [{exp, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). + Jwk = ?UTIL_MOD:fixture_jwk(), + ExpiresIn = os:system_time(seconds), + AccessToken = ?UTIL_MOD:expirable_token_with_expiration_time(ExpiresIn), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken + }, + ?assertEqual({ok, [{exp, ExpiresIn}]}, oauth2_client:get_expiration_time(AccessTokenResponse)). access_token_response_without_expiration_time(_) -> - Jwk = ?UTIL_MOD:fixture_jwk(), - AccessToken = maps:remove(<<"exp">>, ?UTIL_MOD:fixture_token()), - ct:log("AccesToken ~p", [AccessToken]), - {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), - AccessTokenResponse = #successful_access_token_response{ - access_token = EncodedToken - }, - ct:log("AccessTokenResponse ~p", [AccessTokenResponse]), - ?assertEqual({error, missing_exp_field}, oauth2_client:get_expiration_time(AccessTokenResponse)). + Jwk = ?UTIL_MOD:fixture_jwk(), + AccessToken = maps:remove(<<"exp">>, ?UTIL_MOD:fixture_token()), + ct:log("AccesToken ~p", [AccessToken]), + {_, EncodedToken} = ?UTIL_MOD:sign_token_hs(AccessToken, Jwk), + AccessTokenResponse = #successful_access_token_response{ + access_token = EncodedToken + }, + ct:log("AccessTokenResponse ~p", [AccessTokenResponse]), + ?assertEqual({error, missing_exp_field}, oauth2_client:get_expiration_time(AccessTokenResponse)).