94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
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 postLogin(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,
|
|
})
|
|
}
|