Remove dummy user_id from OAuth state sessions
Use a simple signed cookie for OAuth state instead of PGStore, which required a dummy user_id placeholder to satisfy the session store's save logic. Fixes #24 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e3ef03ddcd
commit
c24f712cb6
|
|
@ -53,12 +53,16 @@ func (h *OAuthHandler) Login(c *gin.Context) {
|
|||
}
|
||||
|
||||
state := generateState()
|
||||
session, _ := h.deps.SessionStore.Get(c.Request, "oauth_state")
|
||||
session.Values["state"] = state
|
||||
session.Values["user_id"] = "00000000-0000-0000-0000-000000000000" // placeholder for save
|
||||
if err := session.Save(c.Request, c.Writer); err != nil {
|
||||
log.Error().Err(err).Msg("save oauth state error")
|
||||
}
|
||||
isSecure := strings.HasPrefix(h.deps.Config.BaseURL, "https")
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: "oauth_state",
|
||||
Value: state,
|
||||
Path: "/",
|
||||
MaxAge: 600, // 10 minutes
|
||||
HttpOnly: true,
|
||||
Secure: isSecure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
|
||||
url := provider.Config.AuthCodeURL(state, oauth2.AccessTypeOffline)
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
|
|
@ -73,12 +77,17 @@ func (h *OAuthHandler) Callback(c *gin.Context) {
|
|||
}
|
||||
|
||||
// Verify state
|
||||
session, _ := h.deps.SessionStore.Get(c.Request, "oauth_state")
|
||||
expectedState, _ := session.Values["state"].(string)
|
||||
if c.Query("state") != expectedState {
|
||||
stateCookie, err := c.Request.Cookie("oauth_state")
|
||||
if err != nil || c.Query("state") != stateCookie.Value {
|
||||
c.String(http.StatusBadRequest, "Invalid state parameter")
|
||||
return
|
||||
}
|
||||
// Clear the state cookie
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: "oauth_state",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
})
|
||||
|
||||
code := c.Query("code")
|
||||
token, err := provider.Config.Exchange(c.Request.Context(), code)
|
||||
|
|
@ -137,12 +146,16 @@ func (h *OAuthHandler) appleLogin(c *gin.Context) {
|
|||
}
|
||||
|
||||
state := generateState()
|
||||
session, _ := h.deps.SessionStore.Get(c.Request, "oauth_state")
|
||||
session.Values["state"] = state
|
||||
session.Values["user_id"] = "00000000-0000-0000-0000-000000000000"
|
||||
if err := session.Save(c.Request, c.Writer); err != nil {
|
||||
log.Error().Err(err).Msg("save oauth state error")
|
||||
}
|
||||
isSecure := strings.HasPrefix(h.deps.Config.BaseURL, "https")
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: "oauth_state",
|
||||
Value: state,
|
||||
Path: "/",
|
||||
MaxAge: 600, // 10 minutes
|
||||
HttpOnly: true,
|
||||
Secure: isSecure,
|
||||
SameSite: http.SameSiteNoneMode, // Apple uses form_post cross-origin
|
||||
})
|
||||
|
||||
url := appleProvider.Config.AuthCodeURL(state, oauth2.AccessTypeOffline, auth.AppleAuthCodeOption())
|
||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||
|
|
@ -164,12 +177,17 @@ func (h *OAuthHandler) AppleCallback(c *gin.Context) {
|
|||
code := c.PostForm("code")
|
||||
state := c.PostForm("state")
|
||||
|
||||
session, _ := h.deps.SessionStore.Get(c.Request, "oauth_state")
|
||||
expectedState, _ := session.Values["state"].(string)
|
||||
if state != expectedState {
|
||||
stateCookie, err := c.Request.Cookie("oauth_state")
|
||||
if err != nil || state != stateCookie.Value {
|
||||
c.String(http.StatusBadRequest, "Invalid state parameter")
|
||||
return
|
||||
}
|
||||
// Clear the state cookie
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: "oauth_state",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
})
|
||||
|
||||
token, err := appleProvider.ExchangeCode(c.Request.Context(), code)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue