// Package api - docs session cookie. // // The SPA keeps its session token in localStorage and sends it as a bearer // header, so a plain browser navigation to /api/docs carries no credentials. // To let a signed-in operator open the interactive docs in a new tab, login // also sets the session token as an HttpOnly cookie scoped to Path=/api/docs. // Because of the path scope the cookie is never sent to any /api/v1 route, so // cookie auth cannot be used for state-changing requests (no CSRF surface); // Swagger's "Try it out" still needs an explicit bearer token / API key. package api import ( "net/http" "time" ) // DocsCookieName is the cookie extractToken reads when no header token is present. const DocsCookieName = "session" // DocsCookiePath scopes the cookie to the docs pages only. const DocsCookiePath = "/api/docs" // SetDocsSessionCookie stores the session token for the docs pages. func SetDocsSessionCookie(w http.ResponseWriter, r *http.Request, token string, expires time.Time) { http.SetCookie(w, &http.Cookie{ Name: DocsCookieName, Value: token, Path: DocsCookiePath, Expires: expires, HttpOnly: true, Secure: requestIsSecure(r), SameSite: http.SameSiteLaxMode, }) } // ClearDocsSessionCookie removes the docs cookie (logout). func ClearDocsSessionCookie(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, &http.Cookie{ Name: DocsCookieName, Value: "", Path: DocsCookiePath, MaxAge: -1, HttpOnly: true, Secure: requestIsSecure(r), SameSite: http.SameSiteLaxMode, }) } func requestIsSecure(r *http.Request) bool { return r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" }