package oauth import ( "context" "encoding/json" "fmt" "io" "github.com/google/uuid" "golang.org/x/oauth2" "github.com/chaitin/MonkeyCode/backend/domain" ) type CustomOAuth struct { cfg domain.OAuthConfig oauth *oauth2.Config } func NewCustomOAuth(config domain.OAuthConfig) domain.OAuther { c := &CustomOAuth{ cfg: config, oauth: &oauth2.Config{ ClientID: config.ClientID, ClientSecret: config.ClientSecret, Endpoint: oauth2.Endpoint{ AuthURL: config.AuthorizeURL, TokenURL: config.TokenURL, }, RedirectURL: config.RedirectURI, Scopes: config.Scopes, }, } return c } // GetAuthorizeURL implements domain.OAuther. func (c *CustomOAuth) GetAuthorizeURL() (string, string) { state := uuid.NewString() url := c.oauth.AuthCodeURL(state) return state, url } // GetUserInfo implements domain.OAuther. func (c *CustomOAuth) GetUserInfo(code string) (*domain.OAuthUserInfo, error) { info, err := c.getUserInfo(code) if err != nil { return nil, err } return &domain.OAuthUserInfo{ ID: fmt.Sprint(info[c.cfg.IDField]), AvatarURL: fmt.Sprint(info[c.cfg.AvatarField]), Name: fmt.Sprint(info[c.cfg.NameField]), Email: fmt.Sprint(info[c.cfg.EmailField]), }, nil } type UserInfo map[string]any func (c *CustomOAuth) getUserInfo(code string) (UserInfo, error) { token, err := c.oauth.Exchange(context.Background(), code) if err != nil { return nil, err } client := c.oauth.Client(context.Background(), token) res, err := client.Get(c.cfg.UserInfoURL) if err != nil { return nil, err } defer res.Body.Close() buf, err := io.ReadAll(res.Body) if err != nil { return nil, err } var userInfo UserInfo err = json.Unmarshal(buf, &userInfo) if err != nil { return nil, err } return userInfo, nil }