Skip to content

Commit

Permalink
支持google oauth登录
Browse files Browse the repository at this point in the history
- 增加google账号登录渠道
- auth配置增加state字段
  • Loading branch information
jorben committed Jul 3, 2024
1 parent 229452d commit 8277761
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 10 deletions.
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type OAuthProvider struct {
ClientId string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
CallbackUri string `yaml:"callback_uri"`
State string `yaml:"-"`
}

// DbConfig 数据库连接配置
Expand All @@ -26,6 +27,7 @@ type DbConfig struct {
type LeagueConfig struct {
Db DbConfig `yaml:"db"`
Auth struct {
State string `json:"state"`
Provider []OAuthProvider `yaml:"provider"`
} `yaml:"auth"`
Log []log.OutputConfig `yaml:"log"`
Expand Down Expand Up @@ -53,6 +55,9 @@ func GetConfig() *LeagueConfig {
func GetAuthProviderConfig(provider string) OAuthProvider {
for _, authConfig := range leagueConfig.Auth.Provider {
if authConfig.Source == provider {
if len(authConfig.State) == 0 {
authConfig.State = leagueConfig.Auth.State
}
return authConfig
}
}
Expand Down
1 change: 1 addition & 0 deletions config/config_demo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ db:
check_interval: 3 # Ping检测时间间隔,单位:分钟

auth:
state: 1729926124 # 随机state
provider:
- source: github
client_id: Ov23csdx3vwmihIIN
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
)

require (
cloud.google.com/go/compute/metadata v0.3.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/bytedance/sonic v1.11.9 // indirect
Expand Down Expand Up @@ -55,6 +56,7 @@ require (
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
Expand Down Expand Up @@ -78,6 +80,7 @@ github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
Expand Down Expand Up @@ -200,6 +203,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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
8 changes: 4 additions & 4 deletions provider/auth/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ type GithubData struct {
Nickname string `json:"name"`
Email string `json:"email"`
Bio string `json:"bio"`
Status string `json:"status"`
Message string `json:"message"`
}

type GithubOAuth struct {
Expand Down Expand Up @@ -58,7 +56,7 @@ func (g *GithubOAuth) GetUserinfo(ctx *gin.Context) (*model.UserSocialInfo, erro

githubData, err := getGithubData(ctx, token)
if err != nil {
return nil, errors.New("无法获取用户信息,请确认access token是否有效")
return nil, errors.New("获取用户信息失败,请稍后重试")
}

log.Debugf(ctx, "Github data: %s", githubData)
Expand All @@ -72,7 +70,7 @@ func (g *GithubOAuth) GetUserinfo(ctx *gin.Context) (*model.UserSocialInfo, erro
// 缺少必要数据
if data.Id == 0 {
log.Errorf(ctx, "Get github userinfo failed, data: %s", githubData)
return nil, errors.New(fmt.Sprintf("缺失必要用户数据,%s", data.Message))
return nil, errors.New("获取用户数据失败,请确认access token是否有效")
}

return &model.UserSocialInfo{
Expand All @@ -96,6 +94,7 @@ func getGithubData(ctx *gin.Context, accessToken string) (string, error) {
)
if err != nil {
log.Errorf(ctx, "API Request creation failed, err: %s", err.Error())
return "", err
}

// Set the Authorization header before sending the request
Expand All @@ -107,6 +106,7 @@ func getGithubData(ctx *gin.Context, accessToken string) (string, error) {
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Errorf(ctx, "Request failed, err: %s", err.Error())
return "", err
}

// Read the response as a byte slice
Expand Down
106 changes: 101 additions & 5 deletions provider/auth/google.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,124 @@
package auth

import (
"encoding/json"
"errors"
"github.com/gin-gonic/gin"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"io"
"league/config"
"league/log"
"league/model"
"net/http"
)

// ProviderGoogle 渠道名称
const ProviderGoogle = "google"

type GoogleData struct {
Id string `json:"id"`
Avatar string `json:"picture"`
Nickname string `json:"name"`
Email string `json:"email"`
}

type GoogleOAuth struct {
cfg config.OAuthProvider
cfg config.OAuthProvider
googleOAuth2Config *oauth2.Config
}

// NewGoogleOAuth 新建Github oAuth实例
func NewGoogleOAuth(c config.OAuthProvider) *GoogleOAuth {
return &GoogleOAuth{cfg: c}
return &GoogleOAuth{
cfg: c,
googleOAuth2Config: &oauth2.Config{
RedirectURL: c.CallbackUri,
ClientID: c.ClientId,
ClientSecret: c.ClientSecret,
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
},
Endpoint: google.Endpoint,
},
}
}

func (g *GoogleOAuth) GetLoginUrl(ctx *gin.Context) (string, error) {
// Create the dynamic redirect URL for login
return "", nil
return g.googleOAuth2Config.AuthCodeURL(g.cfg.State), nil
}

func (g *GoogleOAuth) GetUserinfo(ctx *gin.Context) (*model.UserSocialInfo, error) {
return nil, nil
// 校验state
state := ctx.Query("state")
if len(state) == 0 || state != g.cfg.State {
return nil, errors.New("state参数不正确")
}
code := ctx.Query("code")
if len(code) == 0 {
return nil, errors.New("缺少必要参数:code")
}
// 获取access token
token, err := g.googleOAuth2Config.Exchange(ctx, code)
if err != nil {
log.Errorf(ctx, "Code exchange failed, err: %s", err.Error())
return nil, err
}

// 获取用户信息
googleData, err := getGoogleData(ctx, token.AccessToken)
if err != nil {
return nil, errors.New("获取用户信息失败,请稍后重试")
}

log.Debugf(ctx, "Google data: %s", googleData)
data := &GoogleData{}
err = json.Unmarshal([]byte(googleData), data)
if err != nil {
log.Errorf(ctx, "Unmarshal google data failed, data: %s, err: %s", googleData, err.Error())
return nil, errors.New("解析用户数据失败")
}

// 缺少必要数据
if len(data.Id) == 0 {
log.Errorf(ctx, "Get google userinfo failed, data: %s", googleData)
return nil, errors.New("获取用户数据失败,请确认access token是否有效")
}

return &model.UserSocialInfo{
Source: ProviderGoogle,
OpenId: data.Id,
Email: data.Email,
Avatar: data.Avatar,
Username: data.Email,
Nickname: data.Nickname,
Bio: "",
}, nil
}

func getGoogleData(ctx *gin.Context, accessToken string) (string, error) {
// Get request to a set URL
req, err := http.NewRequest(
"GET",
"https://www.googleapis.com/oauth2/v2/userinfo?access_token="+accessToken,
nil,
)
if err != nil {
log.Errorf(ctx, "API Request creation failed, err: %s", err.Error())
return "", err
}

// Make the request
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Errorf(ctx, "Request failed, err: %s", err.Error())
return "", err
}

// Read the response as a byte slice
respbody, _ := io.ReadAll(resp.Body)

// Convert byte slice to string and return
return string(respbody), nil
}
3 changes: 2 additions & 1 deletion router/api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ func AuthLogin(ctx *gin.Context) {
c.CJSON(errs.ErrAuthLoginUrl)
return
}
ctx.Redirect(http.StatusFound, url)
log.Debugf(ctx, "Login url: %s", url)
ctx.Redirect(http.StatusTemporaryRedirect, url)
}

// AuthCallback 登录回调接口
Expand Down

0 comments on commit 8277761

Please sign in to comment.