diff --git a/api/Authenticator.api b/api/Authenticator.api index 4248f58..d106cf9 100644 --- a/api/Authenticator.api +++ b/api/Authenticator.api @@ -17,9 +17,7 @@ type ( type ( SteamLoginInitReq {} - SteamLoginInitResp { - RedirectUrl string `json:"redirectUrl"` - } +// No response needed - endpoint will redirect directly ) type ( @@ -55,10 +53,10 @@ service Authenticator { @doc ( summary: "Initiate Steam login" - description: "Redirects user to Steam OpenID login page" + description: "Redirects user to Steam OpenID login page with nonce for security" ) @handler steamLoginInitHandler - get /steam/login (SteamLoginInitReq) returns (SteamLoginInitResp) + get /steam/login (SteamLoginInitReq) @doc ( summary: "Steam login callback" diff --git a/src/etc/authenticator.yaml b/src/etc/authenticator.yaml index ffa9f16..ce56ceb 100644 --- a/src/etc/authenticator.yaml +++ b/src/etc/authenticator.yaml @@ -4,3 +4,8 @@ Port: 8888 Steam: CallbackURL: https://www.cialloo.com/api/authenticator/steam/callback + +Redis: + Host: redis.production.svc.cluster.local:6379 + Type: node + Pass: "" diff --git a/src/go.mod b/src/go.mod index 29268a8..83007a6 100644 --- a/src/go.mod +++ b/src/go.mod @@ -2,17 +2,20 @@ module src go 1.24.4 -require github.com/zeromicro/go-zero v1.9.1 +require ( + github.com/google/uuid v1.6.0 + github.com/zeromicro/go-zero v1.9.1 +) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fatih/color v1.18.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/grafana/pyroscope-go v1.2.7 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect @@ -26,6 +29,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/redis/go-redis/v9 v9.15.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect diff --git a/src/go.sum b/src/go.sum index 84515f6..8e556a2 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,5 +1,11 @@ +github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= +github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -7,6 +13,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -59,6 +67,8 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/redis/go-redis/v9 v9.15.0 h1:2jdes0xJxer4h3NUZrZ4OGSntGlXp4WbXju2nOTRXto= +github.com/redis/go-redis/v9 v9.15.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -74,6 +84,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/zeromicro/go-zero v1.9.1 h1:GZCl4jun/ZgZHnSvX3SSNDHf+tEGmEQ8x2Z23xjHa9g= github.com/zeromicro/go-zero v1.9.1/go.mod h1:bHOl7Xr7EV/iHZWEqsUNJwFc/9WgAMrPpPagYvOaMtY= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= diff --git a/src/internal/config/config.go b/src/internal/config/config.go index 39d182b..d4b165f 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -1,10 +1,14 @@ package config -import "github.com/zeromicro/go-zero/rest" +import ( + "github.com/zeromicro/go-zero/core/stores/redis" + "github.com/zeromicro/go-zero/rest" +) type Config struct { rest.RestConf Steam SteamConfig + Redis redis.RedisConf } type SteamConfig struct { diff --git a/src/internal/handler/steamlogininithandler.go b/src/internal/handler/steamlogininithandler.go index ea44398..419c760 100644 --- a/src/internal/handler/steamlogininithandler.go +++ b/src/internal/handler/steamlogininithandler.go @@ -3,10 +3,11 @@ package handler import ( "net/http" - "github.com/zeromicro/go-zero/rest/httpx" "src/internal/logic" "src/internal/svc" "src/internal/types" + + "github.com/zeromicro/go-zero/rest/httpx" ) // Initiate Steam login @@ -19,11 +20,10 @@ func steamLoginInitHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { } l := logic.NewSteamLoginInitLogic(r.Context(), svcCtx) - resp, err := l.SteamLoginInit(&req) + err := l.SteamLoginInit(&req, w, r) if err != nil { httpx.ErrorCtx(r.Context(), w, err) - } else { - httpx.OkJsonCtx(r.Context(), w, resp) } + // No response needed - redirect is handled in logic } } diff --git a/src/internal/logic/steamlogininitlogic.go b/src/internal/logic/steamlogininitlogic.go index bd03880..17e21c7 100644 --- a/src/internal/logic/steamlogininitlogic.go +++ b/src/internal/logic/steamlogininitlogic.go @@ -2,11 +2,15 @@ package logic import ( "context" + "fmt" + "net/http" + "time" "src/internal/svc" "src/internal/types" "src/internal/utils/steamauth" + "github.com/google/uuid" "github.com/zeromicro/go-zero/core/logx" ) @@ -16,6 +20,13 @@ type SteamLoginInitLogic struct { svcCtx *svc.ServiceContext } +const ( + // Redis key prefix for storing nonces + nonceKeyPrefix = "steam:nonce:" + // Nonce expiration time (5 minutes) + nonceExpiration = 5 * time.Minute +) + // Initiate Steam login func NewSteamLoginInitLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SteamLoginInitLogic { return &SteamLoginInitLogic{ @@ -25,16 +36,28 @@ func NewSteamLoginInitLogic(ctx context.Context, svcCtx *svc.ServiceContext) *St } } -func (l *SteamLoginInitLogic) SteamLoginInit(req *types.SteamLoginInitReq) (resp *types.SteamLoginInitResp, err error) { +func (l *SteamLoginInitLogic) SteamLoginInit(req *types.SteamLoginInitReq, w http.ResponseWriter, r *http.Request) error { + // Generate a unique nonce (UUID) for this login attempt + nonce := uuid.New().String() + + // Store the nonce in Redis with expiration + nonceKey := nonceKeyPrefix + nonce + err := l.svcCtx.Redis.Setex(nonceKey, "1", int(nonceExpiration.Seconds())) + if err != nil { + l.Logger.Errorf("Failed to store nonce in Redis: %v", err) + return fmt.Errorf("failed to initialize login session") + } + // Get the callback URL from config callbackURL := l.svcCtx.Config.Steam.CallbackURL // Build the Steam OpenID redirect URL redirectURL := steamauth.GetRedirectURL(callbackURL) - l.Logger.Infof("Initiating Steam login with callback URL: %s", callbackURL) + l.Logger.Infof("Initiating Steam login with nonce: %s, callback URL: %s", nonce, callbackURL) - return &types.SteamLoginInitResp{ - RedirectUrl: redirectURL, - }, nil + // Redirect user directly to Steam + http.Redirect(w, r, redirectURL, http.StatusFound) + + return nil } diff --git a/src/internal/svc/servicecontext.go b/src/internal/svc/servicecontext.go index 05b2085..2e9e8f0 100644 --- a/src/internal/svc/servicecontext.go +++ b/src/internal/svc/servicecontext.go @@ -2,14 +2,18 @@ package svc import ( "src/internal/config" + + "github.com/zeromicro/go-zero/core/stores/redis" ) type ServiceContext struct { Config config.Config + Redis *redis.Redis } func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ Config: c, + Redis: redis.MustNewRedis(c.Redis), } } diff --git a/src/internal/types/types.go b/src/internal/types/types.go index f8a4519..3ad1530 100644 --- a/src/internal/types/types.go +++ b/src/internal/types/types.go @@ -31,7 +31,3 @@ type SteamLoginCallbackResp struct { type SteamLoginInitReq struct { } - -type SteamLoginInitResp struct { - RedirectUrl string `json:"redirectUrl"` -}