This repository has been archived by the owner on Oct 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathcookie_manager.go
121 lines (105 loc) · 3.46 KB
/
cookie_manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package auth
import (
"context"
"encoding/base64"
"net/http"
"time"
"github.com/lyft/flytestdlib/errors"
"github.com/lyft/flytestdlib/logger"
"golang.org/x/oauth2"
)
type CookieManager struct {
hashKey []byte
blockKey []byte
}
const (
ErrB64Decoding errors.ErrorCode = "BINARY_DECODING_FAILED"
// #nosec
ErrTokenNil errors.ErrorCode = "EMPTY_OAUTH_TOKEN"
)
func NewCookieManager(ctx context.Context, hashKeyEncoded, blockKeyEncoded string) (CookieManager, error) {
logger.Infof(ctx, "Instantiating cookie manager")
hashKey, err := base64.RawStdEncoding.DecodeString(hashKeyEncoded)
if err != nil {
return CookieManager{}, errors.Wrapf(ErrB64Decoding, err, "Error decoding hash key bytes")
}
blockKey, err := base64.RawStdEncoding.DecodeString(blockKeyEncoded)
if err != nil {
return CookieManager{}, errors.Wrapf(ErrB64Decoding, err, "Error decoding block key bytes")
}
return CookieManager{
hashKey: hashKey,
blockKey: blockKey,
}, nil
}
// TODO: Separate refresh token from access token, remove named returns, and use stdlib errors.
func (c CookieManager) RetrieveTokenValues(ctx context.Context, request *http.Request) (accessToken string,
refreshToken string, err error) {
jwtCookie, err := request.Cookie(accessTokenCookieName)
if err != nil || jwtCookie == nil {
logger.Errorf(ctx, "Could not detect existing access token cookie")
return
}
logger.Debugf(ctx, "Existing JWT cookie found")
accessToken, err = ReadSecureCookie(ctx, *jwtCookie, c.hashKey, c.blockKey)
if err != nil {
logger.Errorf(ctx, "Error reading existing secure JWT cookie %s", err)
return
}
refreshCookie, err := request.Cookie(refreshTokenCookieName)
if err != nil || refreshCookie == nil {
logger.Debugf(ctx, "Could not detect existing access token cookie")
return
}
logger.Debugf(ctx, "Existing refresh cookie found")
refreshToken, err = ReadSecureCookie(ctx, *refreshCookie, c.hashKey, c.blockKey)
if err != nil {
logger.Errorf(ctx, "Error reading existing secure refresh cookie %s", err)
return
}
return
}
func (c CookieManager) SetTokenCookies(ctx context.Context, writer http.ResponseWriter, token *oauth2.Token) error {
if token == nil {
logger.Errorf(ctx, "Attempting to set cookies with nil token")
return errors.Errorf(ErrTokenNil, "Attempting to set cookies with nil token")
}
jwtCookie, err := NewSecureCookie(accessTokenCookieName, token.AccessToken, c.hashKey, c.blockKey)
if err != nil {
logger.Errorf(ctx, "Error generating encrypted JWT cookie %s", err)
return err
}
http.SetCookie(writer, &jwtCookie)
// Set the refresh cookie if there is a refresh token
if token.RefreshToken != "" {
refreshCookie, err := NewSecureCookie(refreshTokenCookieName, token.RefreshToken, c.hashKey, c.blockKey)
if err != nil {
logger.Errorf(ctx, "Error generating encrypted refresh cookie %s", err)
return err
}
http.SetCookie(writer, &refreshCookie)
}
return nil
}
func getLogoutAccessCookie() *http.Cookie {
return &http.Cookie{
Name: accessTokenCookieName,
Value: "",
MaxAge: 0,
HttpOnly: true,
Expires: time.Now().Add(-1 * time.Hour),
}
}
func getLogoutRefreshCookie() *http.Cookie {
return &http.Cookie{
Name: refreshTokenCookieName,
Value: "",
MaxAge: 0,
HttpOnly: true,
Expires: time.Now().Add(-1 * time.Hour),
}
}
func (c CookieManager) DeleteCookies(ctx context.Context, writer http.ResponseWriter) {
http.SetCookie(writer, getLogoutAccessCookie())
http.SetCookie(writer, getLogoutRefreshCookie())
}