Skip to content
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
80acc89
Add scope to oauth2 filter proto file
Nov 3, 2020
c276e54
Use configured scopes in authorizarion request
andreyprezotto Nov 3, 2020
d26dd3a
Initialize member in the correct order
andreyprezotto Nov 4, 2020
1577ed6
Update proto files after proto_format.sh
andreyprezotto Nov 4, 2020
47f1fa4
Fix oauth filter tests
andreyprezotto Nov 4, 2020
906a91f
fix semicolon
andreyprezotto Nov 5, 2020
94fa8b1
fix tests
andreyprezotto Nov 5, 2020
2fdf64a
fix tests
andreyprezotto Nov 5, 2020
7c689b9
fix tests after rebase
andreyprezotto Nov 5, 2020
6549060
Add debug log for test
andreyprezotto Nov 6, 2020
5e709f9
Add debug log for test
andreyprezotto Nov 6, 2020
c2567ec
Auth_scope default value if config wasn't set
andreyprezotto Nov 13, 2020
657e21f
add config test for default user
andreyprezotto Nov 13, 2020
a7acd87
add config test for default user
andreyprezotto Nov 13, 2020
5381f74
Revert "Auth_scope default value if config wasn't set"
andreyprezotto Nov 13, 2020
4d9eab9
Revert "Revert "Auth_scope default value if config wasn't set""
andreyprezotto Nov 13, 2020
5e126b9
revert implementation
andreyprezotto Nov 13, 2020
b64e322
change defaul value implementation
andreyprezotto Nov 13, 2020
7359ad3
fix with .empty
andreyprezotto Nov 13, 2020
62f1ff4
fix semicolon
andreyprezotto Nov 13, 2020
b3c2071
fix property name
andreyprezotto Nov 13, 2020
a18a184
semicolon
andreyprezotto Nov 13, 2020
2aa7274
fix tests
andreyprezotto Nov 13, 2020
a097339
Add auth_scopes to the docs
andreyprezotto Nov 16, 2020
47598a2
Update Release Notes
andreyprezotto Nov 16, 2020
6cca203
Fix colon in docs
andreyprezotto Nov 16, 2020
a5d64d0
Fix release notes
andreyprezotto Nov 16, 2020
5aef557
Fix formatting
andreyprezotto Nov 16, 2020
b956a6e
Fix documentation
andreyprezotto Nov 16, 2020
e8393a7
include default value in proto field comment
andreyprezotto Nov 18, 2020
9fa051d
Merge remote-tracking branch 'upstream/master' into oauth_scope
andreyprezotto Nov 24, 2020
ee4cb01
check_format: line order
andreyprezotto Nov 25, 2020
40fe4b8
add missing api_shadow proto files
andreyprezotto Nov 25, 2020
966e04c
Code review changes
andreyprezotto Nov 20, 2020
5109f3e
check_format: fix
andreyprezotto Nov 25, 2020
0e05c16
fix filter_test formatting
andreyprezotto Nov 25, 2020
ecf6616
correct emptyness check
andreyprezotto Nov 26, 2020
21b9d65
Code review changes
andreyprezotto Nov 30, 2020
527a144
Merge branch 'oauth_changes' into oauth_scope
andreyprezotto Dec 1, 2020
f4226a4
Code review changes
andreyprezotto Dec 9, 2020
82fd52b
Refactor OAuth2Test for init config flexibility
andreyprezotto Dec 10, 2020
4625f33
Merge branch 'oauth_review2' into oauth_scope
andreyprezotto Dec 10, 2020
c936cbb
Merge remote-tracking branch 'upstream/master' into oauth_scope
andreyprezotto Dec 10, 2020
aedc096
Fix doc link to field
andreyprezotto Dec 12, 2020
897b290
format fix
andreyprezotto Dec 15, 2020
9705b0d
move encoding logic to config
andreyprezotto Dec 15, 2020
a83fd6f
Merge remote-tracking branch 'upstream/master' into oauth_scope
andreyprezotto Jan 12, 2021
ab0a563
Merge branch 'oauth_scope' of github.com:andreyprezotto/envoy into oa…
andreyprezotto Jan 12, 2021
f9f9f7a
Update current.rst to match master's content
andreyprezotto Jan 12, 2021
f0efcf4
format fix
andreyprezotto Jan 12, 2021
be36649
Change filter stopinteration
andreyprezotto Jan 21, 2021
6c9c0d9
Merge remote-tracking branch 'upstream/master' into oauth_scope
andreyprezotto Jan 21, 2021
8da1892
Change test to use encodedAuthScopes
andreyprezotto Jan 21, 2021
0a33292
remove authScopes
andreyprezotto Jan 21, 2021
e63ec2b
remove authScopes
andreyprezotto Jan 21, 2021
f2cdd88
remove authScopes
andreyprezotto Jan 21, 2021
96ebfcd
Update filter.cc (#1)
ngoyal16 Jan 22, 2021
9fc7acb
Retest CI
andreyprezotto Jan 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion api/envoy/extensions/filters/http/oauth2/v3alpha/oauth.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ message OAuth2Credentials {

// OAuth config
//
// [#next-free-field: 9]
// [#next-free-field: 10]
message OAuth2Config {
// Endpoint on the authorization server to retrieve the access token from.
config.core.v3.HttpUri token_endpoint = 1;
Expand Down Expand Up @@ -74,6 +74,11 @@ message OAuth2Config {

// Any request that matches any of the provided matchers will be passed through without OAuth validation.
repeated config.route.v3.HeaderMatcher pass_through_matcher = 8;

// Optional list of OAuth scopes to be claimed in the authorization request. If not specified,
// defaults to "user" scope.
Comment thread
htuch marked this conversation as resolved.
// OAuth RFC https://tools.ietf.org/html/rfc6749#section-3.3
repeated string auth_scopes = 9;
}

// Filter config.
Expand Down
7 changes: 6 additions & 1 deletion api/envoy/extensions/filters/http/oauth2/v4alpha/oauth.proto

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions docs/root/configuration/http/http_filters/oauth2_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ The following is an example configuring the filter.
name: hmac
sds_config:
path: "/etc/envoy/hmac.yaml"
# (Optional): defaults to 'user' scope if not provided
auth_scopes:
- user
- openid
- email

Below is a complete code example of how we employ the filter as one of
:ref:`HttpConnectionManager HTTP filters
Expand Down Expand Up @@ -114,6 +119,11 @@ Below is a complete code example of how we employ the filter as one of
name: hmac
sds_config:
path: "/etc/envoy/hmac.yaml"
# (Optional): defaults to 'user' scope if not provided
auth_scopes:
- user
- openid
- email
- name: envoy.router
tracing: {}
codec_type: "AUTO"
Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Minor Behavior Changes
* jwt_authn filter: added support of Jwt time constraint verification with a clock skew (default to 60 seconds) and added a filter config field :ref:`clock_skew_seconds <envoy_v3_api_field_extensions.filters.http.jwt_authn.v3.JwtProvider.clock_skew_seconds>` to configure it.
* memory: enable new tcmalloc with restartable sequences for aarch64 builds.
* mongo proxy metrics: swapped network connection remote and local closed counters previously set reversed (`cx_destroy_local_with_active_rq` and `cx_destroy_remote_with_active_rq`).
* oauth filter: added the optional parameter :ref:`auth_scopes <config_http_filters_oauth>` with default value of 'user' if not provided. Enables this value to be overridden in the Authorization request to the OAuth provider.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you have this link to the field? Should be lots of examples in this file

* tls: removed RSA key transport and SHA-1 cipher suites from the client-side defaults.
* watchdog: the watchdog action :ref:`abort_action <envoy_v3_api_msg_watchdog.v3alpha.AbortActionConfig>` is now the default action to terminate the process if watchdog kill / multikill is enabled.
* xds: to support TTLs, heartbeating has been added to xDS. As a result, responses that contain empty resources without updating the version will no longer be propagated to the
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions source/extensions/filters/http/oauth2/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ secretsProvider(const envoy::extensions::transport_sockets::tls::v3::SdsSecretCo
return secret_manager.findStaticGenericSecretProvider(config.name());
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

} // namespace

Http::FilterFactoryCb OAuth2Config::createFilterFactoryFromProtoTyped(
Expand Down
27 changes: 25 additions & 2 deletions source/extensions/filters/http/oauth2/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ constexpr const char* CookieTailHttpOnlyFormatString =
";version=1;path=/;Max-Age={};secure;HttpOnly";

const char* AuthorizationEndpointFormat =
"{}?client_id={}&scope=user&response_type=code&redirect_uri={}&state={}";
"{}?client_id={}&scope={}&response_type=code&redirect_uri={}&state={}";

constexpr absl::string_view UnauthorizedBodyMessage = "OAuth flow failed.";

Expand All @@ -60,6 +60,7 @@ constexpr absl::string_view REDIRECT_RACE = "oauth.race_redirect";
constexpr absl::string_view REDIRECT_LOGGED_IN = "oauth.logged_in";
constexpr absl::string_view REDIRECT_FOR_CREDENTIALS = "oauth.missing_credentials";
constexpr absl::string_view SIGN_OUT = "oauth.sign_out";
constexpr absl::string_view DEFAULT_AUTH_SCOPE = "user";

template <class T>
std::vector<Http::HeaderUtility::HeaderData> headerMatchers(const T& matcher_protos) {
Expand All @@ -73,6 +74,25 @@ std::vector<Http::HeaderUtility::HeaderData> headerMatchers(const T& matcher_pro
return matchers;
}

// Transforms the proto list of 'auth_scopes' into a vector of std::string, also
// handling the default value logic
template <class T> std::vector<std::string> authScopesList(const T& auth_scopes_protos) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just use the actual type (Protobuf::RepeatedPtrField<std::string>) here instead of making this generic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snowp Should I change to Protobuf::RepeatedPtrField<std::string> in the class property as well, right? Not only in the function return?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snowp is that what you mean? template <class T> Protobuf::RepeatedPtrField<std::string> authScopesList

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to remove the T from the paramter list and use the real type instead, so std::vector<std::string> authScopesList(const Protobuf::RepeteadPtrField<std::string>& auth_scopes_proto).

If we need to convert to vectorstd::string` then we'd keep that on the class, if not we don't even need this conversion function

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Added a commit to fix this.

std::vector<std::string> scopes;

// if 'auth_scopes' is empty it must return a list with the default value.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: proper grammar in comments, so If instead of if

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (auth_scopes_protos.empty()) {
scopes.reserve(1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reserving one seems redundant, I imagine it's only useful to avoid multiple allocations from happening by telling the vector that multiple entries will be inserted

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@snowp do you think just removing scopes.reserve(1); would be enough here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

scopes.emplace_back(DEFAULT_AUTH_SCOPE);
} else {
scopes.reserve(auth_scopes_protos.size());

for (const auto& scope : auth_scopes_protos) {
scopes.emplace_back(scope);
}
}
return scopes;
}

Comment thread
snowp marked this conversation as resolved.
// Sets the auth token as the Bearer token in the authorization header.
void setBearerToken(Http::RequestHeaderMap& headers, const std::string& token) {
headers.setInline(authorization_handle.handle(), absl::StrCat("Bearer ", token));
Expand All @@ -90,6 +110,7 @@ FilterConfig::FilterConfig(
redirect_matcher_(proto_config.redirect_path_matcher()),
signout_path_(proto_config.signout_path()), secret_reader_(secret_reader),
stats_(FilterConfig::generateStats(stats_prefix, scope)),
auth_scopes_(authScopesList(proto_config.auth_scopes())),
forward_bearer_token_(proto_config.forward_bearer_token()),
pass_through_header_matchers_(headerMatchers(proto_config.pass_through_matcher())) {
if (!cluster_manager.get(oauth_token_endpoint_.cluster())) {
Expand Down Expand Up @@ -275,9 +296,11 @@ Http::FilterHeadersStatus OAuth2Filter::decodeHeaders(Http::RequestHeaderMap& he
const std::string escaped_redirect_uri =
Http::Utility::PercentEncoding::encode(redirect_uri, ":/=&?");

const std::string escaped_auth_scopes = absl::StrJoin(config_->authScopes(), "%20");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the scopes also be escaped (i.e., joined with spaces and using Http::Utility::PercentEncoding::encode to escape the string)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adisuissa I tried to join the list with whitespace and use PercentEncoding::encode, but this function seems to do not replace the whitespace character with percent. Then I just used %20 instead. Do you mean something different?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the names of the auth scopes require escaping as well? You should be able to include as a character in the second arg to encode to have it escape it


const std::string new_url =
fmt::format(AuthorizationEndpointFormat, config_->authorizationEndpoint(),
config_->clientId(), escaped_redirect_uri, escaped_state);
config_->clientId(), escaped_auth_scopes, escaped_redirect_uri, escaped_state);
response_headers->setLocation(new_url);
decoder_callbacks_->encodeHeaders(std::move(response_headers), true, REDIRECT_FOR_CREDENTIALS);

Expand Down
2 changes: 2 additions & 0 deletions source/extensions/filters/http/oauth2/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class FilterConfig {
std::string clientSecret() const { return secret_reader_->clientSecret(); }
std::string tokenSecret() const { return secret_reader_->tokenSecret(); }
FilterStats& stats() { return stats_; }
const std::vector<std::string>& authScopes() const { return auth_scopes_; }

private:
static FilterStats generateStats(const std::string& prefix, Stats::Scope& scope);
Expand All @@ -135,6 +136,7 @@ class FilterConfig {
const Matchers::PathMatcher signout_path_;
std::shared_ptr<SecretReader> secret_reader_;
FilterStats stats_;
const std::vector<std::string> auth_scopes_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is no longer used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, just removed it

const bool forward_bearer_token_ : 1;
const std::vector<Http::HeaderUtility::HeaderData> pass_through_header_matchers_;
};
Expand Down
1 change: 1 addition & 0 deletions source/extensions/filters/http/oauth2/oauth_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ void OAuth2ClientImpl::onSuccess(const Http::AsyncClient::Request&,
const auto response_code = message->headers().Status()->value().getStringView();
if (response_code != "200") {
ENVOY_LOG(debug, "Oauth response code: {}", response_code);
ENVOY_LOG(debug, "Oauth response body: {}", message->bodyAsString());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid of the amount of data that would be logged here.
Wouldn't this even make debug unusable in some cases?
Eg: big pages being proxied

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me clarify this @joaovitor. What is being logged here is the response body of the request to the OAuth provider. This is not the upstream request (to service being proxied in the end).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great @andreyprezotto ... Hope to see this PR merged.
This will improve oauth integration in envoy a lot.
Thanks for this work!

parent_->sendUnauthorizedResponse();
return;
}
Expand Down
8 changes: 8 additions & 0 deletions test/extensions/filters/http/oauth2/config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ void expectInvalidSecretConfig(const std::string& failed_secret_name,
signout_path:
path:
exact: /signout
auth_scopes:
- user
- openid
- email
)EOF";

OAuth2Config factory;
Expand Down Expand Up @@ -87,6 +91,10 @@ TEST(ConfigTest, CreateFilter) {
signout_path:
path:
exact: /signout
auth_scopes:
- user
- openid
- email
)EOF";

OAuth2Config factory;
Expand Down
73 changes: 59 additions & 14 deletions test/extensions/filters/http/oauth2/filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static const std::string TEST_CALLBACK = "/_oauth";
static const std::string TEST_CLIENT_ID = "1";
static const std::string TEST_CLIENT_SECRET_ID = "MyClientSecretKnoxID";
static const std::string TEST_TOKEN_SECRET_ID = "MyTokenSecretKnoxID";
static const std::string TEST_ENCODED_AUTH_SCOPES = "user%20openid%20email";

namespace {
Http::RegisterCustomInlineHeader<Http::CustomInlineHeaderRegistry::Type::RequestHeaders>
Expand Down Expand Up @@ -91,6 +92,9 @@ class OAuth2Test : public testing::Test {
p.set_authorization_endpoint("https://auth.example.com/oauth/authorize/");
p.mutable_signout_path()->mutable_path()->set_exact("/_signout");
p.set_forward_bearer_token(true);
p.add_auth_scopes("user");
p.add_auth_scopes("openid");
p.add_auth_scopes("email");
auto* matcher = p.add_pass_through_matcher();
matcher->set_name(":method");
matcher->set_exact_match("OPTIONS");
Expand Down Expand Up @@ -147,6 +151,43 @@ TEST_F(OAuth2Test, InvalidCluster) {
"specify which cluster to direct OAuth requests to.");
}

// Verifies that the OAuth config is created with a default value for auth_scopes field when it is
// not set in proto/yaml.
TEST_F(OAuth2Test, DefaultAuthScope) {

// Set up proto fields
envoy::extensions::filters::http::oauth2::v3alpha::OAuth2Config p;
auto* endpoint = p.mutable_token_endpoint();
endpoint->set_cluster("auth.example.com");
endpoint->set_uri("auth.example.com/_oauth");
endpoint->mutable_timeout()->set_seconds(1);
p.set_redirect_uri("%REQ(x-forwarded-proto)%://%REQ(:authority)%" + TEST_CALLBACK);
p.mutable_redirect_path_matcher()->mutable_path()->set_exact(TEST_CALLBACK);
p.set_authorization_endpoint("https://auth.example.com/oauth/authorize/");
p.mutable_signout_path()->mutable_path()->set_exact("/_signout");
p.set_forward_bearer_token(true);
auto* matcher = p.add_pass_through_matcher();
matcher->set_name(":method");
matcher->set_exact_match("OPTIONS");

auto credentials = p.mutable_credentials();
credentials->set_client_id(TEST_CLIENT_ID);
credentials->mutable_token_secret()->set_name("secret");
credentials->mutable_hmac_secret()->set_name("hmac");

MessageUtil::validate(p, ProtobufMessage::getStrictValidationVisitor());

// Create the OAuth config.
auto secret_reader = std::make_shared<MockSecretReader>();
FilterConfigSharedPtr test_config_;
test_config_ = std::make_shared<FilterConfig>(p, factory_context_.cluster_manager_, secret_reader,
scope_, "test.");

// auth_scopes was not set, should return default value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: same comment on comment grammar: proper case and end in period. Bonus point for complete sentence

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

std::vector<std::string> default_scope = {"user"};
EXPECT_EQ(test_config_->authScopes(), default_scope);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the only use case of authScopes, can we remove this function and just test via the encodedAuthScopes instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

}

/**
* Scenario: The OAuth filter receives a sign out request.
*
Expand Down Expand Up @@ -239,8 +280,8 @@ TEST_F(OAuth2Test, OAuthErrorNonOAuthHttpCallback) {
{Http::Headers::get().Location.get(),
"https://auth.example.com/oauth/"
"authorize/?client_id=" +
TEST_CLIENT_ID +
"&scope=user&response_type=code&"
TEST_CLIENT_ID + "&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&response_type=code&"
"redirect_uri=http%3A%2F%2Ftraffic.example.com%2F"
"_oauth&state=http%3A%2F%2Ftraffic.example.com%2Fnot%2F_oauth"},
};
Expand Down Expand Up @@ -392,8 +433,8 @@ TEST_F(OAuth2Test, OAuthTestInvalidUrlInStateQueryParam) {
Http::TestRequestHeaderMapImpl request_headers{
{Http::Headers::get().Host.get(), "traffic.example.com"},
{Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get},
{Http::Headers::get().Path.get(), "/_oauth?code=abcdefxyz123&scope=user&"
"state=blah"},
{Http::Headers::get().Path.get(),
"/_oauth?code=abcdefxyz123&scope=" + TEST_ENCODED_AUTH_SCOPES + "&state=blah"},
{Http::Headers::get().Cookie.get(), "OauthExpires=123;version=test"},
{Http::Headers::get().Cookie.get(), "BearerToken=legit_token;version=test"},
{Http::Headers::get().Cookie.get(),
Expand Down Expand Up @@ -426,8 +467,9 @@ TEST_F(OAuth2Test, OAuthTestCallbackUrlInStateQueryParam) {
Http::TestRequestHeaderMapImpl request_headers{
{Http::Headers::get().Host.get(), "traffic.example.com"},
{Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get},
{Http::Headers::get().Path.get(), "/_oauth?code=abcdefxyz123&scope=user&"
"state=https%3A%2F%2Ftraffic.example.com%2F_oauth"},
{Http::Headers::get().Path.get(),
"/_oauth?code=abcdefxyz123&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&state=https%3A%2F%2Ftraffic.example.com%2F_oauth"},
{Http::Headers::get().Cookie.get(), "OauthExpires=123;version=test"},
{Http::Headers::get().Cookie.get(), "BearerToken=legit_token;version=test"},
{Http::Headers::get().Cookie.get(),
Expand Down Expand Up @@ -457,8 +499,9 @@ TEST_F(OAuth2Test, OAuthTestCallbackUrlInStateQueryParam) {
Http::TestRequestHeaderMapImpl final_request_headers{
{Http::Headers::get().Host.get(), "traffic.example.com"},
{Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get},
{Http::Headers::get().Path.get(), "/_oauth?code=abcdefxyz123&scope=user&"
"state=https%3A%2F%2Ftraffic.example.com%2F_oauth"},
{Http::Headers::get().Path.get(),
"/_oauth?code=abcdefxyz123&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&state=https%3A%2F%2Ftraffic.example.com%2F_oauth"},
{Http::Headers::get().Cookie.get(), "OauthExpires=123;version=test"},
{Http::Headers::get().Cookie.get(), "BearerToken=legit_token;version=test"},
{Http::Headers::get().Cookie.get(),
Expand All @@ -482,8 +525,9 @@ TEST_F(OAuth2Test, OAuthTestUpdatePathAfterSuccess) {
Http::TestRequestHeaderMapImpl request_headers{
{Http::Headers::get().Host.get(), "traffic.example.com"},
{Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get},
{Http::Headers::get().Path.get(), "/_oauth?code=abcdefxyz123&scope=user&"
"state=https%3A%2F%2Ftraffic.example.com%2Foriginal_path"},
{Http::Headers::get().Path.get(),
"/_oauth?code=abcdefxyz123&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&state=https%3A%2F%2Ftraffic.example.com%2Foriginal_path"},
{Http::Headers::get().Cookie.get(), "OauthExpires=123;version=test"},
{Http::Headers::get().Cookie.get(), "BearerToken=legit_token;version=test"},
{Http::Headers::get().Cookie.get(),
Expand Down Expand Up @@ -511,8 +555,9 @@ TEST_F(OAuth2Test, OAuthTestUpdatePathAfterSuccess) {
Http::TestRequestHeaderMapImpl final_request_headers{
{Http::Headers::get().Host.get(), "traffic.example.com"},
{Http::Headers::get().Method.get(), Http::Headers::get().MethodValues.Get},
{Http::Headers::get().Path.get(), "/_oauth?code=abcdefxyz123&scope=user&"
"state=https%3A%2F%2Ftraffic.example.com%2Foriginal_path"},
{Http::Headers::get().Path.get(),
"/_oauth?code=abcdefxyz123&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&state=https%3A%2F%2Ftraffic.example.com%2Foriginal_path"},
{Http::Headers::get().Cookie.get(), "OauthExpires=123;version=test"},
{Http::Headers::get().Cookie.get(), "BearerToken=legit_token;version=test"},
{Http::Headers::get().Cookie.get(),
Expand Down Expand Up @@ -545,8 +590,8 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithParameters) {
{Http::Headers::get().Location.get(),
"https://auth.example.com/oauth/"
"authorize/?client_id=" +
TEST_CLIENT_ID +
"&scope=user&response_type=code&"
TEST_CLIENT_ID + "&scope=" + TEST_ENCODED_AUTH_SCOPES +
"&response_type=code&"
"redirect_uri=https%3A%2F%2Ftraffic.example.com%2F"
"_oauth&state=https%3A%2F%2Ftraffic.example.com%2Ftest%"
"3Fname%3Dadmin%26level%3Dtrace"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ name: oauth
name: token
hmac_secret:
name: hmac
auth_scopes:
- user
- openid
- email
)EOF");

// Add the OAuth cluster.
Expand Down