@@ -41,7 +41,7 @@ Http::RegisterCustomInlineHeader<Http::CustomInlineHeaderRegistry::Type::Request
41
41
42
42
constexpr const char * CookieDeleteFormatString =
43
43
" {}=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT" ;
44
- constexpr const char * CookieTailHttpOnlyFormatString = " ;path=/;Max-Age={};secure;HttpOnly" ;
44
+ constexpr const char * CookieTailHttpOnlyFormatString = " ;path=/;Max-Age={};secure;HttpOnly{} " ;
45
45
constexpr const char * CookieDomainFormatString = " ;domain={}" ;
46
46
47
47
constexpr absl::string_view UnauthorizedBodyMessage = " OAuth flow failed." ;
@@ -60,6 +60,9 @@ constexpr absl::string_view REDIRECT_FOR_CREDENTIALS = "oauth.missing_credential
60
60
constexpr absl::string_view SIGN_OUT = " oauth.sign_out" ;
61
61
constexpr absl::string_view DEFAULT_AUTH_SCOPE = " user" ;
62
62
63
+ constexpr absl::string_view SameSiteLax = " ;SameSite=Lax" ;
64
+ constexpr absl::string_view SameSiteStrict = " ;SameSite=Strict" ;
65
+ constexpr absl::string_view SameSiteNone = " ;SameSite=None" ;
63
66
constexpr absl::string_view HmacPayloadSeparator = " \n " ;
64
67
65
68
template <class T >
@@ -129,6 +132,28 @@ getAuthType(envoy::extensions::filters::http::oauth2::v3::OAuth2Config_AuthType
129
132
}
130
133
}
131
134
135
+ // Helper function to get SameSite attribute string from proto enum.
136
+ std::string
137
+ getSameSiteString (envoy::extensions::filters::http::oauth2::v3::CookieConfig_SameSite same_site) {
138
+ switch (same_site) {
139
+ PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
140
+ case envoy::extensions::filters::http::oauth2::v3::CookieConfig_SameSite::
141
+ CookieConfig_SameSite_STRICT:
142
+ return std::string (SameSiteStrict);
143
+ case envoy::extensions::filters::http::oauth2::v3::CookieConfig_SameSite::
144
+ CookieConfig_SameSite_LAX:
145
+ return std::string (SameSiteLax);
146
+ case envoy::extensions::filters::http::oauth2::v3::CookieConfig_SameSite::
147
+ CookieConfig_SameSite_NONE:
148
+ return std::string (SameSiteNone);
149
+ case envoy::extensions::filters::http::oauth2::v3::CookieConfig_SameSite::
150
+ CookieConfig_SameSite_DISABLED:
151
+ return EMPTY_STRING;
152
+ }
153
+ IS_ENVOY_BUG (" unexpected same_site enum value" );
154
+ return EMPTY_STRING;
155
+ }
156
+
132
157
Http::Utility::QueryParamsMulti buildAutorizationQueryParams (
133
158
const envoy::extensions::filters::http::oauth2::v3::OAuth2Config& proto_config) {
134
159
auto query_params =
@@ -246,7 +271,37 @@ FilterConfig::FilterConfig(
246
271
use_refresh_token_(FilterConfig::shouldUseRefreshToken(proto_config)),
247
272
disable_id_token_set_cookie_(proto_config.disable_id_token_set_cookie()),
248
273
disable_access_token_set_cookie_(proto_config.disable_access_token_set_cookie()),
249
- disable_refresh_token_set_cookie_(proto_config.disable_refresh_token_set_cookie()) {
274
+ disable_refresh_token_set_cookie_(proto_config.disable_refresh_token_set_cookie()),
275
+ bearer_token_cookie_settings_(
276
+ (proto_config.has_cookie_configs() &&
277
+ proto_config.cookie_configs().has_bearer_token_cookie_config())
278
+ ? CookieSettings(proto_config.cookie_configs().bearer_token_cookie_config())
279
+ : CookieSettings()),
280
+ hmac_cookie_settings_(
281
+ (proto_config.has_cookie_configs() &&
282
+ proto_config.cookie_configs().has_oauth_hmac_cookie_config())
283
+ ? CookieSettings(proto_config.cookie_configs().oauth_hmac_cookie_config())
284
+ : CookieSettings()),
285
+ expires_cookie_settings_(
286
+ (proto_config.has_cookie_configs() &&
287
+ proto_config.cookie_configs().has_oauth_expires_cookie_config())
288
+ ? CookieSettings(proto_config.cookie_configs().oauth_expires_cookie_config())
289
+ : CookieSettings()),
290
+ id_token_cookie_settings_(
291
+ (proto_config.has_cookie_configs() &&
292
+ proto_config.cookie_configs().has_id_token_cookie_config())
293
+ ? CookieSettings(proto_config.cookie_configs().id_token_cookie_config())
294
+ : CookieSettings()),
295
+ refresh_token_cookie_settings_(
296
+ (proto_config.has_cookie_configs() &&
297
+ proto_config.cookie_configs().has_refresh_token_cookie_config())
298
+ ? CookieSettings(proto_config.cookie_configs().refresh_token_cookie_config())
299
+ : CookieSettings()),
300
+ nonce_cookie_settings_(
301
+ (proto_config.has_cookie_configs() &&
302
+ proto_config.cookie_configs().has_oauth_nonce_cookie_config())
303
+ ? CookieSettings(proto_config.cookie_configs().oauth_nonce_cookie_config())
304
+ : CookieSettings()) {
250
305
if (!context.clusterManager ().clusters ().hasCluster (oauth_token_endpoint_.cluster ())) {
251
306
throw EnvoyException (fmt::format (" OAuth2 filter: unknown cluster '{}' in config. Please "
252
307
" specify which cluster to direct OAuth requests to." ,
@@ -544,8 +599,10 @@ void OAuth2Filter::redirectToOAuthServer(Http::RequestHeaderMap& headers) {
544
599
if (!csrf_token_cookie_exists) {
545
600
// Expire the CSRF token cookie in 10 minutes.
546
601
// This should be enough time for the user to complete the OAuth flow.
547
- std::string expire_in = std::to_string (10 * 60 );
548
- std::string cookie_tail_http_only = fmt::format (CookieTailHttpOnlyFormatString, expire_in);
602
+ std::string csrf_expires = std::to_string (10 * 60 );
603
+ std::string same_site = getSameSiteString (config_->nonceCookieSettings ().same_site_ );
604
+ std::string cookie_tail_http_only =
605
+ fmt::format (CookieTailHttpOnlyFormatString, csrf_expires, same_site);
549
606
if (!config_->cookieDomain ().empty ()) {
550
607
cookie_tail_http_only = absl::StrCat (
551
608
fmt::format (CookieDomainFormatString, config_->cookieDomain ()), cookie_tail_http_only);
@@ -728,6 +785,43 @@ std::string OAuth2Filter::getExpiresTimeForIdToken(const std::string& id_token,
728
785
return std::to_string (expires_in.count ());
729
786
}
730
787
788
+ // Helper function to build the cookie tail string.
789
+ std::string OAuth2Filter::BuildCookieTail (int cookie_type) const {
790
+ std::string same_site;
791
+ std::string expires_time = expires_in_;
792
+
793
+ switch (cookie_type) {
794
+ PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
795
+ case 1 : // BEARER_TOKEN TYPE
796
+ same_site = getSameSiteString (config_->bearerTokenCookieSettings ().same_site_ );
797
+ break ;
798
+ case 2 : // OAUTH_HMAC TYPE
799
+ same_site = getSameSiteString (config_->hmacCookieSettings ().same_site_ );
800
+ break ;
801
+ case 3 : // OAUTH_EXPIRES TYPE
802
+ same_site = getSameSiteString (config_->expiresCookieSettings ().same_site_ );
803
+ break ;
804
+ case 4 : // ID_TOKEN TYPE
805
+ same_site = getSameSiteString (config_->idTokenCookieSettings ().same_site_ );
806
+ expires_time = expires_id_token_in_;
807
+ break ;
808
+ case 5 : // REFRESH_TOKEN TYPE
809
+ same_site = getSameSiteString (config_->refreshTokenCookieSettings ().same_site_ );
810
+ expires_time = expires_refresh_token_in_;
811
+ break ;
812
+ case 6 : // OAUTH_NONCE TYPE
813
+ same_site = getSameSiteString (config_->refreshTokenCookieSettings ().same_site_ );
814
+ break ;
815
+ }
816
+
817
+ std::string cookie_tail = fmt::format (CookieTailHttpOnlyFormatString, expires_time, same_site);
818
+ if (!config_->cookieDomain ().empty ()) {
819
+ cookie_tail =
820
+ absl::StrCat (fmt::format (CookieDomainFormatString, config_->cookieDomain ()), cookie_tail);
821
+ }
822
+ return cookie_tail;
823
+ }
824
+
731
825
void OAuth2Filter::onGetAccessTokenSuccess (const std::string& access_code,
732
826
const std::string& id_token,
733
827
const std::string& refresh_token,
@@ -809,51 +903,33 @@ void OAuth2Filter::onRefreshAccessTokenFailure() {
809
903
void OAuth2Filter::addResponseCookies (Http::ResponseHeaderMap& headers,
810
904
const std::string& encoded_token) const {
811
905
// We use HTTP Only cookies.
812
- std::string cookie_tail_http_only = fmt::format (CookieTailHttpOnlyFormatString, expires_in_);
813
- if (!config_->cookieDomain ().empty ()) {
814
- cookie_tail_http_only = absl::StrCat (
815
- fmt::format (CookieDomainFormatString, config_->cookieDomain ()), cookie_tail_http_only);
816
- }
817
-
818
906
const CookieNames& cookie_names = config_->cookieNames ();
819
907
908
+ // Set the cookies in the response headers.
820
909
headers.addReferenceKey (
821
910
Http::Headers::get ().SetCookie ,
822
- absl::StrCat (cookie_names.oauth_hmac_ , " =" , encoded_token, cookie_tail_http_only));
823
- headers.addReferenceKey (
824
- Http::Headers::get ().SetCookie ,
825
- absl::StrCat (cookie_names.oauth_expires_ , " =" , new_expires_, cookie_tail_http_only));
911
+ absl::StrCat (cookie_names.oauth_hmac_ , " =" , encoded_token, BuildCookieTail (2 ))); // OAUTH_HMAC
912
+
913
+ headers.addReferenceKey (Http::Headers::get ().SetCookie ,
914
+ absl::StrCat (cookie_names.oauth_expires_ , " =" , new_expires_,
915
+ BuildCookieTail (3 ))); // OAUTH_EXPIRES
826
916
827
917
if (!access_token_.empty ()) {
828
- headers.addReferenceKey (
829
- Http::Headers::get (). SetCookie ,
830
- absl::StrCat (cookie_names. bearer_token_ , " = " , access_token_, cookie_tail_http_only));
918
+ headers.addReferenceKey (Http::Headers::get (). SetCookie ,
919
+ absl::StrCat (cookie_names. bearer_token_ , " = " , access_token_ ,
920
+ BuildCookieTail ( 1 ))); // BEARER_TOKEN
831
921
}
832
922
833
923
if (!id_token_.empty ()) {
834
- std::string id_token_cookie_tail_http_only =
835
- fmt::format (CookieTailHttpOnlyFormatString, expires_id_token_in_);
836
- if (!config_->cookieDomain ().empty ()) {
837
- id_token_cookie_tail_http_only =
838
- absl::StrCat (fmt::format (CookieDomainFormatString, config_->cookieDomain ()),
839
- id_token_cookie_tail_http_only);
840
- }
841
924
headers.addReferenceKey (
842
925
Http::Headers::get ().SetCookie ,
843
- absl::StrCat (cookie_names.id_token_ , " =" , id_token_, id_token_cookie_tail_http_only));
926
+ absl::StrCat (cookie_names.id_token_ , " =" , id_token_, BuildCookieTail ( 4 ))); // ID_TOKEN
844
927
}
845
928
846
929
if (!refresh_token_.empty ()) {
847
- std::string refresh_token_cookie_tail_http_only =
848
- fmt::format (CookieTailHttpOnlyFormatString, expires_refresh_token_in_);
849
- if (!config_->cookieDomain ().empty ()) {
850
- refresh_token_cookie_tail_http_only =
851
- absl::StrCat (fmt::format (CookieDomainFormatString, config_->cookieDomain ()),
852
- refresh_token_cookie_tail_http_only);
853
- }
854
930
headers.addReferenceKey (Http::Headers::get ().SetCookie ,
855
931
absl::StrCat (cookie_names.refresh_token_ , " =" , refresh_token_,
856
- refresh_token_cookie_tail_http_only));
932
+ BuildCookieTail ( 5 ))); // REFRESH_TOKEN
857
933
}
858
934
}
859
935
0 commit comments