Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
6 changes: 5 additions & 1 deletion api/envoy/extensions/filters/http/oauth2/v3alpha/oauth.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ message OAuth2Credentials {

// OAuth config
//
// [#next-free-field: 10]
// [#next-free-field: 11]
message OAuth2Config {
// Endpoint on the authorization server to retrieve the access token from.
config.core.v3.HttpUri token_endpoint = 1;
Expand Down Expand Up @@ -76,6 +76,10 @@ message OAuth2Config {
// defaults to "user" scope.
// OAuth RFC https://tools.ietf.org/html/rfc6749#section-3.3
repeated string auth_scopes = 9;

// Optional resource parameter for authorization request
// RFC: https://tools.ietf.org/html/rfc8707
string resource = 10;

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.

The RFC seems to allow multiple values here, should this be a repeated field?

Multiple "resource" parameters MAY be
      used to indicate that the requested token is intended to be used
      at multiple resources.

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 I will convert this to a repeated field.

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 Its up for review.

}

// Filter config.
Expand Down
6 changes: 5 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.

4 changes: 4 additions & 0 deletions docs/root/configuration/http/http_filters/oauth2_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ The following is an example configuring the filter.
- user
- openid
- email
# (Optional): set resource parameter for Authorization request
resource: oauth2-resource

Below is a complete code example of how we employ the filter as one of
:ref:`HttpConnectionManager HTTP filters
Expand Down Expand Up @@ -124,6 +126,8 @@ Below is a complete code example of how we employ the filter as one of
- user
- openid
- email
# (Optional): set resource parameter for Authorization request
resource: oauth2-resource
- name: envoy.router
tracing: {}
codec_type: "AUTO"
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.

11 changes: 10 additions & 1 deletion source/extensions/filters/http/oauth2/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ constexpr const char* CookieTailHttpOnlyFormatString =
const char* AuthorizationEndpointFormat =
"{}?client_id={}&scope={}&response_type=code&redirect_uri={}&state={}";

const char* AuthorizationEndpointResourceParamFormat = "&resource={}";

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

const std::string& queryParamsError() { CONSTRUCT_ON_FIRST_USE(std::string, "error"); }
Expand Down Expand Up @@ -112,6 +114,7 @@ FilterConfig::FilterConfig(
stats_(FilterConfig::generateStats(stats_prefix, scope)),
encoded_auth_scopes_(Http::Utility::PercentEncoding::encode(
absl::StrJoin(authScopesList(proto_config.auth_scopes()), " "), ":/=&? ")),
resource_(proto_config.resource()),
forward_bearer_token_(proto_config.forward_bearer_token()),
pass_through_header_matchers_(headerMatchers(proto_config.pass_through_matcher())) {
if (!cluster_manager.clusters().hasCluster(oauth_token_endpoint_.cluster())) {
Expand Down Expand Up @@ -300,7 +303,13 @@ Http::FilterHeadersStatus OAuth2Filter::decodeHeaders(Http::RequestHeaderMap& he
const std::string new_url = fmt::format(
AuthorizationEndpointFormat, config_->authorizationEndpoint(), config_->clientId(),
config_->encodedAuthScopes(), escaped_redirect_uri, escaped_state);
response_headers->setLocation(new_url);

const std::string resource_param =
config_->resource().empty()
? ""
: fmt::format(AuthorizationEndpointResourceParamFormat, config_->resource());

response_headers->setLocation(new_url + resource_param);
decoder_callbacks_->encodeHeaders(std::move(response_headers), true, REDIRECT_FOR_CREDENTIALS);

config_->stats().oauth_unauthorized_rq_.inc();
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 @@ -124,6 +124,7 @@ class FilterConfig {
std::string tokenSecret() const { return secret_reader_->tokenSecret(); }
FilterStats& stats() { return stats_; }
const std::string& encodedAuthScopes() const { return encoded_auth_scopes_; }
const std::string resource() const { return resource_; }

private:
static FilterStats generateStats(const std::string& prefix, Stats::Scope& scope);
Expand All @@ -137,6 +138,7 @@ class FilterConfig {
std::shared_ptr<SecretReader> secret_reader_;
FilterStats stats_;
const std::string encoded_auth_scopes_;
const std::string resource_;
const bool forward_bearer_token_ : 1;
const std::vector<Http::HeaderUtility::HeaderData> pass_through_header_matchers_;
};
Expand Down
2 changes: 2 additions & 0 deletions test/extensions/filters/http/oauth2/config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void expectInvalidSecretConfig(const std::string& failed_secret_name,
- user
- openid
- email
resource: oauth2-resource
)EOF";

OAuth2Config factory;
Expand Down Expand Up @@ -95,6 +96,7 @@ TEST(ConfigTest, CreateFilter) {
- user
- openid
- email
resource: oauth2-resource
)EOF";

OAuth2Config factory;
Expand Down
10 changes: 8 additions & 2 deletions test/extensions/filters/http/oauth2/filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class OAuth2Test : public testing::Test {
p.add_auth_scopes("user");
p.add_auth_scopes("openid");
p.add_auth_scopes("email");
p.set_resource("oauth2-resource");
auto* matcher = p.add_pass_through_matcher();
matcher->set_name(":method");
matcher->set_exact_match("OPTIONS");
Expand Down Expand Up @@ -197,6 +198,9 @@ TEST_F(OAuth2Test, DefaultAuthScope) {
// Auth_scopes was not set, should return default value.
EXPECT_EQ(test_config_->encodedAuthScopes(), TEST_DEFAULT_SCOPE);

// resource by default is not set

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/punctuation in comments

EXPECT_EQ(test_config_->resource(), "");

// Recreate the filter with current config and test if the scope was added
// as a query parameter in response headers.
init(test_config_);
Expand Down Expand Up @@ -324,7 +328,8 @@ TEST_F(OAuth2Test, OAuthErrorNonOAuthHttpCallback) {
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"},
"_oauth&state=http%3A%2F%2Ftraffic.example.com%2Fnot%2F_oauth"
"&resource=oauth2-resource"},
};

// explicitly tell the validator to fail the validation
Expand Down Expand Up @@ -634,7 +639,8 @@ TEST_F(OAuth2Test, OAuthTestFullFlowPostWithParameters) {
"&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"},
"3Fname%3Dadmin%26level%3Dtrace"
"&resource=oauth2-resource"},
};

// Fail the validation to trigger the OAuth flow.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ name: oauth
- user
- openid
- email
resource: oauth2-resource
)EOF");

// Add the OAuth cluster.
Expand Down