Skip to content

Commit

Permalink
add login
Browse files Browse the repository at this point in the history
  • Loading branch information
shadow88sky committed May 16, 2023
1 parent 7d38319 commit 703671e
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 79 deletions.
87 changes: 10 additions & 77 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,20 @@
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"

"github.com/KNN3-Network/oauth-server/module"
"github.com/KNN3-Network/oauth-server/utils"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"go.uber.org/zap"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
)

var logger = utils.Logger

var (
githubOauthConfig *oauth2.Config
)

var stackoverflow = new(module.Stackoverflow)

func init() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
githubOauthConfig = &oauth2.Config{
ClientID: os.Getenv("CLIENT_ID"),
ClientSecret: os.Getenv("CLIENT_SECRET"),
RedirectURL: os.Getenv("REDIRECT_URL"),
Scopes: []string{"read:user", "user:email"}, // 请求用户信息和邮箱权限
Endpoint: github.Endpoint,
}
}

func main() {
r := gin.Default()
r.Use(cors.Default())
Expand Down Expand Up @@ -68,15 +44,7 @@ func main() {
return
}
if platformType == "github" {
// 使用OAuth配置对象中定义的Exchange方法,通过code获取access token
token, err := githubOauthConfig.Exchange(c, code)
if err != nil {
logger.Error("failed to exchange token:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取token错误"))
return
}
client := githubOauthConfig.Client(c, token)
userInfo, err := getUserInfo(client)
userInfo, err := module.RequestGithubUserInfo(c, code)
if err != nil {
logger.Error("failed to get user info:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取github用户信息错误"))
Expand Down Expand Up @@ -114,13 +82,13 @@ func main() {

c.JSON(http.StatusOK, gin.H{"data": "success"})
} else if platformType == "discord" {
token, err := utils.ExchangeCodeForToken(code)
token, err := module.ExchangeCodeForToken(code)
if err != nil {
logger.Error("failed to exchange discord token:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取token错误"))
return
}
user, err := utils.FetchUser(token)
user, err := module.FetchUser(token)
if err != nil {
logger.Error("failed to get discord user info:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取discord用户信息错误"))
Expand Down Expand Up @@ -153,26 +121,25 @@ func main() {
}
}
c.JSON(http.StatusOK, gin.H{"data": "success"})
}

switch platformType {
case "stackexchange":
} else if platformType == "stackexchange" {
stackoverflow.Bind(c, code, address)
default:
logger.Info("error platformType", zap.String("platformType", platformType))
}
})

// github oauth
r.GET("/oauth/github", func(c *gin.Context) {
code := c.Query("code")
source := c.Query("source")
if code == "" {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("No authorization code provided."))
return
}
logger.Info("github oauth认证", zap.String("code", code))

c.Redirect(http.StatusTemporaryRedirect, "https://topscore.social/pass/succss?type=github&code="+code)
if source == "login" { // 使用OAuth配置对象中定义的Exchange方法,通过code获取access token
module.RedirectGithubLogin(c, code)
} else {
c.Redirect(http.StatusTemporaryRedirect, "https://topscore.social/pass/succss?type=github&code="+code)
}
})

// github oauth
Expand Down Expand Up @@ -210,37 +177,3 @@ func main() {

r.Run(":8001")
}

func getUserInfo(client *http.Client) (map[string]interface{}, error) {
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
if err != nil {
return nil, fmt.Errorf("get user info request failed: %w", err)
}

resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("get user info request failed: %w", err)
}

defer resp.Body.Close()

var userInfo map[string]interface{}
if err := decodeResponse(resp, &userInfo); err != nil {
return nil, err
}

return userInfo, nil
}

// 辅助函数,用于从HTTP响应中反序列化JSON
func decodeResponse(resp *http.Response, v interface{}) error {
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

if err := json.NewDecoder(resp.Body).Decode(v); err != nil {
return fmt.Errorf("failed to decode response body: %w", err)
}

return nil
}
2 changes: 1 addition & 1 deletion utils/discord.go → module/discord.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package module

import (
"encoding/json"
Expand Down
118 changes: 118 additions & 0 deletions module/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package module

import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"

"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"go.uber.org/zap"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
)

var (
githubOauthConfig *oauth2.Config
transformer_url string
)

var respData struct {
JWT string `json:"jwt"`
}

func init() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
transformer_url = os.Getenv("TRANSFORMER_URL")
githubOauthConfig = &oauth2.Config{
ClientID: os.Getenv("CLIENT_ID"),
ClientSecret: os.Getenv("CLIENT_SECRET"),
RedirectURL: os.Getenv("REDIRECT_URL"),
Scopes: []string{"read:user", "user:email"}, // 请求用户信息和邮箱权限
Endpoint: github.Endpoint,
}
}

func RequestGithubUserInfo(c *gin.Context, code string) (map[string]interface{}, error) {
// 使用OAuth配置对象中定义的Exchange方法,通过code获取access token
token, err := githubOauthConfig.Exchange(c, code)
if err != nil {
logger.Error("failed to exchange token:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取token错误"))
return nil, err
}
client := githubOauthConfig.Client(c, token)
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
if err != nil {
return nil, fmt.Errorf("get user info request failed: %w", err)
}

resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("get user info request failed: %w", err)
}

defer resp.Body.Close()

var userInfo map[string]interface{}
if err := decodeResponse(resp, &userInfo); err != nil {
return nil, err
}

return userInfo, nil
}

func RedirectGithubLogin(c *gin.Context, code string) {
userInfo, err := RequestGithubUserInfo(c, code)
if err != nil {
logger.Error("failed to get user info:", zap.Error(err))
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("获取github用户信息错误"))
return
}
github := userInfo["login"].(string)
// 构造请求 URL
reqURL, err := url.Parse(transformer_url + "/api/users/thirdPartyLogin")
if err != nil {
// 处理 URL 解析错误
fmt.Printf("Error parsing URL: %v\n", err)
return
}
// 构建查询参数
queryParams := url.Values{}
queryParams.Add("type", "github")
queryParams.Add("id", github)
reqURL.RawQuery = queryParams.Encode()

// 发送 GET 请求
resp, err := http.Get(reqURL.String())
if err != nil {
// 处理请求错误
fmt.Printf("Error sending request: %v\n", err)
return
}
defer resp.Body.Close()

if err := json.NewDecoder(resp.Body).Decode(&respData); err != nil {
// 处理响应体解析错误
fmt.Printf("Error parsing response body: %v\n", err)
return
}
// 输出响应数据中的 JWT 字段
fmt.Printf("JWT: %s\n", respData.JWT)
// 设置 Cookie
cookie := &http.Cookie{
Name: "jwt",
Value: respData.JWT,
Path: "/",
}
http.SetCookie(c.Writer, cookie)

// 重定向到目标 URL
c.Redirect(http.StatusSeeOther, "https://trans.com")
}
2 changes: 1 addition & 1 deletion utils/gmail.go → module/gmail.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package module

import (
"fmt"
Expand Down

0 comments on commit 703671e

Please sign in to comment.