Add google oauth provider. Need redirect_uri
parent
9c3ffed99e
commit
ae5e4edacf
1
Godeps
1
Godeps
|
@ -15,3 +15,4 @@ github.com/sergi/go-diff 1d28411638c1e67fe1930830df207bef72496ae9
|
|||
github.com/tylerb/graceful 50a48b6e73fcc75b45e22c05b79629a67c79e938
|
||||
golang.org/x/net 749a502dd1eaf3e5bfd4f8956748c502357c0bbe
|
||||
golang.org/x/oauth2 1e695b1c8febf17aad3bfa7bf0a819ef94b98ad5
|
||||
google.golang.org/api bc20c61134e1d25265dd60049f5735381e79b631
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* github.com/tylerb/graceful [MIT](https://github.com/tylerb/graceful/blob/master/LICENSE)
|
||||
* golang.org/x/net [BSD](https://github.com/golang/net/blob/master/LICENSE)
|
||||
* golang.org/x/oauth2 [BSD](https://github.com/golang/oauth2/blob/master/LICENSE)
|
||||
* google.golang.org/api/oauth2/v2 [BSD](https://github.com/google/google-api-go-client/blob/master/LICENSE)
|
||||
|
||||
### Javascript
|
||||
* Base64 0.2.1 [WTFPL](http://github.com/davidchambers/Base64.js)
|
||||
|
|
|
@ -1,19 +1,88 @@
|
|||
package oauth2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
goauth2 "google.golang.org/api/oauth2/v2"
|
||||
)
|
||||
|
||||
// Endpoint is Google's OAuth 2.0 endpoint.
|
||||
// Copied here to remove tons of package dependencies
|
||||
var GoogleEndpoint = oauth2.Endpoint{
|
||||
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
||||
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||
}
|
||||
var _ Provider = &Google{}
|
||||
|
||||
type Google struct {
|
||||
Provider
|
||||
Domains []string // Optional google email domain checking
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
Domains []string // Optional google email domain checking
|
||||
Logger chronograf.Logger
|
||||
}
|
||||
|
||||
/*
|
||||
client := conf.Client(oauth2.NoContext, tok)
|
||||
email, err := client.Get("https://www.googleapis.com/oauth2/v3/userinfo")
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
// Name is the name of the provider
|
||||
func (g *Google) Name() string {
|
||||
return "google"
|
||||
}
|
||||
|
||||
// ID returns the google application client id
|
||||
func (g *Google) ID() string {
|
||||
return g.ClientID
|
||||
}
|
||||
|
||||
// Secret returns the google application client secret
|
||||
func (g *Google) Secret() string {
|
||||
return g.ClientSecret
|
||||
}
|
||||
|
||||
// Scopes for google is only the email address
|
||||
// Documentation is here: https://developers.google.com/+/web/api/rest/oauth#email
|
||||
func (g *Google) Scopes() []string {
|
||||
return []string{
|
||||
goauth2.UserinfoEmailScope,
|
||||
goauth2.UserinfoProfileScope,
|
||||
}
|
||||
defer email.Body.Close()
|
||||
data, _ := ioutil.ReadAll(email.Body)
|
||||
log.Println("Email body: ", string(data))
|
||||
c.Status(http.StatusOK)
|
||||
*/
|
||||
}
|
||||
|
||||
// Config is the Google OAuth2 exchange information and endpoints
|
||||
func (g *Google) Config() *oauth2.Config {
|
||||
return &oauth2.Config{
|
||||
ClientID: g.ID(),
|
||||
ClientSecret: g.Secret(),
|
||||
Scopes: g.Scopes(),
|
||||
Endpoint: GoogleEndpoint,
|
||||
RedirectURL: "http://localhost:8888/oauth/google/callback", // TODO: we are required to have a redirect_uri from google
|
||||
}
|
||||
}
|
||||
|
||||
// PrincipalID returns the google email address of the user.
|
||||
func (g *Google) PrincipalID(provider *http.Client) (string, error) {
|
||||
srv, err := goauth2.New(provider)
|
||||
if err != nil {
|
||||
g.Logger.Error("Unable to communicate with Google ", err.Error())
|
||||
return "", err
|
||||
}
|
||||
info, err := srv.Userinfo.Get().Do()
|
||||
if err != nil {
|
||||
g.Logger.Error("Unable to retrieve Google email ", err.Error())
|
||||
return "", err
|
||||
}
|
||||
// No domain filtering required, so, the user is autenticated.
|
||||
if len(g.Domains) == 0 {
|
||||
return info.Email, nil
|
||||
}
|
||||
|
||||
// Check if the account domain is acceptable
|
||||
for _, requiredDomain := range g.Domains {
|
||||
if info.Hd == requiredDomain {
|
||||
return info.Email, nil
|
||||
}
|
||||
}
|
||||
g.Logger.Error("Domain '", info.Hd, "' is not a member of required Google domain(s): ", g.Domains)
|
||||
return "", fmt.Errorf("Not in required domain")
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@ type MuxOpts struct {
|
|||
TokenSecret string // TokenSecret is the JWT secret
|
||||
GithubClientID string // GithubClientID is the GH OAuth id
|
||||
GithubClientSecret string // GithubClientSecret is the GH OAuth secret
|
||||
GithubOrgs []string // GithubOrgs is the list of organizations a user my be a member of
|
||||
GithubOrgs []string // GithubOrgs is the list of organizations a user may be a member of
|
||||
GoogleClientID string // GoogleClientID is the Google OAuth id
|
||||
GoogleClientSecret string // GoogleClientSecret is the Google OAuth secret
|
||||
GoogleDomains []string // GoogleOrgs is the list of domains a user may be a member of
|
||||
}
|
||||
|
||||
// NewMux attaches all the route handlers; handler returned servers chronograf.
|
||||
|
@ -145,6 +148,18 @@ func AuthAPI(opts MuxOpts, router *httprouter.Router) http.Handler {
|
|||
router.Handler("GET", "/oauth/github/logout", ghMux.Logout())
|
||||
router.Handler("GET", "/oauth/github/callback", ghMux.Callback())
|
||||
|
||||
google := oauth2.Google{
|
||||
ClientID: opts.GoogleClientID,
|
||||
ClientSecret: opts.GoogleClientSecret,
|
||||
Domains: opts.GoogleDomains,
|
||||
Logger: opts.Logger,
|
||||
}
|
||||
|
||||
goMux := oauth2.NewJWTMux(&google, &auth, opts.Logger)
|
||||
router.Handler("GET", "/oauth/google/login", goMux.Login())
|
||||
router.Handler("GET", "/oauth/google/logout", goMux.Logout())
|
||||
router.Handler("GET", "/oauth/google/callback", goMux.Callback())
|
||||
|
||||
tokenMiddleware := oauth2.AuthorizedToken(&auth, &oauth2.CookieExtractor{Name: "session"}, opts.Logger, router)
|
||||
// Wrap the API with token validation middleware.
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -47,13 +47,17 @@ type Server struct {
|
|||
GithubClientID string `short:"i" long:"github-client-id" description:"Github Client ID for OAuth 2 support" env:"GH_CLIENT_ID"`
|
||||
GithubClientSecret string `short:"s" long:"github-client-secret" description:"Github Client Secret for OAuth 2 support" env:"GH_CLIENT_SECRET"`
|
||||
GithubOrgs []string `short:"o" long:"github-organization" description:"Github organization user is required to have active membership" env:"GH_ORGS" env-delim:","`
|
||||
ReportingDisabled bool `short:"r" long:"reporting-disabled" description:"Disable reporting of usage stats (os,arch,version,cluster_id,uptime) once every 24hr" env:"REPORTING_DISABLED"`
|
||||
LogLevel string `short:"l" long:"log-level" value-name:"choice" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal" choice:"panic" default:"info" description:"Set the logging level" env:"LOG_LEVEL"`
|
||||
Basepath string `short:"p" long:"basepath" description:"A URL path prefix under which all chronograf routes will be mounted" env:"BASE_PATH"`
|
||||
ShowVersion bool `short:"v" long:"version" description:"Show Chronograf version info"`
|
||||
BuildInfo BuildInfo
|
||||
Listener net.Listener
|
||||
handler http.Handler
|
||||
GoogleClientID string `long:"google-client-id" description:"Google Client ID for OAuth 2 support" env:"GOOGLE_CLIENT_ID"`
|
||||
GoogleClientSecret string `long:"google-client-secret" description:"Google Client Secret for OAuth 2 support" env:"GOGGLE_CLIENT_SECRET"`
|
||||
GoogleDomains []string `long:"google-domains" description:"Google email domain user is required to have active membership" env:"GOOGLE_DOMAINS" env-delim:","`
|
||||
|
||||
ReportingDisabled bool `short:"r" long:"reporting-disabled" description:"Disable reporting of usage stats (os,arch,version,cluster_id,uptime) once every 24hr" env:"REPORTING_DISABLED"`
|
||||
LogLevel string `short:"l" long:"log-level" value-name:"choice" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal" choice:"panic" default:"info" description:"Set the logging level" env:"LOG_LEVEL"`
|
||||
Basepath string `short:"p" long:"basepath" description:"A URL path prefix under which all chronograf routes will be mounted" env:"BASE_PATH"`
|
||||
ShowVersion bool `short:"v" long:"version" description:"Show Chronograf version info"`
|
||||
BuildInfo BuildInfo
|
||||
Listener net.Listener
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
// BuildInfo is sent to the usage client to track versions and commits
|
||||
|
@ -63,7 +67,9 @@ type BuildInfo struct {
|
|||
}
|
||||
|
||||
func (s *Server) useAuth() bool {
|
||||
return s.TokenSecret != "" && s.GithubClientID != "" && s.GithubClientSecret != ""
|
||||
gh := s.TokenSecret != "" && s.GithubClientID != "" && s.GithubClientSecret != ""
|
||||
google := s.TokenSecret != "" && s.GoogleClientID != "" && s.GoogleClientSecret != ""
|
||||
return gh || google
|
||||
}
|
||||
|
||||
// Serve starts and runs the chronograf server
|
||||
|
@ -77,6 +83,9 @@ func (s *Server) Serve() error {
|
|||
GithubClientID: s.GithubClientID,
|
||||
GithubClientSecret: s.GithubClientSecret,
|
||||
GithubOrgs: s.GithubOrgs,
|
||||
GoogleClientID: s.GoogleClientID,
|
||||
GoogleClientSecret: s.GoogleClientSecret,
|
||||
GoogleDomains: s.GoogleDomains,
|
||||
Logger: logger,
|
||||
UseAuth: s.useAuth(),
|
||||
}, service)
|
||||
|
|
Loading…
Reference in New Issue