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" "net/http" "uauth/tool" ) //go:embed login.html var page string var ( config = oauth2.Config{ ClientID: "test", ClientSecret: "Foobar123", 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 { app := nf.New() app.Get("/login", handleLoginPage) app.Post("/login", handleLoginAction) app.Get("/oauth/v2/redirect", handleRedirect) go func() { <-ctx.Done() _ = app.Shutdown(tool.Timeout(2)) }() return app.Run(":18080") } func handleLoginAction(c *nf.Ctx) error { type Req struct { Username string `form:"username"` Password string `form:"password"` } var ( err error req = new(Req) token *oauth2.Token ) if err = c.BodyParser(req); err != nil { return c.Status(http.StatusBadRequest).SendString(err.Error()) } log.Info("[C] password mode: username = %s, password = %s", req.Username, req.Password) if token, err = config.PasswordCredentialsToken(c.Context(), req.Username, req.Password); err != nil { log.Error("[C] config do password token err = %s", err) return c.Status(http.StatusBadRequest).SendString(err.Error()) } bs, _ := json.Marshal(token) log.Info("[C] oauth finally token =\n%s", string(bs)) return resp.Resp200(c, token) } func handleLoginPage(c *nf.Ctx) error { if c.Query("oauth") != "" { uri := config.AuthCodeURL(state, oauth2.ApprovalForce) log.Info("[C] oauth config client_secret = %s", config.ClientSecret) log.Info("[C] redirect to oauth2 server uri = %s", uri) return c.Redirect(uri, http.StatusFound) } return c.HTML(page) } func handleRedirect(c *nf.Ctx) error { type Req struct { State string `query:"state"` Code string `query:"code"` Scope string `query:"scope"` ClientId string `query:"client_id"` } 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 { log.Error("[C] state mismatch, want = %s, got = %s", state, req.State) return c.Status(http.StatusBadRequest).SendString("Bad Request: state mismatch") } 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) }