Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 7 additions & 20 deletions internal/auth/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (

// Authenticator stores all the information associated with proxying the request.
type Authenticator struct {
Validator func(string) bool
EmailDomains []string
ProxyRootDomains []string
Host string
Scheme string
Expand Down Expand Up @@ -80,7 +78,6 @@ func NewAuthenticator(config Configuration, optionFuncs ...func(*Authenticator)
p := &Authenticator{
ProxyClientID: config.ClientConfigs["proxy"].ID,
ProxyClientSecret: config.ClientConfigs["proxy"].Secret,
EmailDomains: config.AuthorizeConfig.EmailConfig.Domains,
Host: config.ServerConfig.Host,
Scheme: config.ServerConfig.Scheme,

Expand Down Expand Up @@ -152,10 +149,16 @@ func (p *Authenticator) SignInPage(rw http.ResponseWriter, req *http.Request, co
// validateRedirectURI middleware already ensures that this is a valid URL
destinationURL, _ := url.Parse(redirectURL.Query().Get("redirect_uri"))

emailDomainsFormValue := req.FormValue("email_domains")
emailDomains := []string{}
if emailDomainsFormValue != "" {
emailDomains = strings.Split(emailDomainsFormValue, ",")
}

t := signInResp{
ProviderName: p.provider.Data().ProviderName,
ProviderSlug: p.provider.Data().ProviderSlug,
EmailDomains: p.EmailDomains,
EmailDomains: emailDomains,
Redirect: redirectURL.String(),
Destination: destinationURL.Host,
Version: VERSION,
Expand Down Expand Up @@ -225,11 +228,6 @@ func (p *Authenticator) authenticate(rw http.ResponseWriter, req *http.Request)
}
}

if !p.Validator(session.Email) {
logger.WithUser(session.Email).Error("invalid email user")
return nil, ErrUserNotAuthorized
}

return session, nil
}

Expand Down Expand Up @@ -569,17 +567,6 @@ func (p *Authenticator) getOAuthCallback(rw http.ResponseWriter, req *http.Reque
return "", HTTPError{Code: http.StatusForbidden, Message: "Invalid Redirect URI"}
}

// Set cookie, or deny: The authenticator validates the session email and group
// - for p.Validator see validator.go#newValidatorImpl for more info
// - for p.provider.ValidateGroup see providers/google.go#ValidateGroup for more info
if !p.Validator(session.Email) {
tags := append(tags, "error:invalid_email")
p.StatsdClient.Incr("application_error", tags, 1.0)
logger.WithRemoteAddress(remoteAddr).WithUser(session.Email).Error(
"invalid_email", "permission denied; unauthorized user")
return "", HTTPError{Code: http.StatusForbidden, Message: "Invalid Account"}
}

logger.WithRemoteAddress(remoteAddr).WithUser(session.Email).Info("authentication complete")
err = p.sessionStore.SaveSession(rw, req, session)
if err != nil {
Expand Down
88 changes: 15 additions & 73 deletions internal/auth/authenticator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,6 @@ func setTestProvider(provider *providers.TestProvider) func(*Authenticator) erro
}
}

func setMockValidator(response bool) func(*Authenticator) error {
return func(a *Authenticator) error {
a.Validator = func(string) bool { return response }
return nil
}
}

func setRedirectURL(redirectURL *url.URL) func(*Authenticator) error {
return func(a *Authenticator) error {
a.redirectURL = redirectURL
Expand Down Expand Up @@ -135,14 +128,16 @@ func TestSignIn(t *testing.T) {
mockAuthCodeCipher *aead.MockCipher
refreshResponse providerRefreshResponse
providerValidToken bool
validEmail bool
expectedSignInPage bool
expectedDestinationURL string
expectedCode int
expectedErrorResponse *errResponse
}{
{
name: "err no cookie calls proxy oauth redirect, no params map redirects to sign in page",
paramsMap: map[string]string{
"email_domains": "testone.com,testtwo.com",
},
mockSessionStore: &sessions.MockSessionStore{
LoadError: http.ErrNoCookie,
},
Expand All @@ -156,7 +151,8 @@ func TestSignIn(t *testing.T) {
LoadError: http.ErrNoCookie,
},
paramsMap: map[string]string{
"redirect_uri": "http://foo.example.com",
"email_domains": "testone.com,testtwo.com",
"redirect_uri": "http://foo.example.com",
},
expectedSignInPage: true,
expectedDestinationURL: "foo.example.com",
Expand All @@ -175,6 +171,9 @@ func TestSignIn(t *testing.T) {
},
{
name: "expired lifetime of session clears session and redirects to sign in",
paramsMap: map[string]string{
"email_domains": "testone.com,testtwo.com",
},
mockSessionStore: &sessions.MockSessionStore{
Session: &sessions.SessionState{
Email: "email",
Expand Down Expand Up @@ -238,23 +237,6 @@ func TestSignIn(t *testing.T) {
expectedCode: http.StatusInternalServerError,
expectedErrorResponse: &errResponse{"save error"},
},
{
name: "refresh period expired, successful refresh, invalid email",
mockSessionStore: &sessions.MockSessionStore{
Session: &sessions.SessionState{
Email: "email",
AccessToken: "accesstoken",
RefreshToken: "refresh",
LifetimeDeadline: time.Now().Add(time.Hour),
RefreshDeadline: time.Now().Add(-time.Hour),
},
},
refreshResponse: providerRefreshResponse{
OK: true,
},
expectedCode: http.StatusUnauthorized,
expectedErrorResponse: &errResponse{ErrUserNotAuthorized.Error()},
},
{
name: "valid session state, save session error",
mockSessionStore: &sessions.MockSessionStore{
Expand All @@ -272,7 +254,7 @@ func TestSignIn(t *testing.T) {
expectedErrorResponse: &errResponse{"save error"},
},
{
name: "invalid session state, invalid email",
name: "invalid session state",
mockSessionStore: &sessions.MockSessionStore{
Session: &sessions.SessionState{
Email: "email",
Expand All @@ -299,7 +281,6 @@ func TestSignIn(t *testing.T) {
refreshResponse: providerRefreshResponse{
OK: true,
},
validEmail: true,
expectedCode: http.StatusForbidden,
expectedErrorResponse: &errResponse{"no state parameter supplied"},
},
Expand All @@ -320,7 +301,6 @@ func TestSignIn(t *testing.T) {
refreshResponse: providerRefreshResponse{
OK: true,
},
validEmail: true,
expectedCode: http.StatusForbidden,
expectedErrorResponse: &errResponse{"no redirect_uri parameter supplied"},
},
Expand All @@ -342,7 +322,6 @@ func TestSignIn(t *testing.T) {
refreshResponse: providerRefreshResponse{
OK: true,
},
validEmail: true,
expectedCode: http.StatusBadRequest,
expectedErrorResponse: &errResponse{"malformed redirect_uri parameter passed"},
},
Expand All @@ -367,7 +346,6 @@ func TestSignIn(t *testing.T) {
mockAuthCodeCipher: &aead.MockCipher{
MarshalError: fmt.Errorf("error marshal"),
},
validEmail: true,
expectedCode: http.StatusInternalServerError,
expectedErrorResponse: &errResponse{"error marshal"},
},
Expand All @@ -392,7 +370,6 @@ func TestSignIn(t *testing.T) {
mockAuthCodeCipher: &aead.MockCipher{
MarshalString: "abcdefg",
},
validEmail: true,
expectedCode: http.StatusFound,
},
{
Expand All @@ -410,7 +387,6 @@ func TestSignIn(t *testing.T) {
"state": "state",
"redirect_uri": "http://foo.example.com",
},
validEmail: true,
providerValidToken: true,
mockAuthCodeCipher: &aead.MockCipher{
MarshalString: "abcdefg",
Expand All @@ -424,7 +400,6 @@ func TestSignIn(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
config := testConfiguration(t)
auth, err := NewAuthenticator(config,
setMockValidator(tc.validEmail),
setMockSessionStore(tc.mockSessionStore),
setMockTempl(),
setMockRedirectURL(),
Expand Down Expand Up @@ -459,7 +434,7 @@ func TestSignIn(t *testing.T) {
expectedSignInResp := &signInResp{
ProviderName: provider.Data().ProviderName,
ProviderSlug: "test",
EmailDomains: auth.EmailDomains,
EmailDomains: []string{"testone.com", "testtwo.com"},
Redirect: u.String(),
Destination: tc.expectedDestinationURL,
Version: VERSION,
Expand Down Expand Up @@ -571,7 +546,6 @@ func TestSignOutPage(t *testing.T) {
provider.RevokeError = tc.RevokeError

p, _ := NewAuthenticator(config,
setMockValidator(true),
setMockSessionStore(tc.mockSessionStore),
setMockTempl(),
setTestProvider(provider),
Expand Down Expand Up @@ -947,9 +921,7 @@ func TestGetProfile(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config := testConfiguration(t)
p, _ := NewAuthenticator(config,
setMockValidator(true),
)
p, _ := NewAuthenticator(config)
u, _ := url.Parse("http://example.com")
testProvider := providers.NewTestProvider(u)
testProvider.Groups = tc.groupEmails
Expand Down Expand Up @@ -1049,9 +1021,7 @@ func TestRedeemCode(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
config := testConfiguration(t)

proxy, _ := NewAuthenticator(config,
setMockValidator(true),
)
proxy, _ := NewAuthenticator(config)

testURL, err := url.Parse("example.com")
if err != nil {
Expand Down Expand Up @@ -1220,7 +1190,6 @@ func TestOAuthCallback(t *testing.T) {
paramsMap map[string]string
expectedError error
testRedeemResponse testRedeemResponse
validEmail bool
csrfResp *sessions.MockCSRFStore
sessionStore *sessions.MockSessionStore
expectedRedirect string
Expand Down Expand Up @@ -1338,29 +1307,7 @@ func TestOAuthCallback(t *testing.T) {
},

{
name: "invalid email address",
paramsMap: map[string]string{
"code": "authCode",
"state": base64.URLEncoding.EncodeToString([]byte("state:http://www.example.com/something")),
},
testRedeemResponse: testRedeemResponse{
SessionState: &sessions.SessionState{
Email: "example@email.com",
AccessToken: "accessToken",
RefreshDeadline: time.Now().Add(time.Hour),
RefreshToken: "refresh",
},
},
csrfResp: &sessions.MockCSRFStore{
Cookie: &http.Cookie{
Name: "something_csrf",
Value: "state",
},
},
expectedError: HTTPError{Code: http.StatusForbidden, Message: "Invalid Account"},
},
{
name: "valid email, invalid redirect",
name: "invalid redirect",
paramsMap: map[string]string{
"code": "authCode",
"state": base64.URLEncoding.EncodeToString([]byte("state:something")),
Expand All @@ -1379,11 +1326,10 @@ func TestOAuthCallback(t *testing.T) {
Value: "state",
},
},
validEmail: true,
expectedError: HTTPError{Code: http.StatusForbidden, Message: "Invalid Redirect URI"},
},
{
name: "valid email, valid redirect, save error",
name: "valid redirect, save error",
paramsMap: map[string]string{
"code": "authCode",
"state": base64.URLEncoding.EncodeToString([]byte("state:http://www.example.com/something")),
Expand All @@ -1405,11 +1351,10 @@ func TestOAuthCallback(t *testing.T) {
sessionStore: &sessions.MockSessionStore{
SaveError: fmt.Errorf("saveError"),
},
validEmail: true,
expectedError: HTTPError{Code: http.StatusInternalServerError, Message: "Internal Error"},
},
{
name: "valid email, valid redirect, valid save",
name: "valid redirect, valid save",
paramsMap: map[string]string{
"code": "authCode",
"state": base64.URLEncoding.EncodeToString([]byte("state:http://www.example.com/something")),
Expand All @@ -1429,7 +1374,6 @@ func TestOAuthCallback(t *testing.T) {
},
},
sessionStore: &sessions.MockSessionStore{},
validEmail: true,
expectedRedirect: "http://www.example.com/something",
},
}
Expand All @@ -1438,7 +1382,6 @@ func TestOAuthCallback(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
config := testConfiguration(t)
proxy, _ := NewAuthenticator(config,
setMockValidator(tc.validEmail),
setMockCSRFStore(tc.csrfResp),
setMockSessionStore(tc.sessionStore),
)
Expand Down Expand Up @@ -1559,7 +1502,6 @@ func TestOAuthStart(t *testing.T) {
provider := providers.NewTestProvider(nil)
proxy, _ := NewAuthenticator(config,
setTestProvider(provider),
setMockValidator(true),
setMockRedirectURL(),
setMockCSRFStore(&sessions.MockCSRFStore{}),
)
Expand Down
Loading