Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/domain/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type OAuthConfig struct {
ClientID string
ClientSecret string
RedirectURI string
Scope string
Scopes []string
AuthorizeURL string
TokenURL string
UserInfoURL string
Expand Down
4 changes: 4 additions & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/rokku-c/go-openai v1.35.7-fix2
github.com/spf13/viper v1.20.1
golang.org/x/crypto v0.39.0
golang.org/x/oauth2 v0.18.0
golang.org/x/text v0.26.0
)

Expand All @@ -33,6 +34,7 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.27.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
Expand Down Expand Up @@ -66,5 +68,7 @@ require (
golang.org/x/sys v0.33.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
15 changes: 15 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
Expand Down Expand Up @@ -193,6 +198,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -221,6 +228,7 @@ golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
Expand All @@ -238,6 +246,13 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
10 changes: 5 additions & 5 deletions backend/internal/user/usecase/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"log/slog"
"net/url"
"strings"
"time"

"github.com/google/uuid"
Expand Down Expand Up @@ -390,7 +389,7 @@ func (u *UserUsecase) OAuthSignUpOrIn(ctx context.Context, req *domain.OAuthSign
cfg.ClientID = setting.CustomOauth.ClientID
cfg.ClientSecret = setting.CustomOauth.ClientSecret
cfg.AuthorizeURL = setting.CustomOauth.AuthorizeURL
cfg.Scope = strings.Join(setting.CustomOauth.Scopes, " ")
cfg.Scopes = setting.CustomOauth.Scopes
cfg.TokenURL = setting.CustomOauth.AccessTokenURL
cfg.UserInfoURL = setting.CustomOauth.UserInfoURL
cfg.IDField = setting.CustomOauth.IDField
Expand Down Expand Up @@ -457,8 +456,9 @@ func (u *UserUsecase) FetchUserInfo(ctx context.Context, req *domain.OAuthCallba
return nil, err
}
cfg := domain.OAuthConfig{
Debug: u.cfg.Debug,
Platform: session.Platform,
Debug: u.cfg.Debug,
Platform: session.Platform,
RedirectURI: fmt.Sprintf("%s/api/v1/user/oauth/callback", u.cfg.BaseUrl),
}

switch session.Platform {
Expand All @@ -475,7 +475,7 @@ func (u *UserUsecase) FetchUserInfo(ctx context.Context, req *domain.OAuthCallba
cfg.ClientID = setting.CustomOauth.ClientID
cfg.ClientSecret = setting.CustomOauth.ClientSecret
cfg.AuthorizeURL = setting.CustomOauth.AuthorizeURL
cfg.Scope = strings.Join(setting.CustomOauth.Scopes, " ")
cfg.Scopes = setting.CustomOauth.Scopes
cfg.TokenURL = setting.CustomOauth.AccessTokenURL
cfg.UserInfoURL = setting.CustomOauth.UserInfoURL
cfg.IDField = setting.CustomOauth.IDField
Expand Down
79 changes: 33 additions & 46 deletions backend/pkg/oauth/custom.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
package oauth

import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
"io"

"github.com/google/uuid"
"golang.org/x/oauth2"

"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/pkg/request"
)

type CustomOAuth struct {
cfg domain.OAuthConfig
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
Expand All @@ -27,17 +38,13 @@ func NewCustomOAuth(config domain.OAuthConfig) domain.OAuther {
// GetAuthorizeURL implements domain.OAuther.
func (c *CustomOAuth) GetAuthorizeURL() (string, string) {
state := uuid.NewString()
url := fmt.Sprintf("%s?response_type=code&client_id=%s&state=%s&redirect_uri=%s", c.cfg.AuthorizeURL, c.cfg.ClientID, state, c.cfg.RedirectURI)
url := c.oauth.AuthCodeURL(state)
return state, url
}

// GetUserInfo implements domain.OAuther.
func (c *CustomOAuth) GetUserInfo(code string) (*domain.OAuthUserInfo, error) {
accessToken, err := c.getAccessToken(code)
if err != nil {
return nil, err
}
info, err := c.getUserInfo(accessToken)
info, err := c.getUserInfo(code)
if err != nil {
return nil, err
}
Expand All @@ -48,49 +55,29 @@ func (c *CustomOAuth) GetUserInfo(code string) (*domain.OAuthUserInfo, error) {
}, nil
}

func (c *CustomOAuth) getAccessToken(code string) (string, error) {
u, err := url.Parse(c.cfg.TokenURL)
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 "", fmt.Errorf("[CustomOAuth] 无效的Token URL: %w", err)
}
client := request.NewClient(u.Scheme, u.Host, 30*time.Second)
client.SetDebug(c.cfg.Debug)
req := domain.GetAccessTokenReq{
GrantType: "authorization_code",
Code: code,
RedirectURL: c.cfg.RedirectURI,
ClientID: c.cfg.ClientID,
ClientSecret: c.cfg.ClientSecret,
return nil, err
}
resp, err := request.Post[domain.OAuthAccessToken](client, u.Path, req, request.WithHeader(request.Header{
"Accept": "application/json",
}))
client := c.oauth.Client(context.Background(), token)
res, err := client.Get(c.cfg.UserInfoURL)
if err != nil {
return "", fmt.Errorf("[CustomOAuth] 获取access token失败: %w", err)
return nil, err
}
return resp.AccessToken, nil
}

type UserInfo map[string]any
defer res.Body.Close()

func (c *CustomOAuth) getUserInfo(accessToken string) (UserInfo, error) {
u, err := url.Parse(c.cfg.UserInfoURL)
buf, err := io.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("[CustomOAuth] 无效的UseInfo URL: %w", err)
}
client := request.NewClient(u.Scheme, u.Host, 30*time.Second)
client.SetDebug(c.cfg.Debug)
h := request.Header{
"Authorization": fmt.Sprintf("Bearer %s", accessToken),
}
if strings.Contains(c.cfg.UserInfoURL, "github") {
h["Accept"] = "application/vnd.github.v3+json"
return nil, err
}

resp, err := request.Get[UserInfo](client, u.Path, request.WithHeader(h))
var userInfo UserInfo
err = json.Unmarshal(buf, &userInfo)
if err != nil {
return nil, fmt.Errorf("[CustomOAuth] 获取用户信息失败: %w", err)
return nil, err
}

return *resp, nil
return userInfo, nil
}
Loading