From 9cec502091c65933e151a07c7310fc80606cae1b Mon Sep 17 00:00:00 2001 From: cialloo Date: Wed, 8 Oct 2025 13:34:08 +0800 Subject: [PATCH] Enhance Steam login flow by adding nonce validation and error handling in callback logic --- src/internal/logic/steamlogincallbacklogic.go | 37 ++++++++++++++++++- src/internal/logic/steamlogininitlogic.go | 5 ++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/internal/logic/steamlogincallbacklogic.go b/src/internal/logic/steamlogincallbacklogic.go index 2952eda..a57c830 100644 --- a/src/internal/logic/steamlogincallbacklogic.go +++ b/src/internal/logic/steamlogincallbacklogic.go @@ -32,6 +32,39 @@ func (l *SteamLoginCallbackLogic) SteamLoginCallback(req *types.SteamLoginCallba // Get the frontend callback URL from config frontendCallbackURL := l.svcCtx.Config.Steam.FrontendCallbackURL + // Extract nonce from query parameter + nonce := r.URL.Query().Get("nonce") + if nonce == "" { + l.Logger.Errorf("Missing nonce in callback request") + redirectURL := fmt.Sprintf("%s?status=error&message=%s", frontendCallbackURL, url.QueryEscape("Invalid login session")) + http.Redirect(w, r, redirectURL, http.StatusFound) + return nil + } + + // Validate nonce exists in Redis + nonceKey := nonceKeyPrefix + nonce + exists, err := l.svcCtx.Redis.Exists(nonceKey) + if err != nil { + l.Logger.Errorf("Failed to check nonce in Redis: %v", err) + redirectURL := fmt.Sprintf("%s?status=error&message=%s", frontendCallbackURL, url.QueryEscape("Session validation failed")) + http.Redirect(w, r, redirectURL, http.StatusFound) + return nil + } + + if !exists { + l.Logger.Errorf("Invalid or expired nonce: %s", nonce) + redirectURL := fmt.Sprintf("%s?status=error&message=%s", frontendCallbackURL, url.QueryEscape("Login session expired or invalid")) + http.Redirect(w, r, redirectURL, http.StatusFound) + return nil + } + + // Delete nonce from Redis to prevent replay attacks + _, err = l.svcCtx.Redis.Del(nonceKey) + if err != nil { + l.Logger.Errorf("Failed to delete nonce from Redis: %v", err) + // Continue anyway - nonce will expire naturally + } + // Convert the request to a map for validation openidParams := map[string]string{ "openid.mode": req.OpenidMode, @@ -57,7 +90,7 @@ func (l *SteamLoginCallbackLogic) SteamLoginCallback(req *types.SteamLoginCallba } if !isValid { - l.Logger.Infof("Invalid Steam OpenID response") + l.Logger.Errorf("Invalid Steam OpenID response") // Redirect to frontend with failure status redirectURL := fmt.Sprintf("%s?status=failed&message=%s", frontendCallbackURL, url.QueryEscape("Steam authentication failed")) http.Redirect(w, r, redirectURL, http.StatusFound) @@ -65,7 +98,7 @@ func (l *SteamLoginCallbackLogic) SteamLoginCallback(req *types.SteamLoginCallba } // Successful validation - l.Logger.Infof("Steam login successful for Steam ID: %s", steamID) + l.Logger.Infof("Steam login successful for Steam ID: %s (nonce: %s)", steamID, nonce) // Redirect to frontend with success status and Steam ID redirectURL := fmt.Sprintf("%s?status=success&steamId=%s", frontendCallbackURL, steamID) diff --git a/src/internal/logic/steamlogininitlogic.go b/src/internal/logic/steamlogininitlogic.go index 17e21c7..57c49e6 100644 --- a/src/internal/logic/steamlogininitlogic.go +++ b/src/internal/logic/steamlogininitlogic.go @@ -51,8 +51,11 @@ func (l *SteamLoginInitLogic) SteamLoginInit(req *types.SteamLoginInitReq, w htt // Get the callback URL from config callbackURL := l.svcCtx.Config.Steam.CallbackURL + // Append nonce to callback URL for validation later + callbackURLWithNonce := fmt.Sprintf("%s?nonce=%s", callbackURL, nonce) + // Build the Steam OpenID redirect URL - redirectURL := steamauth.GetRedirectURL(callbackURL) + redirectURL := steamauth.GetRedirectURL(callbackURLWithNonce) l.Logger.Infof("Initiating Steam login with nonce: %s, callback URL: %s", nonce, callbackURL)