Cookies & Sessions
Cookies and sessions are essential for maintaining state in web applications. This section covers cookie management, session handling, and security best practices for stateful HTTP applications.
Cookie Management
http.SetCookie(response, name, value, options)
Sets a cookie in the HTTP response.
Syntax:
| SetCookie Syntax |
|---|
| http.SetCookie(response, name, value, options) (error)
|
Parameters: - response (map) - Response writer object - name (string) - Cookie name - value (string) - Cookie value - options (map) - Cookie options (domain, path, expires, etc.)
Examples:
Basic Cookie Setting:
| Basic Cookie Setting |
|---|
| package main
import http
import fmt
function setCookieHandler(request map, response map) {
// Set a simple cookie
http.SetCookie(response, "user_preference", "dark_theme", {})
// Set a cookie with options
http.SetCookie(response, "session_id", "abc123xyz", {
"httpOnly": true, // Prevent JavaScript access
"secure": true, // HTTPS only
"sameSite": "strict", // CSRF protection
"maxAge": 3600, // 1 hour expiration
"path": "/", // Available site-wide
"domain": ".example.com" // Available on subdomains
})
// Set a persistent cookie (expires in 30 days)
var thirtyDaysFromNow = getCurrentTimestamp() + (30 * 24 * 3600)
http.SetCookie(response, "remember_me", "true", {
"expires": thirtyDaysFromNow,
"httpOnly": true,
"secure": true,
"sameSite": "lax"
})
http.WriteResponse(response, 200, "text/plain", "Cookies set successfully")
}
|
Cookie Configuration Options:
| Cookie Configuration |
|---|
| package main
import http
// Comprehensive cookie configuration
function setSecureCookie(response map, name string, value string) {
var cookieOptions = {
"httpOnly": true, // Prevent XSS attacks
"secure": true, // HTTPS only
"sameSite": "strict", // CSRF protection
"maxAge": 3600, // 1 hour
"path": "/", // Available site-wide
"domain": "", // Current domain only
}
http.SetCookie(response, name, value, cookieOptions)
}
// Session cookie (expires when browser closes)
function setSessionCookie(response map, name string, value string) {
var sessionOptions = {
"httpOnly": true,
"secure": true,
"sameSite": "strict",
"path": "/"
// No maxAge or expires = session cookie
}
http.SetCookie(response, name, value, sessionOptions)
}
// Persistent cookie (long-term storage)
function setPersistentCookie(response map, name string, value string, days int) {
var expirationTime = getCurrentTimestamp() + (days * 24 * 3600)
var persistentOptions = {
"httpOnly": true,
"secure": true,
"sameSite": "lax",
"expires": expirationTime,
"path": "/"
}
http.SetCookie(response, name, value, persistentOptions)
}
|
http.GetCookie(request, name)
Gets a cookie value from the HTTP request.
Syntax:
| GetCookie Syntax |
|---|
| http.GetCookie(request, name) (value, error)
|
Parameters: - request (map) - Request object - name (string) - Cookie name
Examples:
Reading Cookies:
| Reading Cookies |
|---|
| package main
import http
import json
import fmt
function getCookieHandler(request map, response map) {
// Get a specific cookie
var sessionResult = http.GetCookie(request, "session_id")
var sessionId = sessionResult[0]
var sessionErr = sessionResult[1]
if sessionErr != None {
fmt.Printf("No session cookie found: %s\n", sessionErr)
} else {
fmt.Printf("Session ID: %s\n", sessionId)
}
// Get user preferences
var themeResult = http.GetCookie(request, "user_preference")
var theme = themeResult[0]
var themeErr = themeResult[1]
var responseData = {
"sessionId": sessionId,
"theme": theme,
"hasSession": sessionErr == None,
"hasTheme": themeErr == None
}
var jsonData, _ = json.Marshal(responseData)
http.WriteResponse(response, 200, "application/json", jsonData)
}
// Get all cookies from request
function getAllCookies(request map) {
var cookies = request["cookies"]
if cookies == None {
return {}
}
return cookies
}
function listCookiesHandler(request map, response map) {
var allCookies = getAllCookies(request)
var cookieList = []
for name, value in allCookies {
cookieList = append(cookieList, {
"name": name,
"value": value
})
}
var responseData = {
"cookies": cookieList,
"count": len(cookieList)
}
var jsonData, _ = json.Marshal(responseData)
http.WriteResponse(response, 200, "application/json", jsonData)
}
|
Cookie Deletion
| Delete Cookie |
|---|
| package main
import http
// Delete a cookie by setting it to expire immediately
function deleteCookie(response map, name string) {
http.SetCookie(response, name, "", {
"httpOnly": true,
"secure": true,
"sameSite": "strict",
"maxAge": -1, // Expire immediately
"path": "/"
})
}
function deleteCookieHandler(request map, response map) {
var query = request["query"]
var cookieName = query["name"]
if cookieName == None or cookieName == "" {
http.WriteResponse(response, 400, "application/json", "{\"error\": \"Cookie name required\"}")
return
}
deleteCookie(response, cookieName)
var responseData = {
"message": "Cookie deleted",
"cookieName": cookieName
}
var jsonData, _ = json.Marshal(responseData)
http.WriteResponse(response, 200, "application/json", jsonData)
}
|
Session Management
Session Store Implementation
| Session Store |
|---|
| package main
import http
import json
import fmt
// In-memory session store (use Redis/database in production)
var sessionStore = {}
// Session structure
type Session struct {
id string
userId string
data map
createdAt int
lastAccessed int
expiresAt int
}
// Create a new session
function createSession(userId string, sessionData map) {
var sessionId = generateSessionId()
var currentTime = getCurrentTimestamp()
var session = {
"id": sessionId,
"userId": userId,
"data": sessionData,
"createdAt": currentTime,
"lastAccessed": currentTime,
"expiresAt": currentTime + 3600 // 1 hour default
}
sessionStore[sessionId] = session
return session
}
// Get session by ID
function getSession(sessionId string) {
var session = sessionStore[sessionId]
if session == None {
return None
}
// Check if session is expired
if isSessionExpired(session) {
delete(sessionStore, sessionId)
return None
}
// Update last accessed time
session["lastAccessed"] = getCurrentTimestamp()
return session
}
// Update session data
function updateSession(sessionId string, data map) {
var session = sessionStore[sessionId]
if session != None {
session["data"] = data
session["lastAccessed"] = getCurrentTimestamp()
return true
}
return false
}
// Destroy session
function destroySession(sessionId string) {
delete(sessionStore, sessionId)
}
// Check if session is expired
function isSessionExpired(session map) {
var expiresAt = session["expiresAt"]
var currentTime = getCurrentTimestamp()
return currentTime > expiresAt
}
// Generate secure session ID
function generateSessionId() {
// In a real implementation, use cryptographically secure random generator
return "sess_" + generateRandomString(64)
}
// Clean up expired sessions (run periodically)
function cleanupExpiredSessions() {
var currentTime = getCurrentTimestamp()
var expiredSessions = []
for sessionId, session in sessionStore {
if currentTime > session["expiresAt"] {
expiredSessions = append(expiredSessions, sessionId)
}
}
for sessionId in expiredSessions {
delete(sessionStore, sessionId)
}
fmt.Printf("Cleaned up %d expired sessions\n", len(expiredSessions))
}
|
Session Middleware
| Session Middleware |
|---|
| package main
import http
import fmt
// Session middleware that loads session data into request
function sessionMiddleware(next function) {
return function(request map, response map) {
var sessionId = getSessionIdFromCookie(request)
if sessionId != "" {
var session = getSession(sessionId)
if session != None {
// Add session to request context
request["session"] = session
request["sessionId"] = sessionId
request["userId"] = session["userId"]
request["sessionData"] = session["data"]
}
}
next(request, response)
}
}
function getSessionIdFromCookie(request map) {
var cookieResult = http.GetCookie(request, "session_id")
var sessionId = cookieResult[0]
var err = cookieResult[1]
if err != None {
return ""
}
return sessionId
}
// Session-aware handler example
function sessionAwareHandler(request map, response map) {
var session = request["session"]
var sessionData = request["sessionData"]
if session == None {
// No session - show login prompt
var responseData = {
"authenticated": false,
"message": "Please log in"
}
var jsonData, _ = json.Marshal(responseData)
http.WriteResponse(response, 401, "application/json", jsonData)
return
}
// Session exists - show user data
var responseData = {
"authenticated": true,
"userId": session["userId"],
"sessionData": sessionData,
"lastAccessed": session["lastAccessed"]
}
var jsonData, _ = json.Marshal(responseData)
http.WriteResponse(response, 200, "application/json", jsonData)
}
|
Login with Session Creation
| Login Session |
|---|
| package main
import http
import json
import fmt
function loginWithSessionHandler(request map, response map) {
var method = request["method"]
if method != "POST" {
http.WriteResponse(response, 405, "application/json", "{\"error\": \"Method not allowed\"}")
return
}
var body = request["body"]
var loginData, parseErr = json.Unmarshal(body)
if parseErr != None {
http.WriteResponse(response, 400, "application/json", "{\"error\": \"Invalid JSON\"}")
return
}
var username = loginData["username"]
var password = loginData["password"]
var rememberMe = loginData["rememberMe"]
// Authenticate user
var user = authenticateUser(username, password)
if user == None {
http.WriteResponse(response, 401, "application/json", "{\"error\": \"Invalid credentials\"}")
return
}
// Create session with user data
var sessionData = {
"username": user["username"],
"email": user["email"],
"roles": user["roles"],
"loginTime": getCurrentTimestamp()
}
var session = createSession(user["id"], sessionData)
// Set session cookie
var cookieOptions = {
"httpOnly": true,
"secure": true,
"sameSite": "strict",
"path": "/"
}
// Set expiration based on "remember me"
if rememberMe == true {
cookieOptions["maxAge"] = 30 * 24 * 3600 // 30 days
session["expiresAt"] = getCurrentTimestamp() + (30 * 24 * 3600)
} else {
// Session cookie (expires when browser closes)
session["expiresAt"] = getCurrentTimestamp() + 3600 // 1 hour
}
http.SetCookie(response, "session_id", session["id"], cookieOptions)
var loginResponse = {
"success": true,
"user": {
"id": user["id"],
"username": user["username"],
"email": user["email"]
},
"sessionId": session["id"]
}
var jsonData, _ = json.Marshal(loginResponse)
http.WriteResponse(response, 200, "application/json", jsonData)
}
function logoutWithSessionHandler(request map, response map) {
var sessionId = getSessionIdFromCookie(request)
if sessionId != "" {
destroySession(sessionId)
}
// Clear session cookie
deleteCookie(response, "session_id")
var logoutResponse = {
"success": true,
"message": "Logged out successfully"
}
var jsonData, _ = json.Marshal(logoutResponse)
http.WriteResponse(response, 200, "application/json", jsonData)
}
|
| Shopping Cart |
|---|
| package main
import http
import json
import fmt
// Shopping cart using sessions
function addToCartHandler(request map, response map) {
var method = request["method"]
if method != "POST" {
http.WriteResponse(response, 405, "application/json", "{\"error\": \"Method not allowed\"}")
return
}
var body = request["body"]
var cartData, parseErr = json.Unmarshal(body)
if parseErr != None {
http.WriteResponse(response, 400, "application/json", "{\"error\": \"Invalid JSON\"}")
return
}
var productId = cartData["productId"]
var quantity = cartData["quantity"]
if productId == None or quantity == None {
http.WriteResponse(response, 400, "application/json", "{\"error\": \"Product ID and quantity required\"}")
return
}
// Get or create session
var sessionId = getSessionIdFromCookie(request)
var session = None
if sessionId != "" {
session = getSession(sessionId)
}
if session == None {
// Create new session for anonymous user
session = createSession("anonymous", {"cart": {}})
http.SetCookie(response, "session_id", session["id"], {
"httpOnly": true,
"secure": true,
"sameSite": "strict",
"maxAge": 3600, // 1 hour
"path": "/"
})
}
// Get current cart
var sessionData = session["data"]
var cart = sessionData["cart"]
if cart == None {
cart = {}
}
// Add item to cart
var currentQuantity = cart[productId]
if currentQuantity == None {
currentQuantity = 0
}
cart[productId] = currentQuantity + quantity
// Update session
sessionData["cart"] = cart
updateSession(session["id"], sessionData)
var cartResponse = {
"success": true,
"cart": cart,
"itemCount": getCartItemCount(cart)
}
var jsonData, _ = json.Marshal(cartResponse)
http.WriteResponse(response, 200, "application/json", jsonData)
}
function getCartHandler(request map, response map) {
var sessionId = getSessionIdFromCookie(request)
var cart = {}
if sessionId != "" {
var session = getSession(sessionId)
if session != None {
var sessionData = session["data"]
cart = sessionData["cart"]
if cart == None {
cart = {}
}
}
}
var cartResponse = {
"cart": cart,
"itemCount": getCartItemCount(cart),
"total": calculateCartTotal(cart)
}
var jsonData, _ = json.Marshal(cartResponse)
http.WriteResponse(response, 200, "application/json", jsonData)
}
function getCartItemCount(cart map) {
var count = 0
for productId, quantity in cart {
count = count + quantity
}
return count
}
function calculateCartTotal(cart map) {
// In a real implementation, look up product prices
var total = 0.0
for productId, quantity in cart {
var price = getProductPrice(productId) // Mock function
total = total + (price * quantity)
}
return total
}
|
Security Best Practices
Secure Cookie Configuration
| Secure Cookie Config |
|---|
| package main
import http
// Production-ready secure cookie settings
function setSecureSessionCookie(response map, sessionId string) {
var secureOptions = {
"httpOnly": true, // Prevent XSS attacks
"secure": true, // HTTPS only
"sameSite": "strict", // CSRF protection
"maxAge": 3600, // 1 hour expiration
"path": "/", // Available site-wide
"domain": "", // Current domain only (no subdomains)
}
http.SetCookie(response, "session_id", sessionId, secureOptions)
}
// Development cookie settings (less restrictive)
function setDevelopmentCookie(response map, name string, value string) {
var devOptions = {
"httpOnly": true,
"secure": false, // Allow HTTP in development
"sameSite": "lax", // Less restrictive for development
"maxAge": 3600,
"path": "/"
}
http.SetCookie(response, name, value, devOptions)
}
|
Session Security
| Session Security |
|---|
| package main
import http
import fmt
// Session security middleware
function sessionSecurityMiddleware(next function) {
return function(request map, response map) {
var sessionId = getSessionIdFromCookie(request)
if sessionId != "" {
var session = getSession(sessionId)
if session != None {
// Check for session hijacking
if detectSessionHijacking(request, session) {
fmt.Printf("Potential session hijacking detected for session: %s\n", sessionId)
destroySession(sessionId)
deleteCookie(response, "session_id")
http.WriteResponse(response, 401, "application/json", "{\"error\": \"Session security violation\"}")
return
}
// Regenerate session ID periodically
if shouldRegenerateSessionId(session) {
var newSessionId = regenerateSessionId(session)
http.SetCookie(response, "session_id", newSessionId, {
"httpOnly": true,
"secure": true,
"sameSite": "strict",
"maxAge": 3600,
"path": "/"
})
}
}
}
next(request, response)
}
}
function detectSessionHijacking(request map, session map) {
// Check IP address consistency
var currentIP = getClientIP(request)
var sessionIP = session["data"]["ipAddress"]
if sessionIP != None and sessionIP != currentIP {
return true
}
// Check User-Agent consistency
var currentUA = request["headers"]["User-Agent"]
var sessionUA = session["data"]["userAgent"]
if sessionUA != None and sessionUA != currentUA {
return true
}
return false
}
function shouldRegenerateSessionId(session map) {
var lastRegeneration = session["data"]["lastRegeneration"]
var currentTime = getCurrentTimestamp()
// Regenerate every 30 minutes
return lastRegeneration == None or (currentTime - lastRegeneration) > 1800
}
function regenerateSessionId(oldSession map) {
var newSessionId = generateSessionId()
var oldSessionId = oldSession["id"]
// Copy session data to new ID
oldSession["id"] = newSessionId
oldSession["data"]["lastRegeneration"] = getCurrentTimestamp()
sessionStore[newSessionId] = oldSession
delete(sessionStore, oldSessionId)
return newSessionId
}
|
CSRF Protection with Sessions
| CSRF Protection |
|---|
| package main
import http
import json
// Generate CSRF token for session
function generateCSRFToken(sessionId string) {
var token = generateRandomString(32)
var session = getSession(sessionId)
if session != None {
session["data"]["csrfToken"] = token
updateSession(sessionId, session["data"])
}
return token
}
// CSRF protection middleware using sessions
function sessionCSRFMiddleware(next function) {
return function(request map, response map) {
var method = request["method"]
// Only check CSRF for state-changing methods
if method == "POST" or method == "PUT" or method == "DELETE" or method == "PATCH" {
var sessionId = getSessionIdFromCookie(request)
var session = getSession(sessionId)
if session == None {
http.WriteResponse(response, 401, "application/json", "{\"error\": \"No session found\"}")
return
}
var sessionCSRFToken = session["data"]["csrfToken"]
var requestCSRFToken = request["headers"]["X-CSRF-Token"]
if sessionCSRFToken == None or requestCSRFToken == None or sessionCSRFToken != requestCSRFToken {
http.WriteResponse(response, 403, "application/json", "{\"error\": \"CSRF token mismatch\"}")
return
}
}
next(request, response)
}
}
// Endpoint to get CSRF token
function getCSRFTokenHandler(request map, response map) {
var sessionId = getSessionIdFromCookie(request)
if sessionId == "" {
http.WriteResponse(response, 401, "application/json", "{\"error\": \"No session found\"}")
return
}
var csrfToken = generateCSRFToken(sessionId)
var tokenResponse = {
"csrfToken": csrfToken
}
var jsonData, _ = json.Marshal(tokenResponse)
http.WriteResponse(response, 200, "application/json", jsonData)
}
|
Complete Session-Based Application
| Complete Session App |
|---|
| package main
import http
import json
import fmt
// Complete session-based web application setup
function setupSessionBasedApp() {
var mux = http.NewMux()[0]
// Public routes
http.HandleFunc(mux, "/", homeHandler)
http.HandleFunc(mux, "/login", loginWithSessionHandler)
http.HandleFunc(mux, "/register", registerHandler)
// Session-protected routes
var sessionMux = http.NewMux()[0]
// Apply session middleware to all protected routes
var sessionHandler = sessionMiddleware(sessionMux)
// Protected endpoints
http.HandleFunc(sessionMux, "/profile", profileHandler)
http.HandleFunc(sessionMux, "/logout", logoutWithSessionHandler)
http.HandleFunc(sessionMux, "/cart", getCartHandler)
http.HandleFunc(sessionMux, "/cart/add", addToCartHandler)
http.HandleFunc(sessionMux, "/csrf-token", getCSRFTokenHandler)
// Mount session-protected routes
http.Handle(mux, "/app/", http.StripPrefix("/app", sessionHandler))
return mux
}
function startSessionServer() {
var mux = setupSessionBasedApp()
var server = http.NewServer(":8080")[0]
// Add security middleware
var secureHandler = chainMiddleware([
loggingMiddleware,
corsMiddleware,
securityHeadersMiddleware,
sessionSecurityMiddleware,
sessionCSRFMiddleware
])(mux)
http.SetHandler(server, secureHandler)
// Start session cleanup routine
go cleanupExpiredSessions() // Run in background
fmt.Println("🍪 Session-based server starting on :8080")
http.ListenAndServe(server)
}
|
Best Practices Summary
1. Cookie Security
- Always use
httpOnly for session cookies - Use
secure flag for HTTPS - Set appropriate
sameSite values - Use reasonable expiration times
2. Session Management
- Generate cryptographically secure session IDs
- Store minimal data in sessions
- Implement session expiration and cleanup
- Regenerate session IDs periodically
3. Security Measures
- Implement CSRF protection
- Detect and prevent session hijacking
- Use secure cookie configurations
- Validate session integrity
- Clean up expired sessions regularly
- Use external session stores (Redis) for scalability
- Implement session data compression if needed
- Monitor session storage usage
Next Steps