Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions pkg/ginmw/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ginmw

import (
"github.com/gin-gonic/gin"
"go.uber.org/fx"
)

// Middleware is the shared interface for Gin middlewares registered via FX.
// Both ctl-api and dashboard-ui BFF use this interface.
type Middleware interface {
Name() string
Handler() gin.HandlerFunc
}

// AsMiddleware annotates a constructor so FX collects it into the "middlewares" group.
func AsMiddleware(f any) any {
return fx.Annotate(
f,
fx.As(new(Middleware)),
fx.ResultTags(`group:"middlewares"`),
)
}
16 changes: 13 additions & 3 deletions services/ctl-api/internal/app/auth/service/cookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,39 @@ import (
// helpers concerned with the cross-domain nuon auth cookie

func (s *service) clearCookie(c *gin.Context) {
// Secure flag should be false for localhost (HTTP), true for production (HTTPS)
secure := s.cfg.RootDomain != "localhost"

http.SetCookie(c.Writer, &http.Cookie{
Name: NuonAuthCookieName,
Value: "",
Path: "/",
Domain: s.cfg.RootDomain,
MaxAge: -1,
Expires: time.Now().Add(-time.Hour),
Secure: true,
Secure: secure,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
}

func (s *service) setCookie(c *gin.Context, token string) {
s.l.Debug("setting cookie", zap.String("service", "auth"), zap.String("domain", s.cfg.RootDomain))
// Secure flag should be false for localhost (HTTP), true for production (HTTPS)
secure := s.cfg.RootDomain != "localhost"

s.l.Debug("setting cookie",
zap.String("service", "auth"),
zap.String("domain", s.cfg.RootDomain),
zap.Bool("secure", secure))

http.SetCookie(c.Writer, &http.Cookie{
Name: NuonAuthCookieName,
Value: token,
Path: "/",
Domain: s.cfg.RootDomain, // this should be the root domain
MaxAge: 86400, // 24 hours
Expires: time.Now().Add(time.Duration(s.cfg.NuonAuthSessionTTL) * time.Minute),
Secure: true,
Secure: secure,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
Expand Down
16 changes: 16 additions & 0 deletions services/ctl-api/internal/app/auth/service/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ func (s *service) Index(c *gin.Context) {
if tokenInfo, err := s.validateToken(token); err == nil {
isAuthenticated = true
email = tokenInfo.Email

// If already authenticated and a redirect URL is provided, redirect there
if redirectURL != "" {
validatedURL, err := s.validateRequestedURL(redirectURL)
if err != nil {
s.l.Warn("invalid redirect URL for authenticated user",
zap.String("url", redirectURL),
zap.Error(err))
} else {
s.l.Info("redirecting authenticated user to requested URL",
zap.String("email", email),
zap.String("url", validatedURL))
s.redirect302(c, validatedURL)
return
}
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion services/dashboard-ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

# production
/build
/dist

# misc
.DS_Store
Expand All @@ -39,4 +40,4 @@ test/mock-api-handlers.js
src/types/nuon-oapi-v3.d.ts
NOTES.md
compilation-analysis.json
analyze.js
analyze.js
Loading
Loading