Repository: envoyproxy/envoy
File: source/extensions/filters/http/oauth2/filter.cc (C++)

Code before:
  }
  if (!authorization_endpoint_url_.initialize(authorization_endpoint_,
                                              /*is_connect_request=*/false)) {
    throw EnvoyException(
        fmt::format("OAuth2 filter: invalid authorization endpoint URL '{}' in config.",
                    authorization_endpoint_));
  }
  if (!end_session_endpoint_.empty()) {
    bool is_oidc = false;
    for (const auto& scope : proto_config.auth_scopes()) {
      if (scope == OAUTH2_SCOPE_OPENID) {
        is_oidc = true;
        break;
      }
    }
    if (!is_oidc) {
      throw EnvoyException(
          "OAuth2 filter: end session endpoint is only supported for OpenID Connect.");
    }
  }

  if (proto_config.has_retry_policy()) {
    auto retry_policy = Http::Utility::convertCoreToRouteRetryPolicy(
        proto_config.retry_policy(), "5xx,gateway-error,connect-failure,reset");
    // Use the null validation visitor because it used by the async client in the previous
    // implementation.
    auto parsed_policy_or_error = Router::RetryPolicyImpl::create(
        retry_policy, ProtobufMessage::getNullValidationVisitor(), context);
    THROW_IF_NOT_OK_REF(parsed_policy_or_error.status());
    retry_policy_ = std::move(parsed_policy_or_error.value());
  }
}

FilterStats FilterConfig::generateStats(const std::string& prefix,
                                        const std::string& filter_stats_prefix,
                                        Stats::Scope& scope) {
  const std::string final_prefix = absl::StrCat(prefix, filter_stats_prefix);
  return {ALL_OAUTH_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))};
}

bool FilterConfig::shouldUseRefreshToken(
    const envoy::extensions::filters::http::oauth2::v3::OAuth2Config& proto_config) const {
  return PROTOBUF_GET_WRAPPED_OR_DEFAULT(proto_config, use_refresh_token, true);
}

void OAuth2CookieValidator::setParams(const Http::RequestHeaderMap& headers,
                                      const std::string& secret) {
  const auto& cookies = Http::Utility::parseCookies(headers, [this](absl::string_view key) -> bool {
    return key == cookie_names_.oauth_expires_ || key == cookie_names_.bearer_token_ ||
           key == cookie_names_.oauth_hmac_ || key == cookie_names_.id_token_ ||
           key == cookie_names_.refresh_token_;

Review comment (suggestion):
```suggestion
    // Use the null validation visitor for the backward compatibility. The proto should already
    // been validated during the config load.
```

Code after:
  }
  if (!authorization_endpoint_url_.initialize(authorization_endpoint_,
                                              /*is_connect_request=*/false)) {
    throw EnvoyException(
        fmt::format("OAuth2 filter: invalid authorization endpoint URL '{}' in config.",
                    authorization_endpoint_));
  }
  if (!end_session_endpoint_.empty()) {
    bool is_oidc = false;
    for (const auto& scope : proto_config.auth_scopes()) {
      if (scope == OAUTH2_SCOPE_OPENID) {
        is_oidc = true;
        break;
      }
    }
    if (!is_oidc) {
      throw EnvoyException(
          "OAuth2 filter: end session endpoint is only supported for OpenID Connect.");
    }
  }

  if (proto_config.has_retry_policy()) {
    auto retry_policy = Http::Utility::convertCoreToRouteRetryPolicy(
        proto_config.retry_policy(), "5xx,gateway-error,connect-failure,reset");
    // Use the null validation visitor for the backward compatibility. The proto should already
    // been validated during the config load.
    auto parsed_policy_or_error = Router::RetryPolicyImpl::create(
        retry_policy, ProtobufMessage::getNullValidationVisitor(), context);
    THROW_IF_NOT_OK_REF(parsed_policy_or_error.status());
    retry_policy_ = std::move(parsed_policy_or_error.value());
  }
}

FilterStats FilterConfig::generateStats(const std::string& prefix,
                                        const std::string& filter_stats_prefix,
                                        Stats::Scope& scope) {
  const std::string final_prefix = absl::StrCat(prefix, filter_stats_prefix);
  return {ALL_OAUTH_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))};
}

bool FilterConfig::shouldUseRefreshToken(
    const envoy::extensions::filters::http::oauth2::v3::OAuth2Config& proto_config) const {
  return PROTOBUF_GET_WRAPPED_OR_DEFAULT(proto_config, use_refresh_token, true);
}

void OAuth2CookieValidator::setParams(const Http::RequestHeaderMap& headers,
                                      const std::string& secret) {
  const auto& cookies = Http::Utility::parseCookies(headers, [this](absl::string_view key) -> bool {
    return key == cookie_names_.oauth_expires_ || key == cookie_names_.bearer_token_ ||
           key == cookie_names_.oauth_hmac_ || key == cookie_names_.id_token_ ||
           key == cookie_names_.refresh_token_;