package server import ( "code.smartsheep.studio/hydrogen/interactive/pkg/services" "context" "encoding/json" "fmt" "github.com/gofiber/fiber/v2" "github.com/google/uuid" "github.com/spf13/viper" "golang.org/x/oauth2" ) var cfg oauth2.Config func buildOauth2Config() { cfg = oauth2.Config{ RedirectURL: fmt.Sprintf("https://%s/auth/callback", viper.GetString("domain")), ClientID: viper.GetString("passport.client_id"), ClientSecret: viper.GetString("passport.client_secret"), Scopes: []string{"openid"}, Endpoint: oauth2.Endpoint{ AuthURL: fmt.Sprintf("%s/auth/o/connect", viper.GetString("passport.endpoint")), TokenURL: fmt.Sprintf("%s/api/auth/token", viper.GetString("passport.endpoint")), AuthStyle: oauth2.AuthStyleInParams, }, } } func doLogin(c *fiber.Ctx) error { buildOauth2Config() url := cfg.AuthCodeURL(uuid.NewString()) return c.JSON(fiber.Map{ "target": url, }) } func doPostLogin(c *fiber.Ctx) error { buildOauth2Config() code := c.Query("code") token, err := cfg.Exchange(context.Background(), code) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("failed to exchange token: %q", err)) } agent := fiber. Get(fmt.Sprintf("%s/api/users/me", viper.GetString("passport.endpoint"))). Set(fiber.HeaderAuthorization, fmt.Sprintf("Bearer %s", token.AccessToken)) _, body, errs := agent.Bytes() if len(errs) > 0 { return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("failed to get userinfo: %q", errs)) } var userinfo services.PassportUserinfo err = json.Unmarshal(body, &userinfo) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("failed to parse userinfo: %q", err)) } account, err := services.LinkAccount(userinfo) access, refresh, err := services.GetToken(account) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("failed to get token: %q", err)) } return c.JSON(fiber.Map{ "access_token": access, "refresh_token": refresh, }) } func doRefreshToken(c *fiber.Ctx) error { var data struct { RefreshToken string `json:"refresh_token" validate:"required"` } if err := BindAndValidate(c, &data); err != nil { return err } access, refresh, err := services.RefreshToken(data.RefreshToken) if err != nil { return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("failed to get token: %q", err)) } return c.JSON(fiber.Map{ "access_token": access, "refresh_token": refresh, }) }