Skip to content

Commit

Permalink
filters/auth: export EncryptedCookieEncoder
Browse files Browse the repository at this point in the history
Export EncryptedCookieEncoder and decouple it from OAuthConfig.

Signed-off-by: Alexander Yastrebov <alexander.yastrebov@zalando.de>
  • Loading branch information
AlexanderYastrebov committed Mar 22, 2024
1 parent 3bb6eb6 commit 54a3e3d
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 29 deletions.
11 changes: 10 additions & 1 deletion filters/auth/grantconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,16 @@ func (c *OAuthConfig) Init() error {
}

if c.GrantCookieEncoder == nil {
c.GrantCookieEncoder = &EncryptedCookieEncoder{config: c}
encryption, err := c.Secrets.GetEncrypter(secretsRefreshInternal, c.SecretFile)
if err != nil {
return err
}
c.GrantCookieEncoder = &EncryptedCookieEncoder{
Encryption: encryption,
CookieName: c.TokenCookieName,
RemoveSubdomains: *c.TokenCookieRemoveSubdomains,
Insecure: c.Insecure,
}
}

c.initialized = true
Expand Down
50 changes: 22 additions & 28 deletions filters/auth/grantcookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,31 @@ type CookieEncoder interface {
Read(request *http.Request) (*oauth2.Token, error)
}

// EncryptedCookieEncoder is a CookieEncoder that encrypts the token before storing it in a cookie.
type EncryptedCookieEncoder struct {
config *OAuthConfig
Encryption secrets.Encryption
CookieName string
RemoveSubdomains int
Insecure bool
}

var _ CookieEncoder = &EncryptedCookieEncoder{}

func (ce *EncryptedCookieEncoder) Update(request *http.Request, token *oauth2.Token) ([]*http.Cookie, error) {
if token != nil {
c, err := createCookie(ce.config, request.Host, token)
c, err := ce.createCookie(request.Host, token)
if err != nil {
return nil, err
}
return []*http.Cookie{c}, nil
} else {
c := createDeleteCookie(ce.config, request.Host)
c := ce.createDeleteCookie(request.Host)
return []*http.Cookie{c}, nil
}
}

func (ce *EncryptedCookieEncoder) Read(request *http.Request) (*oauth2.Token, error) {
c, err := extractCookie(request, ce.config)
c, err := ce.extractCookie(request)
if err != nil {
return nil, err
}
Expand All @@ -61,19 +65,14 @@ type cookie struct {
Domain string `json:"domain,omitempty"`
}

func decodeCookie(cookieHeader string, config *OAuthConfig) (c *cookie, err error) {
func (ce *EncryptedCookieEncoder) decodeCookie(cookieHeader string) (c *cookie, err error) {
var eb []byte
if eb, err = base64.StdEncoding.DecodeString(cookieHeader); err != nil {
return
}

var encryption secrets.Encryption
if encryption, err = config.Secrets.GetEncrypter(secretsRefreshInternal, config.SecretFile); err != nil {
return
}

var b []byte
if b, err = encryption.Decrypt(eb); err != nil {
if b, err = ce.Encryption.Decrypt(eb); err != nil {
return
}

Expand All @@ -98,14 +97,14 @@ func (c *cookie) allowedForHost(host string) bool {
// cookie of the same name.
// The grant token cookie is extracted so it does not get exposed to untrusted downstream
// services.
func extractCookie(request *http.Request, config *OAuthConfig) (*cookie, error) {
func (ce *EncryptedCookieEncoder) extractCookie(request *http.Request) (*cookie, error) {
cookies := request.Cookies()
for i, c := range cookies {
if c.Name != config.TokenCookieName {
if c.Name != ce.CookieName {
continue
}

decoded, err := decodeCookie(c.Value, config)
decoded, err := ce.decodeCookie(c.Value)
if err == nil && decoded.allowedForHost(request.Host) {
request.Header.Del("Cookie")
for j, c := range cookies {
Expand All @@ -121,20 +120,20 @@ func extractCookie(request *http.Request, config *OAuthConfig) (*cookie, error)

// createDeleteCookie creates a cookie, which instructs the client to clear the grant
// token cookie when used with a Set-Cookie header.
func createDeleteCookie(config *OAuthConfig, host string) *http.Cookie {
func (ce *EncryptedCookieEncoder) createDeleteCookie(host string) *http.Cookie {
return &http.Cookie{
Name: config.TokenCookieName,
Name: ce.CookieName,
Value: "",
Path: "/",
Domain: extractDomainFromHost(host, *config.TokenCookieRemoveSubdomains),
Domain: extractDomainFromHost(host, ce.RemoveSubdomains),
MaxAge: -1,
Secure: !config.Insecure,
Secure: !ce.Insecure,
HttpOnly: true,
}
}

func createCookie(config *OAuthConfig, host string, t *oauth2.Token) (*http.Cookie, error) {
domain := extractDomainFromHost(host, *config.TokenCookieRemoveSubdomains)
func (ce *EncryptedCookieEncoder) createCookie(host string, t *oauth2.Token) (*http.Cookie, error) {
domain := extractDomainFromHost(host, ce.RemoveSubdomains)
c := &cookie{
AccessToken: t.AccessToken,
RefreshToken: t.RefreshToken,
Expand All @@ -147,12 +146,7 @@ func createCookie(config *OAuthConfig, host string, t *oauth2.Token) (*http.Cook
return nil, err
}

encryption, err := config.Secrets.GetEncrypter(secretsRefreshInternal, config.SecretFile)
if err != nil {
return nil, err
}

eb, err := encryption.Encrypt(b)
eb, err := ce.Encryption.Encrypt(b)
if err != nil {
return nil, err
}
Expand All @@ -165,12 +159,12 @@ func createCookie(config *OAuthConfig, host string, t *oauth2.Token) (*http.Cook
// Since we don't know the actual refresh token expiry, set it to
// 30 days as a good compromise.
return &http.Cookie{
Name: config.TokenCookieName,
Name: ce.CookieName,
Value: b64,
Path: "/",
Domain: domain,
Expires: t.Expiry.Add(time.Hour * 24 * 30),
Secure: !config.Insecure,
Secure: !ce.Insecure,
HttpOnly: true,
}, nil
}

0 comments on commit 54a3e3d

Please sign in to comment.