Goth returning error during oauth callback "could not find a matching session for this request".
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.6k
- Forks
- 631
- PR merge metrics
- No merged PRs in 30d
Description
My oauth is not working for production, I deployed the server and client as web service on render.com using docker container.
Here is the server url : [server(go)](https://server-6zuj.onrender.com)
and client url: [nextjs](https://client-2r99.onrender.com)
The error I am getting from the server is: "Error completing OAuth authentication: could not find a matching session for this request."
`router.go`
```go
package router
import (
"net/http"
"time"
"github.com/cprakhar/datawhiz/config"
"github.com/cprakhar/datawhiz/internal/handlers"
"github.com/cprakhar/datawhiz/internal/middleware"
"github.com/gin-contrib/cors"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/markbates/goth/gothic"
)
// NewRouter initializes the Gin router with the necessary routes and middleware.
func NewRouter(cfg *config.Config) *gin.Engine {
router := gin.Default()
var sameSite http.SameSite
switch cfg.Env.SameSite {
case "lax":
sameSite = http.SameSiteLaxMode
case "strict":
sameSite = http.SameSiteStrictMode
case "none":
sameSite = http.SameSiteNoneMode
default:
sameSite = http.SameSiteLaxMode // Default to Lax if not specified
}
store := cookie.NewStore([]byte(cfg.Env.SessionSecret))
store.Options(sessions.Options{
Path: "/",
MaxAge: int(cfg.Env.SessionMaxAge),
HttpOnly: true,
Secure: cfg.Env.SessionSecure,
SameSite: sameSite,
})
gothic.Store = store
cors := cors.New(cors.Config{
AllowOrigins: []string{cfg.Env.FrontendBaseURL},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH","DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
})
router.Use(sessions.Sessions(gothic.SessionName, store))
router.Use(cors)
h := &handlers.Handler{Cfg: cfg}
h.InitProviders()
api := router.Group("/api/v1")
api.GET("/health", h.HandleHealthCheck)
api.POST("/auth/register", h.HandleRegister)
api.GET("/auth/oauth/signin", h.HandleOAuthSignIn)
api.GET("/auth/oauth/callback", h.HandleOAuthCallback)
api.POST("/auth/login", h.HandleLogin)
api.POST("/auth/logout", middleware.RequireAuth(), h.HandleLogout)
api.GET("/auth/me", middleware.RequireAuth(), h.HandleMe)
api.GET("/connections", middleware.RequireAuth(), h.HandleGetConnections)
api.GET("/connections/:id", middleware.RequireAuth(), h.HandleGetConnection)
api.POST("/connections/ping", middleware.RequireAuth(), h.HandlePingConnection)
api.POST("/connections", middleware.RequireAuth(), h.HandleCreateConnection)
api.POST("/connections/:id/activate", middleware.RequireAuth(), h.HandleActivateConnection)
api.DELETE("/connections/:id/deactivate", middleware.RequireAuth(), h.HandleDeactivateConnection)
api.DELETE("/connections/:id", middleware.RequireAuth(), h.HandleDeleteConnection)
api.GET("/tables/:id", middleware.RequireAuth(), h.HandleGetTables)
api.GET("/tables/:id/:table_name/schema", middleware.RequireAuth(), h.HandleGetTableSchema)
api.GET("/tables/:id/:table_name/records", middleware.RequireAuth(), h.HandleGetTableRecords)
api.POST("/query/:id/generate", middleware.RequireAuth(), h.HandleGenerateQuery)
api.POST("/query/:id/execute", middleware.RequireAuth(), h.HandleExecuteQuery)
api.GET("/query/history/:id", middleware.RequireAuth(), h.HandleGetQueryHistory)
api.DELETE("/query/history/:id", middleware.RequireAuth(), h.HandleDeleteQueryHistory)
return router
}
```
`oauth.go`
```go
package handlers
import (
"context"
"log"
"net/http"
"github.com/cprakhar/datawhiz/internal/database/schema"
"github.com/cprakhar/datawhiz/internal/database/users"
"github.com/cprakhar/datawhiz/utils/response"
"github.com/cprakhar/datawhiz/utils/secure"
"github.com/gin-gonic/gin"
"github.com/markbates/goth"
"github.com/markbates/goth/gothic"
"github.com/markbates/goth/providers/github"
"github.com/markbates/goth/providers/google"
)
// InitProviders initializes the OAuth providers with the necessary credentials.
func (h *Handler) InitProviders() {
goth.UseProviders(
google.New(
h.Cfg.Env.GoogleClientID,
h.Cfg.Env.GoogleClientSecret,
h.Cfg.Env.BackendBaseURL + "/api/v1/auth/oauth/callback?provider=google",
"email", "profile",
),
github.New(
h.Cfg.Env.GitHubClientID,
h.Cfg.Env.GitHubClientSecret,
h.Cfg.Env.BackendBaseURL + "/api/v1/auth/oauth/callback?provider=github",
"read:user",
),
)
}
// HandleOAuthSignIn initiates the OAuth sign-in process by redirecting to the provider's authentication page.
func (h *Handler) HandleOAuthSignIn (ctx *gin.Context) {
provider := ctx.Query("provider")
log.Println(ctx.Request.URL)
type providerKeyType string
const providerKey providerKeyType = "oauth_provider"
req := ctx.Request.WithContext(context.WithValue(ctx, providerKey, provider))
session, err := gothic.Store.Get(ctx.Request, gothic.SessionName)
if err != nil {
log.Println("Error getting session:", err)
response.InternalError(ctx, err)
return
}
session.Values["oauth_provider"] = provider
session.Save(ctx.Request, ctx.Writer)
gothic.BeginAuthHandler(ctx.Writer, req)
}
// HandleOAuthCallback handles the OAuth callback after the user has authenticated with the provider.
func (h *Handler) HandleOAuthCallback(ctx *gin.Context) {
provider := ctx.Query("provider")
redirectURL := h.Cfg.Env.FrontendBaseURL + "/auth/oauth/callback?provider=" + provider
req := gothic.GetContextWithProvider(ctx.Request, provider)
user, err := gothic.CompleteUserAuth(ctx.Writer, req)
if err != nil {
log.Println("Error completing OAuth authentication:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
exists, err := users.CheckUserExists(h.Cfg.DBClient, user.Email)
if err != nil {
log.Println("Error checking if user exists:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
if !exists {
newUser := &schema.User{
Name: user.Name,
Email: user.Email,
AvatarURL: user.AvatarURL,
OAuthProvider: provider,
OAuthID: user.UserID,
}
createdUser, err := users.InsertOneUser(h.Cfg.DBClient, newUser)
if err != nil {
log.Println("Error creating new user:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
err = secure.SetSessionCookie(ctx,
map[string]interface{}{
"user_id": createdUser.ID,
"email": createdUser.Email,
},
)
if err != nil {
log.Println("Error setting session cookie:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=success")
return
}
upsertUser := &schema.User{
Name: user.Name,
Email: user.Email,
AvatarURL: user.AvatarURL,
OAuthProvider: provider,
OAuthID: user.UserID,
}
updatedUser, err := users.UpsertOAuthUser(h.Cfg.DBClient, upsertUser)
if err != nil {
log.Println("Error upserting user:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
err = secure.SetSessionCookie(ctx,
map[string]interface{}{
"user_id": updatedUser.ID,
"email": updatedUser.Email,
},
)
if err != nil {
log.Println("Error setting session cookie:", err)
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=error")
return
}
ctx.Redirect(http.StatusTemporaryRedirect, redirectURL+"&status=success")
}
```
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
Start with router.go and oauth.go, tracing the deployed sign-in and callback flow from the Render URLs through session creation and cookie handling. Compare the production session, CORS, SameSite, Secure, and OAuth redirect configuration shown in these entry points. Done means the production callback completes authentication without the matching-session error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go, nextjs
- Domain
- authentication, backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100