package oauth import ( "context" "git.0x7f.app/WOJ/woj-server/internal/misc/config" "git.0x7f.app/WOJ/woj-server/internal/misc/log" "git.0x7f.app/WOJ/woj-server/internal/repo/cache" "git.0x7f.app/WOJ/woj-server/internal/service/user" "git.0x7f.app/WOJ/woj-server/internal/web/jwt" "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" "github.com/samber/do" "go.uber.org/zap" "golang.org/x/oauth2" ) type Service interface { LoginHandler() gin.HandlerFunc CallbackHandler() gin.HandlerFunc IsEnabled() bool GetLoginPath() string GetCallbackPath() string HealthCheck() error } const ( basePath = "/oauth" callbackPath = basePath + "/callback" loginPath = basePath + "/login" ) func NewService(i *do.Injector) (Service, error) { srv := &service{} srv.log = do.MustInvoke[log.Service](i).GetLogger("oauth") srv.jwt = do.MustInvoke[jwt.Service](i) srv.user = do.MustInvoke[user.Service](i) srv.cache = do.MustInvoke[cache.Service](i) srv.enabled = false conf := do.MustInvoke[config.Service](i).GetConfig() if conf.WebServer.OAuth.Domain == "" { return srv, srv.err } srv.provider, srv.err = oidc.NewProvider(context.Background(), conf.WebServer.OAuth.Domain) if srv.err != nil { srv.log.Error("failed to create oauth provider", zap.Error(srv.err), zap.String("domain", conf.WebServer.OAuth.Domain)) return srv, srv.err } srv.verifier = srv.provider.Verifier(&oidc.Config{ClientID: conf.WebServer.OAuth.ClientID}) srv.conf = oauth2.Config{ ClientID: conf.WebServer.OAuth.ClientID, ClientSecret: conf.WebServer.OAuth.ClientSecret, RedirectURL: conf.WebServer.PublicBase + callbackPath, Endpoint: srv.provider.Endpoint(), Scopes: []string{oidc.ScopeOpenID, "profile", "email", "roles"}, } srv.enabled = true return srv, srv.err } type service struct { log *zap.Logger jwt jwt.Service user user.Service cache cache.Service provider *oidc.Provider conf oauth2.Config verifier *oidc.IDTokenVerifier enabled bool err error } func (s *service) IsEnabled() bool { return s.enabled && s.err == nil } func (s *service) GetLoginPath() string { return loginPath } func (s *service) GetCallbackPath() string { return callbackPath } func (s *service) HealthCheck() error { return s.err }