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.") } }
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.") } }
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.") } }
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.") } }
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.") } }
func TestRegisterGet(t *testing.T) { reg := setup() w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/register", nil) ctx := reg.NewContext() ctx.SessionStorer = mocks.NewMockClientStorer() if err := reg.registerHandler(ctx, w, r); err != nil { t.Error(err) } if w.Code != http.StatusOK { t.Error("It should have written a 200:", w.Code) } if w.Body.Len() == 0 { t.Error("It should have wrote a response.") } if str := w.Body.String(); !strings.Contains(str, "<form") { t.Error("It should have rendered a nice form:", str) } else if !strings.Contains(str, `name="`+reg.PrimaryID) { t.Error("Form should contain the primary ID:", str) } }
func TestOAuthFailure(t *testing.T) { t.Parallel() ab := authboss.New() oauth := OAuth2{ab} ab.OAuth2Providers = testProviders values := url.Values{} values.Set("error", "something") values.Set("error_reason", "auth_failure") values.Set("error_description", "Failed to auth.") ctx := ab.NewContext() session := mocks.NewMockClientStorer() session.Put(authboss.SessionOAuth2State, authboss.FormValueOAuth2State) ctx.SessionStorer = session r, _ := http.NewRequest("GET", "/oauth2/google?"+values.Encode(), nil) err := oauth.oauthCallback(ctx, nil, r) if red, ok := err.(authboss.ErrAndRedirect); !ok { t.Error("Should be a redirect error") } else if len(red.FlashError) == 0 { t.Error("Should have a flash error.") } else if red.Err.Error() != "auth_failure" { t.Error("It should record the failure.") } }
func TestRedirect_Override(t *testing.T) { t.Parallel() ab := authboss.New() cookies := mocks.NewMockClientStorer() r, _ := http.NewRequest("GET", "http://localhost?redir=foo/bar", nil) w := httptest.NewRecorder() ctx, _ := ab.ContextFromRequest(r) ctx.SessionStorer = cookies Redirect(ctx, w, r, "/shouldNotGo", "success", "failure", true) if w.Code != http.StatusFound { t.Error("Expected a redirect.") } if w.Header().Get("Location") != "/foo/bar" { t.Error("Expected to be redirected to root.") } if val, _ := cookies.Get(authboss.FlashSuccessKey); val != "success" { t.Error("Flash success msg wrong:", val) } if val, _ := cookies.Get(authboss.FlashErrorKey); val != "failure" { t.Error("Flash failure msg wrong:", val) } }
func TestTemplates_Render(t *testing.T) { t.Parallel() cookies := mocks.NewMockClientStorer() ab := authboss.New() ab.LayoutDataMaker = func(_ http.ResponseWriter, _ *http.Request) authboss.HTMLData { return authboss.HTMLData{"fun": "is"} } ab.XSRFName = "do you think" ab.XSRFMaker = func(_ http.ResponseWriter, _ *http.Request) string { return "that's air you're breathing now?" } // Set up flashes cookies.Put(authboss.FlashSuccessKey, "no") cookies.Put(authboss.FlashErrorKey, "spoon") r, _ := http.NewRequest("GET", "http://localhost", nil) w := httptest.NewRecorder() ctx, _ := ab.ContextFromRequest(r) ctx.SessionStorer = cookies tpls := Templates{ "hello": testViewTemplate, } err := tpls.Render(ctx, w, r, "hello", authboss.HTMLData{"external": "there"}) if err != nil { t.Error(err) } if w.Body.String() != "there is no spoon do you think that's air you're breathing now?" { t.Error("Body was wrong:", w.Body.String()) } }
func testRequest(ab *authboss.Authboss, method string, postFormValues ...string) (*authboss.Context, *httptest.ResponseRecorder, *http.Request, authboss.ClientStorerErr) { sessionStorer := mocks.NewMockClientStorer() ctx := ab.NewContext() r := mocks.MockRequest(method, postFormValues...) ctx.SessionStorer = sessionStorer return ctx, httptest.NewRecorder(), r, sessionStorer }
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) } }
func TestLogout(t *testing.T) { t.Parallel() ab := authboss.New() oauth := OAuth2{ab} ab.AuthLogoutOKPath = "/dashboard" r, _ := http.NewRequest("GET", "/oauth2/google?", nil) w := httptest.NewRecorder() ctx := ab.NewContext() session := mocks.NewMockClientStorer(authboss.SessionKey, "asdf", authboss.SessionLastAction, "1234") cookies := mocks.NewMockClientStorer(authboss.CookieRemember, "qwert") ctx.SessionStorer = session ctx.CookieStorer = cookies if err := oauth.logout(ctx, w, r); err != nil { t.Error(err) } if val, ok := session.Get(authboss.SessionKey); ok { t.Error("Unexpected session key:", val) } if val, ok := session.Get(authboss.SessionLastAction); ok { t.Error("Unexpected last action:", val) } if val, ok := cookies.Get(authboss.CookieRemember); ok { t.Error("Unexpected rm cookie:", val) } if http.StatusFound != w.Code { t.Errorf("Expected status code %d, got %d", http.StatusFound, w.Code) } location := w.Header().Get("Location") if location != ab.AuthLogoutOKPath { t.Error("Redirect wrong:", location) } }
func testRequest(ab *authboss.Authboss, method string, postFormValues ...string) (*authboss.Context, *httptest.ResponseRecorder, *http.Request, authboss.ClientStorerErr) { r, err := http.NewRequest(method, "", nil) if err != nil { panic(err) } sessionStorer := mocks.NewMockClientStorer() ctx := mocks.MockRequestContext(ab, postFormValues...) ctx.SessionStorer = sessionStorer return ctx, httptest.NewRecorder(), r, sessionStorer }
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.") } }
func TestRegisterPostSuccess(t *testing.T) { reg := setup() reg.Policies = nil w := httptest.NewRecorder() vals := url.Values{} email := "*****@*****.**" vals.Set(reg.PrimaryID, email) vals.Set(authboss.StorePassword, "pass") vals.Set(authboss.ConfirmPrefix+authboss.StorePassword, "pass") r, _ := http.NewRequest("POST", "/register", bytes.NewBufferString(vals.Encode())) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") ctx := reg.NewContext() ctx.SessionStorer = mocks.NewMockClientStorer() if err := reg.registerHandler(ctx, w, r); err != nil { t.Error(err) } if w.Code != http.StatusFound { t.Error("It should have written a redirect:", w.Code) } if loc := w.Header().Get("Location"); loc != reg.RegisterOKPath { t.Error("Redirected to the wrong location", loc) } user, err := reg.Storer.Get(email) if err == authboss.ErrUserNotFound { t.Error("The user have been saved.") } attrs := authboss.Unbind(user) if e, err := attrs.StringErr(reg.PrimaryID); err != nil { t.Error(err) } else if e != email { t.Errorf("Email was not set properly, want: %s, got: %s", email, e) } if p, err := attrs.StringErr(authboss.StorePassword); err != nil { t.Error(err) } else if p == "pass" { t.Error("Password was not hashed.") } }
func TestAuth_loginHandlerFunc_POST(t *testing.T) { t.Parallel() a, storer := testSetup() storer.Users["john"] = authboss.Attributes{"password": "******"} ctx, w, r, _ := testRequest(a.Authboss, "POST", "username", "john", "password", "1234") cb := mocks.NewMockAfterCallback() a.Callbacks = authboss.NewCallbacks() a.Callbacks.After(authboss.EventAuth, cb.Fn) a.AuthLoginOKPath = "/dashboard" sessions := mocks.NewMockClientStorer() ctx.SessionStorer = sessions if err := a.loginHandlerFunc(ctx, w, r); err != nil { t.Error("Unexpected error:", err) } if _, ok := ctx.Values[authboss.CookieRemember]; !ok { t.Error("Authboss cookie remember should be set for the callback") } if !cb.HasBeenCalled { t.Error("Expected after callback to have been called") } if w.Code != http.StatusFound { t.Error("Unexpected status:", w.Code) } loc := w.Header().Get("Location") if loc != a.AuthLoginOKPath { t.Error("Unexpeced location:", loc) } val, ok := sessions.Values[authboss.SessionKey] if !ok { t.Error("Expected session to be set") } else if val != "john" { t.Error("Expected session value to be authed username") } }
func TestOAuth2Init(t *testing.T) { t.Parallel() ab := authboss.New() oauth := OAuth2{ab} session := mocks.NewMockClientStorer() ab.OAuth2Providers = testProviders r, _ := http.NewRequest("GET", "/oauth2/google?redir=/my/redirect%23lol&rm=true", nil) w := httptest.NewRecorder() ctx := ab.NewContext() ctx.SessionStorer = session oauth.oauthInit(ctx, w, r) if w.Code != http.StatusFound { t.Error("Code was wrong:", w.Code) } loc := w.Header().Get("Location") parsed, err := url.Parse(loc) if err != nil { t.Error(err) } if !strings.Contains(loc, google.Endpoint.AuthURL) { t.Error("Redirected to wrong url:", loc) } query := parsed.Query() if query["include_requested_scopes"][0] != "true" { t.Error("Missing extra parameters:", loc) } state := query[authboss.FormValueOAuth2State][0] if len(state) == 0 { t.Error("It should have had some state:", loc) } if params := session.Values[authboss.SessionOAuth2Params]; params != `{"redir":"/my/redirect#lol","rm":"true"}` { t.Error("The params were wrong:", params) } }
func TestAuth_logoutHandlerFunc_GET(t *testing.T) { t.Parallel() a, _ := testSetup() a.AuthLogoutOKPath = "/dashboard" ctx, w, r, sessionStorer := testRequest(a.Authboss, "GET") sessionStorer.Put(authboss.SessionKey, "asdf") sessionStorer.Put(authboss.SessionLastAction, "1234") cookieStorer := mocks.NewMockClientStorer(authboss.CookieRemember, "qwert") ctx.CookieStorer = cookieStorer if err := a.logoutHandlerFunc(ctx, w, r); err != nil { t.Error("Unexpected error:", err) } if val, ok := sessionStorer.Get(authboss.SessionKey); ok { t.Error("Unexpected session key:", val) } if val, ok := sessionStorer.Get(authboss.SessionLastAction); ok { t.Error("Unexpected last action:", val) } if val, ok := cookieStorer.Get(authboss.CookieRemember); ok { t.Error("Unexpected rm cookie:", val) } if http.StatusFound != w.Code { t.Errorf("Expected status code %d, got %d", http.StatusFound, w.Code) } location := w.Header().Get("Location") if location != "/dashboard" { t.Errorf("Expected lcoation %s, got %s", "/dashboard", location) } }
func TestRegisterPostValidationErrs(t *testing.T) { reg := setup() w := httptest.NewRecorder() vals := url.Values{} email := "*****@*****.**" vals.Set(reg.PrimaryID, email) vals.Set(authboss.StorePassword, "pass") vals.Set(authboss.ConfirmPrefix+authboss.StorePassword, "pass2") r, _ := http.NewRequest("POST", "/register", bytes.NewBufferString(vals.Encode())) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") ctx := reg.NewContext() ctx.SessionStorer = mocks.NewMockClientStorer() if err := reg.registerHandler(ctx, w, r); err != nil { t.Error(err) } if w.Code != http.StatusOK { t.Error("It should have written a 200:", w.Code) } if w.Body.Len() == 0 { t.Error("It should have wrote a response.") } if str := w.Body.String(); !strings.Contains(str, "Does not match password") { t.Error("Confirm password should have an error:", str) } if _, err := reg.Storer.Get(email); err != authboss.ErrUserNotFound { t.Error("The user should not have been saved.") } }
func TestOAuthXSRFFailure(t *testing.T) { t.Parallel() ab := authboss.New() oauth := OAuth2{ab} session := mocks.NewMockClientStorer() session.Put(authboss.SessionOAuth2State, authboss.FormValueOAuth2State) ab.OAuth2Providers = testProviders values := url.Values{} values.Set(authboss.FormValueOAuth2State, "notstate") values.Set("code", "code") ctx := ab.NewContext() ctx.SessionStorer = session r, _ := http.NewRequest("GET", "/oauth2/google?"+values.Encode(), nil) err := oauth.oauthCallback(ctx, nil, r) if err != errOAuthStateValidation { t.Error("Should have gotten an error about state validation:", err) } }
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) } }