Skip to content

Commit ef1b773

Browse files
committed
updated
1 parent 37d578e commit ef1b773

File tree

5 files changed

+190
-0
lines changed

5 files changed

+190
-0
lines changed

config/default.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ type Config struct {
2525
GoogleClientID string `mapstructure:"GOOGLE_OAUTH_CLIENT_ID"`
2626
GoogleClientSecret string `mapstructure:"GOOGLE_OAUTH_CLIENT_SECRET"`
2727
GoogleOAuthRedirectUrl string `mapstructure:"GOOGLE_OAUTH_REDIRECT_URL"`
28+
29+
GitHubClientID string `mapstructure:"GITHUB_OAUTH_CLIENT_ID"`
30+
GitHubClientSecret string `mapstructure:"GITHUB_OAUTH_CLIENT_SECRET"`
31+
GitHubOAuthRedirectUrl string `mapstructure:"GITHUB_OAUTH_REDIRECT_URL"`
2832
}
2933

3034
func LoadConfig(path string) (config Config, err error) {

controllers/auth.controller.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,68 @@ func (ac *AuthController) GoogleOAuth(ctx *gin.Context) {
193193

194194
ctx.Redirect(http.StatusTemporaryRedirect, fmt.Sprint(config.ClientOrigin, pathUrl))
195195
}
196+
197+
func (ac *AuthController) GitHubOAuth(ctx *gin.Context) {
198+
code := ctx.Query("code")
199+
var pathUrl string = "/"
200+
201+
if ctx.Query("state") != "" {
202+
pathUrl = ctx.Query("state")
203+
}
204+
205+
if code == "" {
206+
ctx.JSON(http.StatusUnauthorized, gin.H{"status": "fail", "message": "Authorization code not provided!"})
207+
return
208+
}
209+
210+
// Use the code to get the id and access tokens
211+
tokenRes, err := utils.GetGitHubOauthToken(code)
212+
213+
if err != nil {
214+
ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
215+
}
216+
217+
user, err := utils.GetGitHubUser(tokenRes.Access_token)
218+
219+
if err != nil {
220+
ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
221+
}
222+
223+
createdAt := time.Now()
224+
resBody := &models.UpdateDBUser{
225+
Email: user.Email,
226+
Name: user.Name,
227+
Photo: user.Photo,
228+
Provider: "github",
229+
Role: "user",
230+
Verified: true,
231+
CreatedAt: createdAt,
232+
UpdatedAt: createdAt,
233+
}
234+
235+
updatedUser, err := ac.userService.UpsertUser(user.Email, resBody)
236+
if err != nil {
237+
ctx.JSON(http.StatusBadGateway, gin.H{"status": "fail", "message": err.Error()})
238+
}
239+
240+
config, _ := config.LoadConfig(".")
241+
242+
// Generate Tokens
243+
access_token, err := utils.CreateToken(config.AccessTokenExpiresIn, updatedUser.ID.Hex(), config.AccessTokenPrivateKey)
244+
if err != nil {
245+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
246+
return
247+
}
248+
249+
refresh_token, err := utils.CreateToken(config.RefreshTokenExpiresIn, updatedUser.ID.Hex(), config.RefreshTokenPrivateKey)
250+
if err != nil {
251+
ctx.JSON(http.StatusBadRequest, gin.H{"status": "fail", "message": err.Error()})
252+
return
253+
}
254+
255+
ctx.SetCookie("access_token", access_token, config.AccessTokenMaxAge*60, "/", "localhost", false, true)
256+
ctx.SetCookie("refresh_token", refresh_token, config.RefreshTokenMaxAge*60, "/", "localhost", false, true)
257+
ctx.SetCookie("logged_in", "true", config.AccessTokenMaxAge*60, "/", "localhost", false, false)
258+
259+
ctx.Redirect(http.StatusTemporaryRedirect, fmt.Sprint(config.ClientOrigin, pathUrl))
260+
}

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,10 @@ func main() {
118118
AuthRouteController.AuthRoute(router)
119119
UserRouteController.UserRoute(router, userService)
120120
SessionRouteController.SessionRoute(router)
121+
122+
server.NoRoute(func(ctx *gin.Context) {
123+
ctx.JSON(http.StatusNotFound, gin.H{"status": "error", "message": "Route Not Found"})
124+
})
125+
121126
log.Fatal(server.Run(":" + config.Port))
122127
}

routes/session.routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ func (rc *SessionRouteController) SessionRoute(rg *gin.RouterGroup) {
1717
router := rg.Group("/sessions/oauth")
1818

1919
router.GET("/google", rc.authController.GoogleOAuth)
20+
router.GET("/github", rc.authController.GitHubOAuth)
2021
}

utils/githubOAuth.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package utils
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"io/ioutil"
9+
"net/http"
10+
"net/url"
11+
"time"
12+
13+
"github.com/wpcodevo/golang-mongodb/config"
14+
)
15+
16+
type GitHubOauthToken struct {
17+
Access_token string
18+
}
19+
20+
type GitHubUserResult struct {
21+
Name string
22+
Photo string
23+
Email string
24+
}
25+
26+
func GetGitHubOauthToken(code string) (*GitHubOauthToken, error) {
27+
const rootURl = "https://github.com/login/oauth/access_token"
28+
29+
config, _ := config.LoadConfig(".")
30+
values := url.Values{}
31+
values.Add("code", code)
32+
values.Add("client_id", config.GitHubClientID)
33+
values.Add("client_secret", config.GitHubClientSecret)
34+
35+
query := values.Encode()
36+
37+
queryString := fmt.Sprintf("%s?%s", rootURl, bytes.NewBufferString(query))
38+
req, err := http.NewRequest("POST", queryString, nil)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
44+
client := http.Client{
45+
Timeout: time.Second * 30,
46+
}
47+
48+
res, err := client.Do(req)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
if res.StatusCode != http.StatusOK {
54+
return nil, errors.New("could not retrieve token")
55+
}
56+
57+
resBody, err := ioutil.ReadAll(res.Body)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
parsedQuery, err := url.ParseQuery(string(resBody))
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
tokenBody := &GitHubOauthToken{
68+
Access_token: parsedQuery["access_token"][0],
69+
}
70+
71+
return tokenBody, nil
72+
}
73+
74+
func GetGitHubUser(access_token string) (*GitHubUserResult, error) {
75+
rootUrl := "https://api.github.com/user"
76+
77+
req, err := http.NewRequest("GET", rootUrl, nil)
78+
if err != nil {
79+
return nil, err
80+
}
81+
82+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", access_token))
83+
84+
client := http.Client{
85+
Timeout: time.Second * 30,
86+
}
87+
88+
res, err := client.Do(req)
89+
if err != nil {
90+
return nil, err
91+
}
92+
93+
if res.StatusCode != http.StatusOK {
94+
return nil, errors.New("could not retrieve user")
95+
}
96+
97+
resBody, err := ioutil.ReadAll(res.Body)
98+
if err != nil {
99+
return nil, err
100+
}
101+
102+
var GitHubUserRes map[string]interface{}
103+
104+
if err := json.Unmarshal(resBody, &GitHubUserRes); err != nil {
105+
return nil, err
106+
}
107+
108+
userBody := &GitHubUserResult{
109+
Email: GitHubUserRes["email"].(string),
110+
Name: GitHubUserRes["login"].(string),
111+
Photo: GitHubUserRes["avatar_url"].(string),
112+
}
113+
114+
return userBody, nil
115+
}

0 commit comments

Comments
 (0)