From c696872b8a346130155f1a4f35080a431903bee2 Mon Sep 17 00:00:00 2001 From: loveuer Date: Mon, 28 Oct 2024 22:37:22 +0800 Subject: [PATCH] =?UTF-8?q?wip:=20=E7=BB=A7=E7=BB=AD,=20client,=20svc=20?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E8=BF=9B=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/client/client.go | 89 ++++++++++++++++++++++------- internal/client/login.html | 2 +- internal/cmd/client.go | 16 ++++++ internal/cmd/cmd.go | 1 + internal/cmd/serve.go | 2 +- internal/serve/handler/authorize.go | 5 +- 6 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 internal/cmd/client.go diff --git a/internal/client/client.go b/internal/client/client.go index aadc5a0..fc6df78 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -2,33 +2,82 @@ package client import ( "context" + _ "embed" + "encoding/json" "github.com/google/uuid" + "github.com/loveuer/nf" + "github.com/loveuer/nf/nft/log" + "github.com/loveuer/nf/nft/resp" "golang.org/x/oauth2" - "golang.org/x/oauth2/authhandler" + "net/http" + "uauth/internal/tool" ) +//go:embed login.html +var page string + var ( - State = uuid.New().String()[:8] + config = oauth2.Config{ + ClientID: "test", + ClientSecret: "test", + Endpoint: oauth2.Endpoint{ + AuthURL: "http://localhost:8080/oauth/v2/authorize", + TokenURL: "http://localhost:8080/oauth/v2/token", + }, + RedirectURL: "http://localhost:18080/oauth/v2/redirect", + Scopes: []string{"test"}, + } + state = uuid.New().String()[:8] ) func Run(ctx context.Context) error { - oauth2.NewClient(ctx, authhandler.TokenSource( - ctx, - &oauth2.Config{ - ClientID: "", - ClientSecret: "", - Endpoint: oauth2.Endpoint{ - AuthURL: "", - DeviceAuthURL: "", - TokenURL: "", - AuthStyle: 0, - }, - RedirectURL: "", - Scopes: nil, - }, - State, - func(authCodeURL string) (code string, state string, err error) { + app := nf.New() + app.Get("/login", handleLogin) + app.Get("/oauth/v2/redirect", handleRedirect) - }, - )) + go func() { + <-ctx.Done() + _ = app.Shutdown(tool.Timeout(2)) + }() + + return app.Run(":18080") +} + +func handleLogin(c *nf.Ctx) error { + if c.Query("oauth") != "" { + return c.Redirect(config.AuthCodeURL(state), http.StatusFound) + } + + return c.HTML(page) +} + +func handleRedirect(c *nf.Ctx) error { + type Req struct { + State string `query:"state"` + Code string `query:"code"` + } + + var ( + err error + req = new(Req) + token *oauth2.Token + ) + + if err = c.QueryParser(req); err != nil { + return resp.Resp400(c, err.Error()) + } + + if req.State != state { + return resp.Resp400(c, "invalid state") + } + + if token, err = config.Exchange(c.Context(), req.Code); err != nil { + log.Error("[C] oauth config exchange err: %s", err.Error()) + return resp.Resp500(c, err.Error()) + } + + bs, _ := json.Marshal(token) + log.Info("[C] oauth finally token =\n%s", string(bs)) + + return resp.Resp200(c, token) } diff --git a/internal/client/login.html b/internal/client/login.html index 0dc46b3..bb57e1d 100644 --- a/internal/client/login.html +++ b/internal/client/login.html @@ -45,7 +45,7 @@ type="submit" value="登录" /> - 使用 Pro 账号登录 + 使用 OAuth V2 账号登录 diff --git a/internal/cmd/client.go b/internal/cmd/client.go new file mode 100644 index 0000000..b21aeb3 --- /dev/null +++ b/internal/cmd/client.go @@ -0,0 +1,16 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "uauth/internal/client" +) + +func initClient() *cobra.Command { + return &cobra.Command{ + Use: "client", + Short: "Run the client", + RunE: func(cmd *cobra.Command, args []string) error { + return client.Run(cmd.Context()) + }, + } +} diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 9314c39..ad0a28a 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -26,5 +26,6 @@ func init() { Command.AddCommand( initServe(), + initClient(), ) } diff --git a/internal/cmd/serve.go b/internal/cmd/serve.go index 98bff22..7a5641a 100644 --- a/internal/cmd/serve.go +++ b/internal/cmd/serve.go @@ -23,7 +23,7 @@ func initServe() *cobra.Command { } svc.Flags().StringVar(&opt.Cfg.Svc.Address, "address", "localhost:8080", "listen address") - svc.Flags().StringVar(&opt.Cfg.Svc.Prefix, "prefix", "/api/oauth/v2", "api prefix") + svc.Flags().StringVar(&opt.Cfg.Svc.Prefix, "prefix", "/oauth/v2", "api prefix") svc.Flags().StringVar(&opt.Cfg.Svc.Cache, "cache", "lru::", "cache uri") svc.Flags().StringVar(&opt.Cfg.Svc.DB, "db", "sqlite::data.sqlite", "database uri") diff --git a/internal/serve/handler/authorize.go b/internal/serve/handler/authorize.go index f565167..3af0002 100644 --- a/internal/serve/handler/authorize.go +++ b/internal/serve/handler/authorize.go @@ -5,6 +5,7 @@ import ( "errors" "github.com/google/uuid" "github.com/loveuer/nf" + "github.com/loveuer/nf/nft/log" "github.com/loveuer/nf/nft/resp" "gorm.io/gorm" "net/http" @@ -27,6 +28,7 @@ func Authorize(c *nf.Ctx) error { ResponseType string `query:"response_type"` RedirectURI string `query:"redirect_uri"` Scope string `query:"scope"` + State string `query:"state"` } var ( @@ -39,7 +41,8 @@ func Authorize(c *nf.Ctx) error { ) if err = c.QueryParser(req); err != nil { - return resp.Resp400(c, err) + log.Error("[S] query parser err = %s", err.Error()) + return c.Status(http.StatusBadRequest).SendString("Invalid request") } if req.ResponseType != "code" {