Commit 3bba8b2c by Torkel Ödegaard

Github oauth login works

parent b0b77d66
Subproject commit 071ac0dc85e48be546315dde196f90f01ad7b274
Subproject commit d584076b93b4ebfb33e5a5f375feb6d6ff7f9bfc
package api
import (
"encoding/json"
"net/http"
log "github.com/alecthomas/log4go"
"github.com/gin-gonic/gin"
"github.com/golang/oauth2"
"github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/stores"
)
var (
githubOAuthConfig *oauth2.Config
githubRedirectUrl string = "http://localhost:3000/oauth2/github/callback"
githubAuthUrl string = "https://github.com/login/oauth/authorize"
githubTokenUrl string = "https://github.com/login/oauth/access_token"
)
func init() {
addRoutes(func(self *HttpServer) {
if !self.cfg.Http.GithubOAuth.Enabled {
return
}
self.router.GET("/oauth2/github", self.oauthGithub)
self.router.GET("/oauth2/github/callback", self.oauthGithubCallback)
options := &oauth2.Options{
ClientID: self.cfg.Http.GithubOAuth.ClientId,
ClientSecret: self.cfg.Http.GithubOAuth.ClientSecret,
RedirectURL: githubRedirectUrl,
Scopes: []string{"user:email"},
}
cfg, err := oauth2.NewConfig(options, githubAuthUrl, githubTokenUrl)
if err != nil {
log.Error("Failed to init github auth %v", err)
}
githubOAuthConfig = cfg
})
}
func (self *HttpServer) oauthGithub(c *gin.Context) {
url := githubOAuthConfig.AuthCodeURL("", "online", "auto")
c.Redirect(302, url)
}
type githubUserInfoDto struct {
Login string `json:"login"`
Name string `json:"name"`
Email string `json:"email"`
Company string `json:"company"`
}
func (self *HttpServer) oauthGithubCallback(c *gin.Context) {
code := c.Request.URL.Query()["code"][0]
log.Info("OAuth code: %v", code)
transport, err := githubOAuthConfig.NewTransportWithCode(code)
if err != nil {
c.String(500, "Failed to exchange oauth token: "+err.Error())
return
}
client := http.Client{Transport: transport}
resp, err := client.Get("https://api.github.com/user")
if err != nil {
c.String(500, err.Error())
return
}
var userInfo githubUserInfoDto
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&userInfo)
if err != nil {
c.String(500, err.Error())
return
}
if len(userInfo.Email) < 5 {
c.String(500, "Invalid email")
return
}
// try find existing account
account, err := self.store.GetAccountByLogin(userInfo.Email)
// create account if missing
if err == stores.ErrAccountNotFound {
account = &models.Account{
Login: userInfo.Login,
Email: userInfo.Email,
Name: userInfo.Name,
Company: userInfo.Company,
}
if err = self.store.CreateAccount(account); err != nil {
log.Error("Failed to create account %v", err)
c.String(500, "Failed to create account")
return
}
}
// login
loginUserWithAccount(account, c)
c.Redirect(302, "/")
}
......@@ -11,7 +11,14 @@ import (
"github.com/torkelo/grafana-pro/pkg/stores"
)
var oauthCfg *oauth2.Config
var (
googleOAuthConfig *oauth2.Config
googleRedirectUrl string = "http://localhost:3000/oauth2/google/callback"
googleAuthUrl string = "https://accounts.google.com/o/oauth2/auth"
googleTokenUrl string = "https://accounts.google.com/o/oauth2/token"
googleScopeProfile string = "https://www.googleapis.com/auth/userinfo.profile"
googleScopeEmail string = "https://www.googleapis.com/auth/userinfo.email"
)
func init() {
addRoutes(func(self *HttpServer) {
......@@ -19,33 +26,28 @@ func init() {
return
}
self.router.GET("/login/google", self.loginGoogle)
self.router.GET("/oauth2callback", self.oauthCallback)
self.router.GET("/oauth2/google", self.oauthGoogle)
self.router.GET("/oauth2/google/callback", self.oauthGoogleCallback)
options := &oauth2.Options{
ClientID: self.cfg.Http.GoogleOAuth.ClientId,
ClientSecret: self.cfg.Http.GoogleOAuth.ClientSecret,
RedirectURL: "http://localhost:3000/oauth2callback",
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
},
RedirectURL: googleRedirectUrl,
Scopes: []string{googleScopeEmail, googleScopeProfile},
}
cfg, err := oauth2.NewConfig(options,
"https://accounts.google.com/o/oauth2/auth",
"https://accounts.google.com/o/oauth2/token")
cfg, err := oauth2.NewConfig(options, googleAuthUrl, googleTokenUrl)
if err != nil {
log.Error("Failed to init google auth %v", err)
}
oauthCfg = cfg
googleOAuthConfig = cfg
})
}
func (self *HttpServer) loginGoogle(c *gin.Context) {
url := oauthCfg.AuthCodeURL("", "online", "auto")
func (self *HttpServer) oauthGoogle(c *gin.Context) {
url := googleOAuthConfig.AuthCodeURL("", "online", "auto")
c.Redirect(302, url)
}
......@@ -56,11 +58,11 @@ type googleUserInfoDto struct {
Name string `json:"name"`
}
func (self *HttpServer) oauthCallback(c *gin.Context) {
func (self *HttpServer) oauthGoogleCallback(c *gin.Context) {
code := c.Request.URL.Query()["code"][0]
log.Info("OAuth code: %v", code)
transport, err := oauthCfg.NewTransportWithCode(code)
transport, err := googleOAuthConfig.NewTransportWithCode(code)
if err != nil {
c.String(500, "Failed to exchange oauth token: "+err.Error())
return
......
......@@ -6,10 +6,11 @@ type Cfg struct {
type HttpCfg struct {
Port string
GoogleOAuth GoogleOAuthCfg
GoogleOAuth OAuthCfg
GithubOAuth OAuthCfg
}
type GoogleOAuthCfg struct {
type OAuthCfg struct {
Enabled bool
ClientId string
ClientSecret string
......@@ -24,11 +25,16 @@ func NewCfg(port string) *Cfg {
return &Cfg{
Http: HttpCfg{
Port: port,
GoogleOAuth: GoogleOAuthCfg{
GoogleOAuth: OAuthCfg{
Enabled: true,
ClientId: "106011922963-4pvl05e9urtrm8bbqr0vouosj3e8p8kb.apps.googleusercontent.com",
ClientSecret: "K2evIa4QhfbhhAm3SO72t2Zv",
},
GithubOAuth: OAuthCfg{
Enabled: true,
ClientId: "de054205006b9baa2e17",
ClientSecret: "72b7ea52d9f1096fdf36cea95e95362a307e0322",
},
},
}
}
......@@ -27,6 +27,7 @@ type Account struct {
AccountName string
Password string
Name string
Company string
NextDashboardId int
UsingAccountId int
Collaborators []CollaboratorLink
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment