Skip to content

Instantly share code, notes, and snippets.

@ptman
Created May 2, 2022 11:59
Show Gist options
  • Save ptman/f583b0a58e1de2a788789fbc10e4fb9a to your computer and use it in GitHub Desktop.
Save ptman/f583b0a58e1de2a788789fbc10e4fb9a to your computer and use it in GitHub Desktop.
session cookies in go
func errPanic(err error) {
if err != nil {
panic(err)
}
}
func secureRandom(size int) ([]byte, error) {
nonce := make([]byte, size)
_, err := cryptorand.Read(nonce)
errPanic(err)
return nonce, nil
}
type session struct {
Expires time.Time `json:"expires"`
Email string `json:"email"`
}
func (s *session) marshal() (string, error) {
buf, err := json.Marshal(s)
errPanic(err)
aead, err := chacha20poly1305.NewX([]byte(conf.SessionKey))
errPanic(err)
nonce, err := secureRandom(aead.NonceSize())
errPanic(err)
buf = aead.Seal(nonce, nonce, buf, nil)
return base64.RawURLEncoding.EncodeToString(buf), nil
}
func unmarshalSession(b string) (*session, error) {
buf, err := base64.RawURLEncoding.DecodeString(b)
errPanic(err)
aead, err := chacha20poly1305.NewX([]byte(conf.SessionKey))
errPanic(err)
nonce, ciphertext := buf[:aead.NonceSize()], buf[aead.NonceSize():]
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
errPanic(err)
s := &session{}
errPanic(json.Unmarshal(plaintext, s))
return s, nil
}
func (s *session) store(w http.ResponseWriter) {
value, err := s.marshal()
errPanic(err)
cookie := &http.Cookie{
Name: conf.SessionName,
Value: value,
SameSite: http.SameSiteLaxMode,
Path: "/",
HttpOnly: true,
Secure: conf.CookieSecure,
Expires: s.Expires,
MaxAge: int(time.Until(s.Expires).Seconds()),
}
http.SetCookie(w, cookie)
}
func sessionFromRequest(r *http.Request) (*session, error) {
cookie, err := r.Cookie(conf.SessionName)
if errors.Is(err, http.ErrNoCookie) || cookie.Value == "" {
return &session{
Expires: time.Now().Add(time.Hour),
}, nil
}
s, err := unmarshalSession(cookie.Value)
errPanic(err)
return s, nil
}
func handler(w http.ResponseWriter, r *http.Request) {
session, err := sessionFromRequest(r)
errPanic(err)
session.store(w)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment