Skip to content
Snippets Groups Projects
Commit 6f86efb5 authored by Patrick O'Doherty's avatar Patrick O'Doherty
Browse files

Don't allow wide-open Google or Github configs

Fail loudly if either the google_opts domain value or github_opts organization
values are not set in the configuration. The lack of these values means that
 a) in the Google case any @gmail.com address will be allowed
 b) the Github case any Github user will be allowed.

This was previously documented but left as a foot-gun in the code.

Future commits will allow for explicit wildcards to be set.
parent 7f6b342d
No related branches found
No related tags found
No related merge requests found
...@@ -212,13 +212,17 @@ func main() { ...@@ -212,13 +212,17 @@ func main() {
var authprovider auth.Provider var authprovider auth.Provider
switch config.Auth.Provider { switch config.Auth.Provider {
case "google": case "google":
authprovider = google.New(&config.Auth) authprovider, err = google.New(&config.Auth)
case "github": case "github":
authprovider = github.New(&config.Auth) authprovider, err = github.New(&config.Auth)
default: default:
log.Fatalln("Unknown provider %s", config.Auth.Provider) log.Fatalln("Unknown provider %s", config.Auth.Provider)
} }
if err != nil {
log.Fatal(err)
}
ctx := &appContext{ ctx := &appContext{
cookiestore: sessions.NewCookieStore([]byte(config.Server.CookieSecret)), cookiestore: sessions.NewCookieStore([]byte(config.Server.CookieSecret)),
authprovider: authprovider, authprovider: authprovider,
......
package github package github
import ( import (
"errors"
"net/http" "net/http"
"github.com/nsheridan/cashier/server/auth" "github.com/nsheridan/cashier/server/auth"
...@@ -23,7 +24,10 @@ type Config struct { ...@@ -23,7 +24,10 @@ type Config struct {
} }
// New creates a new Github provider from a configuration. // New creates a new Github provider from a configuration.
func New(c *config.Auth) auth.Provider { func New(c *config.Auth) (auth.Provider, error) {
if c.ProviderOpts["organization"] == "" {
return nil, errors.New("github_opts organization must not be empty")
}
return &Config{ return &Config{
config: &oauth2.Config{ config: &oauth2.Config{
ClientID: c.OauthClientID, ClientID: c.OauthClientID,
...@@ -36,7 +40,7 @@ func New(c *config.Auth) auth.Provider { ...@@ -36,7 +40,7 @@ func New(c *config.Auth) auth.Provider {
}, },
}, },
organization: c.ProviderOpts["organization"], organization: c.ProviderOpts["organization"],
} }, nil
} }
// A new oauth2 http client. // A new oauth2 http client.
...@@ -54,9 +58,6 @@ func (c *Config) Valid(token *oauth2.Token) bool { ...@@ -54,9 +58,6 @@ func (c *Config) Valid(token *oauth2.Token) bool {
if !token.Valid() { if !token.Valid() {
return false return false
} }
if c.organization == "" {
return true
}
client := githubapi.NewClient(c.newClient(token)) client := githubapi.NewClient(c.newClient(token))
member, _, err := client.Organizations.IsMember(c.organization, c.Username(token)) member, _, err := client.Organizations.IsMember(c.organization, c.Username(token))
if err != nil { if err != nil {
......
...@@ -19,7 +19,7 @@ var ( ...@@ -19,7 +19,7 @@ var (
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
a := assert.New(t) a := assert.New(t)
p := newGithub() p, _ := newGithub()
g := p.(*Config) g := p.(*Config)
a.Equal(g.config.ClientID, oauthClientID) a.Equal(g.config.ClientID, oauthClientID)
a.Equal(g.config.ClientSecret, oauthClientSecret) a.Equal(g.config.ClientSecret, oauthClientSecret)
...@@ -27,10 +27,20 @@ func TestNew(t *testing.T) { ...@@ -27,10 +27,20 @@ func TestNew(t *testing.T) {
a.Equal(g.organization, organization) a.Equal(g.organization, organization)
} }
func TestNewEmptyOrganization(t *testing.T) {
organization = ""
a := assert.New(t)
_, err := newGithub()
a.EqualError(err, "github_opts organization must not be empty")
organization = "exampleorg"
}
func TestStartSession(t *testing.T) { func TestStartSession(t *testing.T) {
a := assert.New(t) a := assert.New(t)
p := newGithub() p, _ := newGithub()
s := p.StartSession("test_state") s := p.StartSession("test_state")
a.Equal(s.State, "test_state") a.Equal(s.State, "test_state")
a.Contains(s.AuthURL, "github.com/login/oauth/authorize") a.Contains(s.AuthURL, "github.com/login/oauth/authorize")
...@@ -38,7 +48,7 @@ func TestStartSession(t *testing.T) { ...@@ -38,7 +48,7 @@ func TestStartSession(t *testing.T) {
a.Contains(s.AuthURL, fmt.Sprintf("client_id=%s", oauthClientID)) a.Contains(s.AuthURL, fmt.Sprintf("client_id=%s", oauthClientID))
} }
func newGithub() auth.Provider { func newGithub() (auth.Provider, error) {
c := &config.Auth{ c := &config.Auth{
OauthClientID: oauthClientID, OauthClientID: oauthClientID,
OauthClientSecret: oauthClientSecret, OauthClientSecret: oauthClientSecret,
......
package google package google
import ( import (
"errors"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
...@@ -26,7 +27,11 @@ type Config struct { ...@@ -26,7 +27,11 @@ type Config struct {
} }
// New creates a new Google provider from a configuration. // New creates a new Google provider from a configuration.
func New(c *config.Auth) auth.Provider { func New(c *config.Auth) (auth.Provider, error) {
if c.ProviderOpts["domain"] == "" {
return nil, errors.New("google_opts domain must not be empty")
}
return &Config{ return &Config{
config: &oauth2.Config{ config: &oauth2.Config{
ClientID: c.OauthClientID, ClientID: c.OauthClientID,
...@@ -36,7 +41,7 @@ func New(c *config.Auth) auth.Provider { ...@@ -36,7 +41,7 @@ func New(c *config.Auth) auth.Provider {
Scopes: []string{googleapi.UserinfoEmailScope, googleapi.UserinfoProfileScope}, Scopes: []string{googleapi.UserinfoEmailScope, googleapi.UserinfoProfileScope},
}, },
domain: c.ProviderOpts["domain"], domain: c.ProviderOpts["domain"],
} }, nil
} }
// A new oauth2 http client. // A new oauth2 http client.
......
...@@ -19,7 +19,7 @@ var ( ...@@ -19,7 +19,7 @@ var (
func TestNew(t *testing.T) { func TestNew(t *testing.T) {
a := assert.New(t) a := assert.New(t)
p := newGoogle() p, _ := newGoogle()
g := p.(*Config) g := p.(*Config)
a.Equal(g.config.ClientID, oauthClientID) a.Equal(g.config.ClientID, oauthClientID)
a.Equal(g.config.ClientSecret, oauthClientSecret) a.Equal(g.config.ClientSecret, oauthClientSecret)
...@@ -27,10 +27,22 @@ func TestNew(t *testing.T) { ...@@ -27,10 +27,22 @@ func TestNew(t *testing.T) {
a.Equal(g.domain, domain) a.Equal(g.domain, domain)
} }
func TestNewWithoutDomain(t *testing.T) {
a := assert.New(t)
domain = ""
_, err := newGoogle()
a.EqualError(err, "google_opts domain must not be empty")
domain = "example.com"
}
func TestStartSession(t *testing.T) { func TestStartSession(t *testing.T) {
a := assert.New(t) a := assert.New(t)
p := newGoogle() p, err := newGoogle()
a.NoError(err)
s := p.StartSession("test_state") s := p.StartSession("test_state")
a.Equal(s.State, "test_state") a.Equal(s.State, "test_state")
a.Contains(s.AuthURL, "accounts.google.com/o/oauth2/auth") a.Contains(s.AuthURL, "accounts.google.com/o/oauth2/auth")
...@@ -39,13 +51,12 @@ func TestStartSession(t *testing.T) { ...@@ -39,13 +51,12 @@ func TestStartSession(t *testing.T) {
a.Contains(s.AuthURL, fmt.Sprintf("client_id=%s", oauthClientID)) a.Contains(s.AuthURL, fmt.Sprintf("client_id=%s", oauthClientID))
} }
func newGoogle() auth.Provider { func newGoogle() (auth.Provider, error) {
c := &config.Auth{ c := &config.Auth{
OauthClientID: oauthClientID, OauthClientID: oauthClientID,
OauthClientSecret: oauthClientSecret, OauthClientSecret: oauthClientSecret,
OauthCallbackURL: oauthCallbackURL, OauthCallbackURL: oauthCallbackURL,
ProviderOpts: map[string]string{"domain": domain}, ProviderOpts: map[string]string{"domain": domain},
} }
c.ProviderOpts["domain"] = domain
return New(c) return New(c)
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment