Files

75 lines
1.9 KiB
Go
Raw Permalink Normal View History

package api
import (
"context"
"net/http"
"time"
"messenger/internal/auth"
)
const (
accessCookieName = "messenger_access"
refreshCookieName = "messenger_refresh"
accessTTL = 15 * time.Minute
refreshTTL = 30 * 24 * time.Hour
)
type ctxKey string
// ctxKeyUserID is the context key carrying the authenticated user ID.
const ctxKeyUserID ctxKey = "messenger.userID"
func userIDFrom(ctx context.Context) (int64, bool) {
id, ok := ctx.Value(ctxKeyUserID).(int64)
return id, ok
}
func withUserID(ctx context.Context, userID int64) context.Context {
return context.WithValue(ctx, ctxKeyUserID, userID)
}
// requireAuth parses the access-token cookie and injects the user ID
// into the request context.
func requireAuth(tm *auth.TokenManager, next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(accessCookieName)
if err != nil {
writeError(w, http.StatusUnauthorized, "missing access token")
return
}
userID, err := tm.ParseAccessToken(cookie.Value)
if err != nil {
writeError(w, http.StatusUnauthorized, "invalid access token")
return
}
next(w, r.WithContext(withUserID(r.Context(), userID)))
}
}
func setAuthCookies(w http.ResponseWriter, accessToken, refreshToken string, secure bool) {
http.SetCookie(w, &http.Cookie{
Name: accessCookieName,
Value: accessToken,
Path: "/",
HttpOnly: true,
Secure: secure,
SameSite: http.SameSiteLaxMode,
MaxAge: int(accessTTL.Seconds()),
})
http.SetCookie(w, &http.Cookie{
Name: refreshCookieName,
Value: refreshToken,
Path: "/",
HttpOnly: true,
Secure: secure,
SameSite: http.SameSiteLaxMode,
MaxAge: int(refreshTTL.Seconds()),
})
}
func clearAuthCookies(w http.ResponseWriter) {
http.SetCookie(w, &http.Cookie{Name: accessCookieName, Path: "/", MaxAge: -1})
http.SetCookie(w, &http.Cookie{Name: refreshCookieName, Path: "/", MaxAge: -1})
}