Пример #1
0
func TestUnlock(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	storer := mocks.NewMockStorer()
	ab.Storer = storer
	lock := Lock{ab}
	ab.LockWindow = 1 * time.Hour

	email := "*****@*****.**"
	storer.Users[email] = map[string]interface{}{
		ab.PrimaryID: email,
		"password":   "******",
		"locked":     true,
	}

	err := lock.Unlock(email)
	if err != nil {
		t.Error(err)
	}

	attemptTime := storer.Users[email][StoreAttemptTime].(time.Time)
	if attemptTime.After(time.Now().UTC().Add(-ab.LockWindow)) {
		t.Error("StoreLocked not set correctly:", attemptTime)
	}
	if number := storer.Users[email][StoreAttemptNumber].(int64); number != int64(0) {
		t.Error("StoreLocked not set correctly:", number)
	}
	if locked := storer.Users[email][StoreLocked].(time.Time); locked.After(time.Now()) {
		t.Error("User should not be locked.")
	}
}
Пример #2
0
func TestAfterAuthFail_Reset(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	var old, current time.Time
	var ok bool

	ctx := ab.NewContext()
	storer := mocks.NewMockStorer()
	lock := Lock{ab}
	ab.LockWindow = 30 * time.Minute
	ab.Storer = storer

	old = time.Now().UTC().Add(-time.Hour)

	email := "*****@*****.**"
	ctx.User = map[string]interface{}{
		ab.PrimaryID:       email,
		StoreAttemptNumber: int64(2),
		StoreAttemptTime:   old,
		StoreLocked:        old,
	}

	lock.afterAuthFail(ctx)
	if val := storer.Users[email][StoreAttemptNumber].(int64); val != int64(0) {
		t.Error("StoreAttemptNumber set incorrectly:", val)
	}
	if current, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok || current.Before(old) {
		t.Error("StoreAttemptTime not set correctly.")
	}
	if locked := storer.Users[email][StoreLocked].(time.Time); locked.After(time.Now()) {
		t.Error("StoreLocked not set correctly:", locked)
	}
}
Пример #3
0
func TestAfterOAuth(t *testing.T) {
	t.Parallel()

	r := Remember{authboss.New()}
	storer := mocks.NewMockStorer()
	r.Storer = storer

	cookies := mocks.NewMockClientStorer()
	session := mocks.NewMockClientStorer(authboss.SessionOAuth2Params, `{"rm":"true"}`)

	ctx := r.NewContext()
	ctx.SessionStorer = session
	ctx.CookieStorer = cookies
	ctx.User = authboss.Attributes{
		authboss.StoreOAuth2UID:      "uid",
		authboss.StoreOAuth2Provider: "google",
	}

	if err := r.afterOAuth(ctx); err != nil {
		t.Error(err)
	}

	if _, ok := cookies.Values[authboss.CookieRemember]; !ok {
		t.Error("Expected a cookie to have been set.")
	}
}
Пример #4
0
func TestAfterPasswordReset(t *testing.T) {
	t.Parallel()

	r := Remember{authboss.New()}

	id := "*****@*****.**"

	storer := mocks.NewMockStorer()
	r.Storer = storer
	session := mocks.NewMockClientStorer()
	cookies := mocks.NewMockClientStorer()
	storer.Tokens[id] = []string{"one", "two"}
	cookies.Values[authboss.CookieRemember] = "token"

	ctx := r.NewContext()
	ctx.User = authboss.Attributes{r.PrimaryID: id}
	ctx.SessionStorer = session
	ctx.CookieStorer = cookies

	if err := r.afterPassword(ctx); err != nil {
		t.Error(err)
	}

	if _, ok := cookies.Values[authboss.CookieRemember]; ok {
		t.Error("Expected the remember cookie to be deleted.")
	}

	if len(storer.Tokens) != 0 {
		t.Error("Should have wiped out all tokens.")
	}
}
Пример #5
0
func TestAuth_validateCredentials(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	storer := mocks.NewMockStorer()
	ab.Storer = storer

	ctx := ab.NewContext()
	storer.Users["john"] = authboss.Attributes{"password": "******"}
	if _, err := validateCredentials(ctx, "john", "a"); err != nil {
		t.Error("Unexpected error:", err)
	}

	ctx = ab.NewContext()
	if valid, err := validateCredentials(ctx, "jake", "a"); err != nil {
		t.Error("Expect no error when user not found:", err)
	} else if valid {
		t.Error("Expect invalid when not user found")
	}

	ctx = ab.NewContext()
	storer.GetErr = "Failed to load user"
	if _, err := validateCredentials(ctx, "", ""); err.Error() != "Failed to load user" {
		t.Error("Unexpected error:", err)
	}

}
Пример #6
0
func TestNew(t *testing.T) {
	t.Parallel()

	r := &Remember{authboss.New()}
	storer := mocks.NewMockStorer()
	r.Storer = storer
	cookies := mocks.NewMockClientStorer()

	key := "tester"
	token, err := r.new(cookies, key)

	if err != nil {
		t.Error("Unexpected error:", err)
	}

	if len(token) == 0 {
		t.Error("Expected a token.")
	}

	if tok, ok := storer.Tokens[key]; !ok {
		t.Error("Expected it to store against the key:", key)
	} else if len(tok) != 1 || len(tok[0]) == 0 {
		t.Error("Expected a token to be saved.")
	}

	if token != cookies.Values[authboss.CookieRemember] {
		t.Error("Expected a cookie set with the token.")
	}
}
Пример #7
0
func TestAfterAuth(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	lock := Lock{}
	ctx := ab.NewContext()

	if err := lock.afterAuth(ctx); err != errUserMissing {
		t.Error("Expected an error because of missing user:"******"*****@*****.**"}

	if err := lock.afterAuth(ctx); err != nil {
		t.Error(err)
	}
	if storer.Users["*****@*****.**"][StoreAttemptNumber].(int64) != int64(0) {
		t.Error("StoreAttemptNumber set incorrectly.")
	}
	if _, ok := storer.Users["*****@*****.**"][StoreAttemptTime].(time.Time); !ok {
		t.Error("StoreAttemptTime not set.")
	}
}
Пример #8
0
func TestAfterAuth(t *testing.T) {
	t.Parallel()

	r := Remember{authboss.New()}
	storer := mocks.NewMockStorer()
	r.Storer = storer

	cookies := mocks.NewMockClientStorer()
	session := mocks.NewMockClientStorer()

	req, err := http.NewRequest("POST", "http://localhost", bytes.NewBufferString("rm=true"))
	if err != nil {
		t.Error("Unexpected Error:", err)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	ctx := r.NewContext()
	ctx.SessionStorer = session
	ctx.CookieStorer = cookies
	ctx.User = authboss.Attributes{r.PrimaryID: "*****@*****.**"}

	ctx.Values = map[string]string{authboss.CookieRemember: "true"}

	if err := r.afterAuth(ctx); err != nil {
		t.Error(err)
	}

	if _, ok := cookies.Values[authboss.CookieRemember]; !ok {
		t.Error("Expected a cookie to have been set.")
	}
}
Пример #9
0
func TestConfirm_Confirm(t *testing.T) {
	t.Parallel()

	c := setup()
	ctx := c.NewContext()
	log := &bytes.Buffer{}
	c.LogWriter = log
	c.PrimaryID = authboss.StoreUsername
	c.Mailer = authboss.LogMailer(log)

	// Create a token
	token := []byte("hi")
	sum := md5.Sum(token)

	// Create the "database"
	storer := mocks.NewMockStorer()
	c.Storer = storer
	user := authboss.Attributes{
		authboss.StoreUsername: "******",
		StoreConfirmToken:      base64.StdEncoding.EncodeToString(sum[:]),
	}
	storer.Users["usern"] = user

	// Make a request with session and context support.
	r, _ := http.NewRequest("GET", "http://localhost?cnf="+base64.URLEncoding.EncodeToString(token), nil)
	w := httptest.NewRecorder()
	ctx = c.NewContext()
	ctx.CookieStorer = mocks.NewMockClientStorer()
	session := mocks.NewMockClientStorer()
	ctx.User = user
	ctx.SessionStorer = session

	c.confirmHandler(ctx, w, r)
	if w.Code != http.StatusFound {
		t.Error("Expected a redirect after success:", w.Code)
	}

	if log.Len() != 0 {
		t.Error("Expected a clean log on success:", log.String())
	}

	is, ok := ctx.User.Bool(StoreConfirmed)
	if !ok || !is {
		t.Error("The user should be confirmed.")
	}

	tok, ok := ctx.User.String(StoreConfirmToken)
	if ok && len(tok) != 0 {
		t.Error("Confirm token should have been wiped out.")
	}

	if key, ok := ctx.SessionStorer.Get(authboss.SessionKey); !ok || len(key) == 0 {
		t.Error("Should have logged the user in.")
	}
	if success, ok := ctx.SessionStorer.Get(authboss.FlashSuccessKey); !ok || len(success) == 0 {
		t.Error("Should have left a nice message.")
	}
}
Пример #10
0
func TestInitialize(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	ab.OAuth2Storer = mocks.NewMockStorer()
	o := OAuth2{}
	if err := o.Initialize(ab); err != nil {
		t.Error(err)
	}
}
Пример #11
0
func setup() *Confirm {
	ab := authboss.New()
	ab.Storer = mocks.NewMockStorer()
	ab.LayoutHTMLEmail = template.Must(template.New("").Parse(`email ^_^`))
	ab.LayoutTextEmail = template.Must(template.New("").Parse(`email`))

	c := &Confirm{}
	if err := c.Initialize(ab); err != nil {
		panic(err)
	}
	return c
}
Пример #12
0
func TestAfterAuthFail_Lock(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	var old, current time.Time
	var ok bool

	ctx := ab.NewContext()
	storer := mocks.NewMockStorer()
	ab.Storer = storer
	lock := Lock{ab}
	ab.LockWindow = 30 * time.Minute
	ab.LockDuration = 30 * time.Minute
	ab.LockAfter = 3

	email := "*****@*****.**"

	ctx.User = map[string]interface{}{ab.PrimaryID: email}

	old = time.Now().UTC().Add(-1 * time.Hour)

	for i := 0; i < 3; i++ {
		if lockedIntf, ok := storer.Users["*****@*****.**"][StoreLocked]; ok && lockedIntf.(bool) {
			t.Errorf("%d: User should not be locked.", i)
		}

		if err := lock.afterAuthFail(ctx); err != nil {
			t.Error(err)
		}
		if val := storer.Users[email][StoreAttemptNumber].(int64); val != int64(i+1) {
			t.Errorf("%d: StoreAttemptNumber set incorrectly: %v", i, val)
		}
		if current, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok || old.After(current) {
			t.Errorf("%d: StoreAttemptTime not set correctly: %v", i, current)
		}

		current = old
	}

	if locked := storer.Users[email][StoreLocked].(time.Time); !locked.After(time.Now()) {
		t.Error("User should be locked for some duration:", locked)
	}
	if val := storer.Users[email][StoreAttemptNumber].(int64); val != int64(3) {
		t.Error("StoreAttemptNumber set incorrectly:", val)
	}
	if _, ok = storer.Users[email][StoreAttemptTime].(time.Time); !ok {
		t.Error("StoreAttemptTime not set correctly.")
	}
}
Пример #13
0
func setup() *Register {
	ab := authboss.New()
	ab.RegisterOKPath = "/regsuccess"
	ab.Layout = template.Must(template.New("").Parse(`{{template "authboss" .}}`))
	ab.XSRFName = "xsrf"
	ab.XSRFMaker = func(_ http.ResponseWriter, _ *http.Request) string {
		return "xsrfvalue"
	}
	ab.ConfirmFields = []string{"password", "confirm_password"}
	ab.Storer = mocks.NewMockStorer()

	reg := Register{}
	if err := reg.Initialize(ab); err != nil {
		panic(err)
	}

	return &reg
}
Пример #14
0
func TestAuth(t *testing.T) {
	t.Parallel()

	r := &Remember{authboss.New()}
	storer := mocks.NewMockStorer()
	r.Storer = storer

	cookies := mocks.NewMockClientStorer()
	session := mocks.NewMockClientStorer()
	ctx := r.NewContext()
	ctx.CookieStorer = cookies
	ctx.SessionStorer = session

	key := "tester"
	_, err := r.new(cookies, key)
	if err != nil {
		t.Error("Unexpected error:", err)
	}

	cookie, _ := cookies.Get(authboss.CookieRemember)

	interrupt, err := r.auth(ctx)
	if err != nil {
		t.Error("Unexpected error:", err)
	}

	if session.Values[authboss.SessionHalfAuthKey] != "true" {
		t.Error("The user should have been half-authed.")
	}

	if session.Values[authboss.SessionKey] != key {
		t.Error("The user should have been logged in.")
	}

	if chocolateChip, _ := cookies.Get(authboss.CookieRemember); chocolateChip == cookie {
		t.Error("Expected cookie to be different")
	}

	if authboss.InterruptNone != interrupt {
		t.Error("Keys should have matched:", interrupt)
	}
}
Пример #15
0
func testSetup() (a *Auth, s *mocks.MockStorer) {
	s = mocks.NewMockStorer()

	ab := authboss.New()
	ab.LogWriter = ioutil.Discard
	ab.Layout = template.Must(template.New("").Parse(`{{template "authboss" .}}`))
	ab.Storer = s
	ab.XSRFName = "xsrf"
	ab.XSRFMaker = func(_ http.ResponseWriter, _ *http.Request) string {
		return "xsrfvalue"
	}
	ab.PrimaryID = authboss.StoreUsername

	a = &Auth{}
	if err := a.Initialize(ab); err != nil {
		panic(err)
	}

	return a, s
}
Пример #16
0
func TestRegister(t *testing.T) {
	ab := authboss.New()
	ab.Storer = mocks.NewMockStorer()
	r := Register{}
	if err := r.Initialize(ab); err != nil {
		t.Error(err)
	}

	if r.Routes()["/register"] == nil {
		t.Error("Expected a register handler at /register.")
	}

	sto := r.Storage()
	if sto[r.PrimaryID] != authboss.String {
		t.Error("Wanted primary ID to be a string.")
	}
	if sto[authboss.StorePassword] != authboss.String {
		t.Error("Wanted password to be a string.")
	}
}
Пример #17
0
func testSetup() (r *Recover, s *mocks.MockStorer, l *bytes.Buffer) {
	s = mocks.NewMockStorer()
	l = &bytes.Buffer{}

	ab := authboss.New()
	ab.Layout = template.Must(template.New("").Parse(`{{template "authboss" .}}`))
	ab.LayoutHTMLEmail = template.Must(template.New("").Parse(`<strong>{{template "authboss" .}}</strong>`))
	ab.LayoutTextEmail = template.Must(template.New("").Parse(`{{template "authboss" .}}`))
	ab.Storer = s
	ab.XSRFName = "xsrf"
	ab.XSRFMaker = func(_ http.ResponseWriter, _ *http.Request) string {
		return "xsrfvalue"
	}
	ab.PrimaryID = authboss.StoreUsername
	ab.LogWriter = l

	ab.Policies = []authboss.Validator{
		authboss.Rules{
			FieldName:       "username",
			Required:        true,
			MinLength:       2,
			MaxLength:       4,
			AllowWhitespace: false,
		},
		authboss.Rules{
			FieldName:       "password",
			Required:        true,
			MinLength:       4,
			MaxLength:       8,
			AllowWhitespace: false,
		},
	}

	r = &Recover{}
	if err := r.Initialize(ab); err != nil {
		panic(err)
	}

	return r, s, l
}
Пример #18
0
func TestInitialize(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	r := &Remember{}
	err := r.Initialize(ab)
	if err == nil {
		t.Error("Expected error about token storers.")
	}

	ab.Storer = mocks.MockFailStorer{}
	err = r.Initialize(ab)
	if err == nil {
		t.Error("Expected error about token storers.")
	}

	ab.Storer = mocks.NewMockStorer()
	err = r.Initialize(ab)
	if err != nil {
		t.Error("Unexpected error:", err)
	}
}
Пример #19
0
func TestLock(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	storer := mocks.NewMockStorer()
	ab.Storer = storer
	lock := Lock{ab}

	email := "*****@*****.**"
	storer.Users[email] = map[string]interface{}{
		ab.PrimaryID: email,
		"password":   "******",
	}

	err := lock.Lock(email)
	if err != nil {
		t.Error(err)
	}

	if locked := storer.Users[email][StoreLocked].(time.Time); !locked.After(time.Now()) {
		t.Error("User should be locked.")
	}
}
Пример #20
0
func TestAfterOAuth(t *testing.T) {
	t.Parallel()

	r := Remember{authboss.New()}
	storer := mocks.NewMockStorer()
	r.Storer = storer

	cookies := mocks.NewMockClientStorer()
	session := mocks.NewMockClientStorer(authboss.SessionOAuth2Params, `{"rm":"true"}`)

	uri := fmt.Sprintf("%s?state=%s", "localhost/oauthed", "xsrf")
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		t.Error("Unexpected Error:", err)
	}

	ctx, err := r.ContextFromRequest(req)
	if err != nil {
		t.Error("Unexpected error:", err)
	}

	ctx.SessionStorer = session
	ctx.CookieStorer = cookies
	ctx.User = authboss.Attributes{
		authboss.StoreOAuth2UID:      "uid",
		authboss.StoreOAuth2Provider: "google",
	}

	if err := r.afterOAuth(ctx); err != nil {
		t.Error(err)
	}

	if _, ok := cookies.Values[authboss.CookieRemember]; !ok {
		t.Error("Expected a cookie to have been set.")
	}
}
Пример #21
0
func TestOAuthSuccess(t *testing.T) {
	t.Parallel()

	ab := authboss.New()
	oauth := OAuth2{ab}

	expiry := time.Now().UTC().Add(3600 * time.Second)
	fakeToken := &oauth2.Token{
		AccessToken:  "token",
		TokenType:    "Bearer",
		RefreshToken: "refresh",
		Expiry:       expiry,
	}

	fakeCallback := func(_ oauth2.Config, _ *oauth2.Token) (authboss.Attributes, error) {
		return authboss.Attributes{
			authboss.StoreOAuth2UID: "uid",
			authboss.StoreEmail:     "email",
		}, nil
	}

	saveExchange := exchanger
	defer func() {
		exchanger = saveExchange
	}()
	exchanger = func(_ *oauth2.Config, _ context.Context, _ string) (*oauth2.Token, error) {
		return fakeToken, nil
	}

	ab.OAuth2Providers = map[string]authboss.OAuth2Provider{
		"fake": authboss.OAuth2Provider{
			OAuth2Config: &oauth2.Config{
				ClientID:     `jazz`,
				ClientSecret: `hands`,
				Scopes:       []string{`profile`, `email`},
				Endpoint: oauth2.Endpoint{
					AuthURL:  "fakeauth",
					TokenURL: "faketoken",
				},
			},
			Callback:         fakeCallback,
			AdditionalParams: url.Values{"include_requested_scopes": []string{"true"}},
		},
	}

	values := make(url.Values)
	values.Set("code", "code")
	values.Set("state", "state")

	url := fmt.Sprintf("/oauth2/fake?%s", values.Encode())
	r, _ := http.NewRequest("GET", url, nil)
	w := httptest.NewRecorder()
	ctx := ab.NewContext()
	session := mocks.NewMockClientStorer()
	session.Put(authboss.SessionOAuth2State, authboss.FormValueOAuth2State)
	session.Put(authboss.SessionOAuth2Params, `{"redir":"/myurl?myparam=5","rm":"true"}`)

	storer := mocks.NewMockStorer()
	ctx.SessionStorer = session
	ab.OAuth2Storer = storer
	ab.AuthLoginOKPath = "/fakeloginok"

	if err := oauth.oauthCallback(ctx, w, r); err != nil {
		t.Error(err)
	}

	key := "uidfake"
	user, ok := storer.Users[key]
	if !ok {
		t.Error("Couldn't find user.")
	}

	if val, _ := user.String(authboss.StoreEmail); val != "email" {
		t.Error("Email was wrong:", val)
	}
	if val, _ := user.String(authboss.StoreOAuth2Token); val != "token" {
		t.Error("Token was wrong:", val)
	}
	if val, _ := user.String(authboss.StoreOAuth2Refresh); val != "refresh" {
		t.Error("Refresh was wrong:", val)
	}
	if val, _ := user.DateTime(authboss.StoreOAuth2Expiry); !val.Equal(expiry) {
		t.Error("Expiry was wrong:", val)
	}

	if val, _ := session.Get(authboss.SessionKey); val != "uid;fake" {
		t.Error("User was not logged in:", val)
	}
	if _, ok := session.Get(authboss.SessionOAuth2State); ok {
		t.Error("Expected state to be deleted.")
	}

	if w.Code != http.StatusFound {
		t.Error("It should redirect")
	} else if loc := w.Header().Get("Location"); loc != "/myurl?myparam=5" {
		t.Error("Redirect is wrong:", loc)
	}
}