添加gitea第三方登录包含官方及我自部署

This commit is contained in:
junleea 2025-05-17 15:14:15 +08:00
parent 6bc3e3ea2f
commit 9dda8527a7
5 changed files with 130 additions and 0 deletions

View File

@ -838,6 +838,14 @@ func GetThirdPartyAuthUrl(c *gin.Context) {
//params.Add("scope", "")
params.Add("state", stateBase64Str)
respUrl = fmt.Sprintf("%s?%s", proto.StackOverflowAuthorizeBaseUrl, params.Encode())
case "my_gitea":
params := url.Values{}
params.Add("client_id", worker.MyGiteaClientID)
params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback")
params.Add("response_type", "code") //返回code
params.Add("state", stateID)
params.Add("scope", "user")
respUrl = fmt.Sprintf("%s?%s", proto.MyGiteaAuthorizeBaseUrl, params.Encode())
default:
log.Println("platform not support:", platform)
}

View File

@ -195,4 +195,5 @@ const (
GoogleAuthorizeBaseUrl = "https://accounts.google.com/o/oauth2/v2/auth"
FacebookAuthorizeBaseUrl = "https://www.facebook.com/v22.0/dialog/oauth"
StackOverflowAuthorizeBaseUrl = "https://stackoverflow.com/oauth"
MyGiteaAuthorizeBaseUrl = "https://gogs.ljsea.top/login/oauth/authorize"
)

View File

@ -318,3 +318,27 @@ type QQUserInfoResponse struct {
Level string `json:"level"`
IsYellowYearVip string `json:"is_yellow_year_vip"`
}
/**************************gitea***********************/
type GiteaOAuthResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
}
type GiteaOAuthRequest struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Code string `json:"code"`
RedirectURI string `json:"redirect_uri"`
Scope string `json:"scope"`
}
type GiteaUserInfo struct {
Sub string `json:"sub"`
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
Email string `json:"email"`
Picture string `json:"picture"`
Groups interface{} `json:"groups"`
}

View File

@ -489,6 +489,8 @@ func DoThirdPartyCallBack(state *proto.ThirdPartyLoginState, code string) {
DoFaceBookCallBack(state, code)
case "stackoverflow":
DoStackoverflowCallBack(state, code)
case "my_gitea", "gitea":
DoGiteeCallBack(state, code)
default:
log.Println("DoThirdPartyCallBack platform error:", state.Platform)
}
@ -659,3 +661,46 @@ func DoRequestToForeignServer(req *proto.OnlineServerReq) (proto.OutlineServerRe
return resp, nil
}
func DoGiteaCallBack(state *proto.ThirdPartyLoginState, code string) {
var thirdPartyLoginStatus proto.ThirdPartyLoginStatus
thirdPartyLoginStatus.Type = state.Platform
//根据code获取Access Token
var baseDomain string
var clientID string
var clientSecret string
if state.Platform == "my_gitea" {
baseDomain = "https://gogs.ljsea.top"
clientID, clientSecret = worker.MyGiteaClientID, worker.MyGiteaClientSecret
} else {
baseDomain = "https://gitea.com"
clientID, clientSecret = worker.GiteaClientID, worker.GiteaClientSecret
}
tokenResp, _ := worker.GetGiteaAccessTokenByCode(baseDomain, code, "https://pm.ljsea.top/tool/third_party_callback", clientID, clientSecret)
//if err != nil {
// log.Printf("get %s access token error:%v\n", state.Platform, err)
// thirdPartyLoginStatus.Status = proto.ParameterError
// return
//}
if tokenResp.AccessToken == "" {
log.Printf("get %s access token is empty\n", state.Platform)
thirdPartyLoginStatus.Status = proto.ParameterError
} else {
log.Printf("get %s access token:%v\n", state.Platform, tokenResp.AccessToken)
//获取用户信息
userInfoResp, err2 := worker.GetGiteaUserInfo(baseDomain, tokenResp.AccessToken)
if err2 != nil {
log.Printf("get %s user info error:%v\n", state.Platform, err2)
thirdPartyLoginStatus.Status = proto.ParameterError
} else {
log.Printf("get %s user info:%v\n", state.Platform, userInfoResp)
thirdPartyUserInfo := proto.ThirdPartyUserInfo{UserID: userInfoResp.Sub, Name: userInfoResp.Name, Avatar: userInfoResp.Picture, Email: userInfoResp.Email}
HandleThirdPartyLoginStatusV2(state, &thirdPartyLoginStatus, &thirdPartyUserInfo)
thirdPartyLoginStatus.Status = proto.SuccessCode
}
}
//更新redis中的第三方登录状态
thirdPartyLoginStatusStr, _ := json.Marshal(thirdPartyLoginStatus)
log.Printf("do handle %s callback success, third party login status: %v\n", state.Platform, thirdPartyLoginStatus)
worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10)
}

View File

@ -513,3 +513,55 @@ func GetQQUserInfo(accessToken string) (proto.QQUserInfoResponse, error) {
return resp, nil
}
// 我的自部署gitea
const (
MyGiteaClientID = "812f4f39-8b98-426e-a542-3115ff4fb2be"
MyGiteaClientSecret = "gto_uw3p6sy3cutbmfmndgtajschm6vqaxasyaxmjfzsrsgjx32wawwq"
//官方版本
GiteaClientID = "035b79b8-ba9a-4c4b-bb41-ede796d168c8"
GiteaClientSecret = "gto_djia2zwamyvj6pashr24ifhj2nor52i5kphgice5rfwon2vqjpma"
)
// 由于gitea有自部署与官方区别
func GetGiteaAccessTokenByCode(baseUrl, code string, redirectURI string, clientID string, clientSecret string) (proto.GiteaOAuthResponse, error) {
var resp proto.GiteaOAuthResponse
url := baseUrl + "/login/oauth/access_token"
req := proto.GiteaOAuthRequest{
ClientID: clientID,
ClientSecret: clientSecret,
Code: code,
RedirectURI: redirectURI,
Scope: "user",
}
reqData, err := json.Marshal(req)
err2, respBytes := DoPostRequestJSON(url, reqData, nil)
if err2 != nil {
return resp, err2
}
err = json.Unmarshal(respBytes, &resp)
if err != nil {
return resp, err
}
return resp, nil
}
func GetGiteaUserInfo(baseDomain, accessToken string) (proto.GiteaUserInfo, error) {
url := baseDomain + "/login/oauth/userinfo"
headers := map[string]string{
"Authorization": "bearer " + accessToken,
}
var resp proto.GiteaUserInfo
err2, respBytes := DoGetRequest(url, headers)
if err2 != nil {
return resp, err2
}
err := json.Unmarshal(respBytes, &resp)
if err != nil {
return resp, err
}
return resp, nil
}