OAuth remake

This commit is contained in:
Torkel Ödegaard 2014-10-07 17:56:37 -04:00
parent 450d242d5f
commit d7cd2b970e
9 changed files with 72 additions and 41 deletions

1
.gitignore vendored
View File

@ -15,3 +15,4 @@ config.js
.idea/ .idea/
data/sessions data/sessions
grafana-pro

View File

@ -34,6 +34,25 @@ session_id_hashfunc = sha1
; Session hash key, default is use random string ; Session hash key, default is use random string
session_id_hashkey = session_id_hashkey =
[oauth]
enabled = true
[oauth.github]
enabled = true
client_id = de054205006b9baa2e17
client_secret = 72b7ea52d9f1096fdf36cea95e95362a307e0322
scopes = user:email
auth_url = https://github.com/login/oauth/authorize
token_url = https://github.com/login/oauth/access_token
[oauth.google]
enabled = true
client_id = 106011922963-4pvl05e9urtrm8bbqr0vouosj3e8p8kb.apps.googleusercontent.com
client_secret = K2evIa4QhfbhhAm3SO72t2Zv
scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
auth_url = https://accounts.google.com/o/oauth2/auth
token_url = https://accounts.google.com/o/oauth2/token
[log] [log]
root_path = root_path =
; Either "console", "file", "conn", "smtp" or "database", default is "console" ; Either "console", "file", "conn", "smtp" or "database", default is "console"

Binary file not shown.

View File

@ -16,6 +16,7 @@ import (
"github.com/torkelo/grafana-pro/pkg/middleware" "github.com/torkelo/grafana-pro/pkg/middleware"
"github.com/torkelo/grafana-pro/pkg/routes" "github.com/torkelo/grafana-pro/pkg/routes"
"github.com/torkelo/grafana-pro/pkg/setting" "github.com/torkelo/grafana-pro/pkg/setting"
"github.com/torkelo/grafana-pro/pkg/social"
"github.com/torkelo/grafana-pro/pkg/stores/rethink" "github.com/torkelo/grafana-pro/pkg/stores/rethink"
) )
@ -65,6 +66,7 @@ func runWeb(*cli.Context) {
setting.NewConfigContext() setting.NewConfigContext()
setting.InitServices() setting.InitServices()
rethink.Init() rethink.Init()
social.NewOAuthService()
log.Info("Starting Grafana-Pro v.1-alpha") log.Info("Starting Grafana-Pro v.1-alpha")

View File

@ -3,6 +3,7 @@ package middleware
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"strconv"
"github.com/Unknwon/macaron" "github.com/Unknwon/macaron"
"github.com/macaron-contrib/session" "github.com/macaron-contrib/session"
@ -52,7 +53,7 @@ func (ctx *Context) Handle(status int, title string, err error) {
ctx.Data["Title"] = "Internal Server Error" ctx.Data["Title"] = "Internal Server Error"
} }
ctx.HTML(status, "index") ctx.HTML(status, strconv.Itoa(status))
} }
func (ctx *Context) JsonApiErr(status int, message string, err error) { func (ctx *Context) JsonApiErr(status int, message string, err error) {

View File

@ -13,14 +13,14 @@ import (
func OAuthLogin(ctx *middleware.Context) { func OAuthLogin(ctx *middleware.Context) {
if setting.OAuthService == nil { if setting.OAuthService == nil {
ctx.Handle(404, "social.SocialSignIn(oauth service not enabled)", nil) ctx.Handle(404, "login.OAuthLogin(oauth service not enabled)", nil)
return return
} }
name := ctx.Params(":name") name := ctx.Params(":name")
connect, ok := social.SocialMap[name] connect, ok := social.SocialMap[name]
if !ok { if !ok {
ctx.Handle(404, "social.SocialSignIn(social login not enabled)", errors.New(name)) ctx.Handle(404, "login.OAuthLogin(social login not enabled)", errors.New(name))
return return
} }
@ -29,23 +29,24 @@ func OAuthLogin(ctx *middleware.Context) {
ctx.Redirect(connect.AuthCodeURL("", "online", "auto")) ctx.Redirect(connect.AuthCodeURL("", "online", "auto"))
return return
} }
log.Info("code: %v", code)
// handle call back // handle call back
transport, err := connect.NewTransportWithCode(code) transport, err := connect.NewTransportWithCode(code)
if err != nil { if err != nil {
ctx.Handle(500, "social.SocialSignIn(NewTransportWithCode)", err) ctx.Handle(500, "login.OAuthLogin(NewTransportWithCode)", err)
return return
} }
log.Trace("social.SocialSignIn(Got token)") log.Trace("login.OAuthLogin(Got token)")
userInfo, err := connect.UserInfo(transport) userInfo, err := connect.UserInfo(transport)
if err != nil { if err != nil {
ctx.Handle(500, fmt.Sprintf("social.SocialSignIn(get info from %s)", name), err) ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
return return
} }
log.Info("social.SocialSignIn(social login): %s", userInfo) log.Info("login.OAuthLogin(social login): %s", userInfo)
account, err := models.GetAccountByLogin(userInfo.Email) account, err := models.GetAccountByLogin(userInfo.Email)

View File

@ -4,6 +4,7 @@ type OAuthInfo struct {
ClientId, ClientSecret string ClientId, ClientSecret string
Scopes []string Scopes []string
AuthUrl, TokenUrl string AuthUrl, TokenUrl string
Enabled bool
} }
type OAuther struct { type OAuther struct {

View File

@ -29,31 +29,33 @@ type SocialConnector interface {
} }
var ( var (
SocialBaseUrl = "/login" SocialBaseUrl = "/login/"
SocialMap = make(map[string]SocialConnector) SocialMap = make(map[string]SocialConnector)
) )
func NewOauthService() { func NewOAuthService() {
if !setting.Cfg.MustBool("oauth", "enabled") { if !setting.Cfg.MustBool("oauth", "enabled") {
return return
} }
var err error
setting.OAuthService = &setting.OAuther{} setting.OAuthService = &setting.OAuther{}
setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo) setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo)
socialConfigs := make(map[string]*oauth2.Config)
allOauthes := []string{"github", "google", "twitter"} allOauthes := []string{"github", "google", "twitter"}
// Load all OAuth config data. // Load all OAuth config data.
for _, name := range allOauthes { for _, name := range allOauthes {
info := &setting.OAuthInfo{ info := &setting.OAuthInfo{
ClientId: setting.Cfg.MustValue("oauth."+name, "client_id"), ClientId: setting.Cfg.MustValue("oauth."+name, "client_id"),
ClientSecret: setting.Cfg.MustValue("oauth."+name, "client_secrect"), ClientSecret: setting.Cfg.MustValue("oauth."+name, "client_secret"),
Scopes: setting.Cfg.MustValueArray("oauth."+name, "scopes", " "), Scopes: setting.Cfg.MustValueArray("oauth."+name, "scopes", " "),
AuthUrl: setting.Cfg.MustValue("oauth."+name, "auth_url"), AuthUrl: setting.Cfg.MustValue("oauth."+name, "auth_url"),
TokenUrl: setting.Cfg.MustValue("oauth."+name, "token_url"), TokenUrl: setting.Cfg.MustValue("oauth."+name, "token_url"),
Enabled: setting.Cfg.MustBool("oauth."+name, "enabled"),
}
if !info.Enabled {
continue
} }
opts := &oauth2.Options{ opts := &oauth2.Options{
@ -64,26 +66,24 @@ func NewOauthService() {
} }
setting.OAuthService.OAuthInfos[name] = info setting.OAuthService.OAuthInfos[name] = info
socialConfigs[name], err = oauth2.NewConfig(opts, info.AuthUrl, info.TokenUrl) config, err := oauth2.NewConfig(opts, info.AuthUrl, info.TokenUrl)
if err != nil { if err != nil {
log.Error(4, "Failed to init oauth service", err) log.Error(3, "Failed to init oauth service", err)
continue
} }
}
enabledOauths := make([]string, 0, 10) // GitHub.
if name == "github" {
setting.OAuthService.GitHub = true
SocialMap["github"] = &SocialGithub{Config: config}
}
// GitHub. // Google.
if setting.Cfg.MustBool("oauth.github", "enabled") { if name == "google" {
setting.OAuthService.GitHub = true setting.OAuthService.Google = true
newGitHubOAuth(socialConfigs["github"]) SocialMap["google"] = &SocialGoogle{Config: config}
enabledOauths = append(enabledOauths, "GitHub") }
}
// Google.
if setting.Cfg.MustBool("oauth.google", "enabled") {
setting.OAuthService.Google = true
newGoogleOAuth(socialConfigs["google"])
enabledOauths = append(enabledOauths, "Google")
} }
} }
@ -95,12 +95,6 @@ func (s *SocialGithub) Type() int {
return int(models.GITHUB) return int(models.GITHUB)
} }
func newGitHubOAuth(config *oauth2.Config) {
SocialMap["github"] = &SocialGithub{
Config: config,
}
}
func (s *SocialGithub) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) { func (s *SocialGithub) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) {
var data struct { var data struct {
Id int `json:"id"` Id int `json:"id"`
@ -143,12 +137,6 @@ func (s *SocialGoogle) Type() int {
return int(models.GOOGLE) return int(models.GOOGLE)
} }
func newGoogleOAuth(config *oauth2.Config) {
SocialMap["google"] = &SocialGoogle{
Config: config,
}
}
func (s *SocialGoogle) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) { func (s *SocialGoogle) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) {
var data struct { var data struct {
Id string `json:"id"` Id string `json:"id"`

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>Grafana</title>
<link rel="stylesheet" href="/public/css/grafana.dark.min.css" title="Dark">
<link rel="icon" type="image/png" href="img/fav32.png">
<base href="/">
</head>
<body>
<h1>404</h1>
</body>
</html>