diff --git a/cookies.go b/cookies.go index 92cb7af..b5b0018 100644 --- a/cookies.go +++ b/cookies.go @@ -172,6 +172,42 @@ func SetCookieWithMaxAge(w http.ResponseWriter, email string, token string, maxA return nil } +// ClearCookie instructs the browser to delete the "goffee" session cookie. +// It writes an empty cookie with a MaxAge of -1 (immediate deletion) and an +// expiration in the past, using the same attributes as when the cookie was set +// (Path, HttpOnly, SameSite and Secure) so the browser reliably removes it. +// +// This complements a server-side signout: deleting the cached token prevents any +// further authenticated use of the session, while clearing the cookie removes the +// now-useless cookie from the client. +func ClearCookie(w http.ResponseWriter) error { + // Determine if the cookie should have the Secure flag, mirroring SetCookieWithMaxAge. + // Set COOKIE_SECURE=false (or "0", "f") in your .env for local development over HTTP. + // Defaults to true for production safety. + cookieSecureStr := os.Getenv("COOKIE_SECURE") + if cookieSecureStr == "" { + cookieSecureStr = "true" + } + cookieSecure, _ := strconv.ParseBool(cookieSecureStr) + + cookie := http.Cookie{ + Name: "goffee", + Value: "", + Path: "/", + MaxAge: -1, + Expires: time.Unix(0, 0), + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + Secure: cookieSecure, + } + + // The value is empty, so there is nothing to encrypt. Write the deletion + // cookie directly so the browser removes the existing session cookie. + http.SetCookie(w, &cookie) + + return nil +} + // CookieWrite writes a secure HTTP cookie to the response writer after base64 encoding its value. // Returns ErrValueTooLong if the cookie string exceeds the 4096-byte size limit. func CookieWrite(w http.ResponseWriter, cookie http.Cookie) error {