From df015b5123d504eb18b9b0350737b43eb96fd3ad Mon Sep 17 00:00:00 2001 From: Erikson Bahr Date: Thu, 1 Feb 2024 10:38:06 -0300 Subject: [PATCH] add 'OAUTH2_PROXY_OIDC_ENABLE_COOKIE_REFRESH' and 'OAUTH2_PROXY_OIDC_COOKIE_REFRESH_NAME' options --- oauthproxy.go | 7 +++++-- pkg/apis/options/legacy_options.go | 6 ++++++ pkg/apis/options/providers.go | 4 ++++ pkg/middleware/cookie_refresh.go | 23 +++++++++++++---------- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/oauthproxy.go b/oauthproxy.go index d5f79cb779..4eb58e0ccc 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -393,8 +393,11 @@ func buildSessionChain(opts *options.Options, provider providers.Provider, sessi ValidateSession: provider.ValidateSession, })) - x := opts.Providers[0] - chain = chain.Append(middleware.NewCookieRefresh(&middleware.CookieRefreshOptions{IssuerURL: x.OIDCConfig.IssuerURL})) + oidcProviderSettings := opts.Providers[0].OIDCConfig + if oidcProviderSettings.EnableCookieRefresh { + chain = chain.Append(middleware.NewCookieRefresh(&middleware.CookieRefreshOptions{IssuerURL: oidcProviderSettings.IssuerURL, CookieRefreshName: oidcProviderSettings.CookieRefreshName})) + logger.Printf("Enabling OIDC cookie refresh for the cookie '%s' functionality because OIDCEnableCookieRefresh is enabled", oidcProviderSettings.CookieRefreshName) + } return chain } diff --git a/pkg/apis/options/legacy_options.go b/pkg/apis/options/legacy_options.go index 616b33abcb..c3c010a289 100644 --- a/pkg/apis/options/legacy_options.go +++ b/pkg/apis/options/legacy_options.go @@ -543,6 +543,8 @@ type LegacyProvider struct { OIDCGroupsClaim string `flag:"oidc-groups-claim" cfg:"oidc_groups_claim"` OIDCAudienceClaims []string `flag:"oidc-audience-claim" cfg:"oidc_audience_claims"` OIDCExtraAudiences []string `flag:"oidc-extra-audience" cfg:"oidc_extra_audiences"` + OIDCEnableCookieRefresh bool `flag:"oidc-enable-cookie-refresh" cfg:"oidc_enable_cookie_refresh"` + OIDCCookieRefreshName string `flag:"oidc-cookie-refresh-name" cfg:"oidc_cookie_refresh_name"` LoginURL string `flag:"login-url" cfg:"login_url"` RedeemURL string `flag:"redeem-url" cfg:"redeem_url"` ProfileURL string `flag:"profile-url" cfg:"profile_url"` @@ -601,6 +603,8 @@ func legacyProviderFlagSet() *pflag.FlagSet { flagSet.String("oidc-email-claim", OIDCEmailClaim, "which OIDC claim contains the user's email") flagSet.StringSlice("oidc-audience-claim", OIDCAudienceClaims, "which OIDC claims are used as audience to verify against client id") flagSet.StringSlice("oidc-extra-audience", []string{}, "additional audiences allowed to pass audience verification") + flagSet.Bool("oidc-enable-cookie-refresh", false, "Refresh the OIDC provider cookies to enable SSO in an extended period of time") + flagSet.String("oidc-cookie-refresh-name", "hsdpamcookie", "The name of the cookie that the OIDC provider uses to keep its session fresh") flagSet.String("login-url", "", "Authentication endpoint") flagSet.String("redeem-url", "", "Token redemption endpoint") flagSet.String("profile-url", "", "Profile access endpoint") @@ -702,6 +706,8 @@ func (l *LegacyProvider) convert() (Providers, error) { GroupsClaim: l.OIDCGroupsClaim, AudienceClaims: l.OIDCAudienceClaims, ExtraAudiences: l.OIDCExtraAudiences, + EnableCookieRefresh: l.OIDCEnableCookieRefresh, + CookieRefreshName: l.OIDCCookieRefreshName, } // Support for legacy configuration option diff --git a/pkg/apis/options/providers.go b/pkg/apis/options/providers.go index 7b9934051c..a7e02b7d17 100644 --- a/pkg/apis/options/providers.go +++ b/pkg/apis/options/providers.go @@ -230,6 +230,10 @@ type OIDCOptions struct { // ExtraAudiences is a list of additional audiences that are allowed // to pass verification in addition to the client id. ExtraAudiences []string `json:"extraAudiences,omitempty"` + // Enable cookie refresh functionality that is going to be triggered every time the session is updated + EnableCookieRefresh bool `json:"enableCookieRefresh,omitempty"` + // Name of the cookie that is going to be extracted from the request and refreshed + CookieRefreshName string `json:"cookieRefreshName,omitempty"` } type LoginGovOptions struct { diff --git a/pkg/middleware/cookie_refresh.go b/pkg/middleware/cookie_refresh.go index c5b803bbac..a64c161f15 100644 --- a/pkg/middleware/cookie_refresh.go +++ b/pkg/middleware/cookie_refresh.go @@ -11,20 +11,23 @@ import ( ) type CookieRefreshOptions struct { - IssuerURL string + IssuerURL string + CookieRefreshName string } func NewCookieRefresh(opts *CookieRefreshOptions) alice.Constructor { cr := &cookieRefresh{ - HTTPClient: &http.Client{}, - IssuerURL: opts.IssuerURL, + HTTPClient: &http.Client{}, + IssuerURL: opts.IssuerURL, + CookieRefreshName: opts.CookieRefreshName, } return cr.refreshCookie } type cookieRefresh struct { - HTTPClient *http.Client - IssuerURL string + HTTPClient *http.Client + IssuerURL string + CookieRefreshName string } func (cr *cookieRefresh) refreshCookie(next http.Handler) http.Handler { @@ -35,25 +38,25 @@ func (cr *cookieRefresh) refreshCookie(next http.Handler) http.Handler { return } - cookie, err := req.Cookie("hsdpamcookie") + cookie, err := req.Cookie(cr.CookieRefreshName) if err != nil { - logger.Errorf("SSO Cookie Refresher - Could find 'hsdpamcookie' cookie in the request: %v", err) + logger.Errorf("SSO Cookie Refresher - Could find '%s' cookie in the request: %v", cr.CookieRefreshName, err) return } resp := requests.New(fmt.Sprintf("%s/session/refresh", cr.IssuerURL)). WithContext(req.Context()). WithMethod("GET"). SetHeader("api-version", "1"). - SetHeader("Cookie", fmt.Sprintf("hsdpamcookie=%s", cookie.Value)). + SetHeader("Cookie", fmt.Sprintf("%s=%s", cr.CookieRefreshName, cookie.Value)). Do() if resp.StatusCode() != http.StatusNoContent { bodyString := string(resp.Body()) - logger.Errorf("SSO Cookie Refresher - Could not refresh the 'hsdpamcookie' cookie due to status and content: %v - %v", resp.StatusCode(), bodyString) + logger.Errorf("SSO Cookie Refresher - Could not refresh the '%s' cookie due to status and content: %v - %v", cr.CookieRefreshName, resp.StatusCode(), bodyString) return } - logger.Print("SSO Cookie Refresher - Cookie 'hsdpamcookie' refreshed") + logger.Printf("SSO Cookie Refresher - Cookie '%s' refreshed", cr.CookieRefreshName) next.ServeHTTP(rw, req) }) }