cookie not issued on prod.
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.6k
- Forks
- 631
- PR merge metrics
- No merged PRs in 30d
Description
it works greate locally but in prod cookie doesnt get issued over https:
here is my google handler function:
func GoogleCallbackHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Println("GoogleAuthHandler called.")
//log all headers before the redirect
for key, values := range w.Header() {
for _, value := range values {
log.Printf("Header: %s=%s", key, value)
}
}
// Check for the "code" query parameter.
code := r.URL.Query().Get("code")
if code == "" {
// User canceled the Google account selection.
log.Println("Google authentication canceled by user (no code parameter).")
// Redirect to a safe location or display an error.
http.Redirect(w, r, "/", http.StatusFound) // Redirect to home page.
return // Crucial: Stop further execution.
}
// Finalize the authentication process (only if "code" is present).
user, err := gothic.CompleteUserAuth(w, r)
if err != nil {
http.Error(w, "Authentication failed", http.StatusUnauthorized)
log.Println(err)
return
}
// Directly perform FindOrCreateUser logic here
ctx := r.Context()
userEmail := user.Email
userID := uuid.New().String()
log.Println("id", userID)
// Assuming db.DB is a *pgxpool.Pool
// Check if user exists
query := `SELECT id FROM "User" WHERE email = $1`
err = db.DB.QueryRow(ctx, query, userEmail).Scan(&userID)
if err == nil {
// User exists, userID is already set
log.Println("skipped...")
} else if err.Error() == "no rows in result set" { // Use err.Error() for pgxpool
// User does not exist, create new user
query = `INSERT INTO "User" (id, "fullName", email, "avatarUrl") VALUES ($1, $2, $3, $4)` // Include id
_, err = db.DB.Exec(ctx, query, userID, user.Name, user.Email, user.AvatarURL) // use Exec since we already have the id
if err != nil {
http.Error(w, "Database error", http.StatusInternalServerError)
log.Println(err)
return
}
// Set User Preference
query = `INSERT INTO "UserPreference" ("userId") VALUES ($1)` // Include id
_, err = db.DB.Exec(ctx, query, userID) // use Exec since we already have the id
if err != nil {
http.Error(w, "Database error", http.StatusInternalServerError)
log.Println(err)
return
}
} else {
http.Error(w, "Database error", http.StatusInternalServerError)
log.Println(err)
return
}
// Save user ID in the gothic session (as gothic requires).
err = gothic.StoreInSession("user_id", userID, r, w)
if err != nil {
http.Error(w, "Failed to save session", http.StatusInternalServerError)
log.Println(err)
return
}
// Save user data in the custom session store.
session, _ := utils.SessionStore.Get(r, "user_session")
session.Values["user_id"] = userID
session.Save(r, w)
var redirectSecure string
if utils.IsProd {
redirectSecure = os.Getenv("REDIRECT_SECURE_PROD")
} else {
redirectSecure = os.Getenv("REDIRECT_SECURE")
}
// Redirect to home page
if redirectSecure == "" {
redirectSecure = "http://localhost:3000"
}
http.Redirect(w, r, redirectSecure, http.StatusFound)
}
}
in main i initialze a session:
var SessionStore *sessions.CookieStore
func init() {
// Initialize Zerolog with pretty console output
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger()
log.SetOutput(logger)
// Load environment variables
if err := godotenv.Load(); err != nil {
LogInfoWithPrettyError("init", "No .env file found, using system environment variables", err)
}
// Load environment variables (moved to main)
isProduction := os.Getenv("ENV") == "production"
LogInfoWithPrettyError("init", fmt.Sprintf("is production: %v", isProduction), nil)
sessionSecret := os.Getenv("SESSION_SECRET")
if sessionSecret == "" {
LogWarnWithPrettyError("init", "SESSION_SECRET environment variable not set, using default (not recommended for production)", nil)
sessionSecret = "default-session-secret"
}
LogDebugWithPrettyError("init", "Session key loaded", nil)
var domain string
if isProduction {
domain = os.Getenv("SESSION_COOKIE_DOMAIN_PROD")
} else {
domain = os.Getenv("SESSION_COOKIE_DOMAIN")
}
LogDebugWithPrettyError("init", fmt.Sprintf("Session cookie domain: %s", domain), nil)
SessionStore = sessions.NewCookieStore([]byte(sessionSecret))
SessionStore.Options = &sessions.Options{
HttpOnly: true,
Secure: isProduction,
Path: "/",
MaxAge: 86400 * 30,
Domain: domain, // Ensure this is set in .env
SameSite: http.SameSiteNoneMode,
}
LogDebugWithPrettyError("init", "Session store initialized", nil)
gothic.Store = SessionStore // Tell gothic to use our session store
LogDebugWithPrettyError("init", "Gothic store set", nil)
clientID := os.Getenv("GOOGLE_CLIENT_ID")
clientSecret := os.Getenv("GOOGLE_CLIENT_SECRET")
var callbackURL string
if isProduction {
callbackURL = os.Getenv("GOOGLE_CALLBACK_URL_PROD")
} else {
callbackURL = os.Getenv("GOOGLE_CALLBACK_URL")
}
LogDebugWithPrettyError("init", fmt.Sprintf("Google Client ID: %s", clientID), nil)
LogDebugWithPrettyError("init", "Google Client Secret loaded", nil)
LogDebugWithPrettyError("init", fmt.Sprintf("Google Callback URL: %s", callbackURL), nil)
if clientID == "" || clientSecret == "" || callbackURL == "" {
LogWarnWithPrettyError("init", "Error: Google OAuth environment variables are not fully set in .env", nil)
}
goth.UseProviders(
google.New(clientID, clientSecret, callbackURL, "email", "profile"),
)
LogDebugWithPrettyError("init", "Google OAuth provider initialized", nil)
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue provides no repository file or test path; start by locating GoogleCallbackHandler and the init function that configures SessionStore. Compare their behavior and production environment values under HTTPS, then verify the response headers and session behavior. Done means identifying a reproducible production cause and confirming the cookie works, but the issue does not define a repository-specific test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 18/100