diff --git a/auth/auth.go b/auth/auth.go index 5a4d24d..a4d1207 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -87,6 +87,8 @@ func (a *Auth) LoginPost(w http.ResponseWriter, r *http.Request) error { return a.Authboss.Core.Responder.Respond(w, r, http.StatusOK, PageLogin, data) } + r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyValues, validatable)) + handled, err = a.Events.FireBefore(authboss.EventAuth, w, r) if err != nil { return err diff --git a/auth/auth_test.go b/auth/auth_test.go index 78cab58..133e8dd 100644 --- a/auth/auth_test.go +++ b/auth/auth_test.go @@ -114,12 +114,15 @@ func TestAuthPostSuccess(t *testing.T) { h := setupMore(testSetup()) var beforeCalled, afterCalled bool + var beforeHasValues, afterHasValues bool h.ab.Events.Before(authboss.EventAuth, func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error) { beforeCalled = true + beforeHasValues = r.Context().Value(authboss.CTXKeyValues) != nil return false, nil }) h.ab.Events.After(authboss.EventAuth, func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error) { afterCalled = true + afterHasValues = r.Context().Value(authboss.CTXKeyValues) != nil return false, nil }) @@ -151,6 +154,12 @@ func TestAuthPostSuccess(t *testing.T) { if !afterCalled { t.Error("after should have been called") } + if !beforeHasValues { + t.Error("before callback should have access to values") + } + if !afterHasValues { + t.Error("after callback should have access to values") + } }) t.Run("handledBefore", func(t *testing.T) { diff --git a/context.go b/context.go index 5f32a4a..9d7b833 100644 --- a/context.go +++ b/context.go @@ -20,10 +20,11 @@ const ( // renderer CTXKeyData contextKey = "data" - // CTXKeyRM is used to flag the remember me module to actually do the - // remembering, since this is a per-user operation, authentication modules - // need to supply this key if they wish to allow users to be remembered. - CTXKeyRM contextKey = "rm" + // CTXKeyValues is to pass the data submitted from API request or form + // along in the context in case modules need it. The only module that needs + // user information currently is remember so only auth/oauth2 are currently + // going to use this. + CTXKeyValues contextKey = "values" ) func (c contextKey) String() string { diff --git a/internal/mocks/mocks.go b/internal/mocks/mocks.go index faf6dcd..0260f5b 100644 --- a/internal/mocks/mocks.go +++ b/internal/mocks/mocks.go @@ -421,6 +421,7 @@ type Values struct { PID string Password string Token string + Remember bool Errors []error } @@ -440,6 +441,12 @@ func (v Values) GetToken() string { return v.Token } +// GetShouldRemember gets the value that tells +// the remember module if it should remember the user +func (v Values) GetShouldRemember() bool { + return v.Remember +} + // Validate the values func (v Values) Validate() []error { return v.Errors diff --git a/remember/remember.go b/remember/remember.go index ea55643..ee7c1ae 100644 --- a/remember/remember.go +++ b/remember/remember.go @@ -44,10 +44,10 @@ func (r *Remember) Init(ab *authboss.Authboss) error { // RememberAfterAuth creates a remember token and saves it in the user's cookies. func (r *Remember) RememberAfterAuth(w http.ResponseWriter, req *http.Request, handled bool) (bool, error) { - rmIntf := req.Context().Value(authboss.CTXKeyRM) + rmIntf := req.Context().Value(authboss.CTXKeyValues) if rmIntf == nil { return false, nil - } else if rm, ok := rmIntf.(bool); ok && !rm { + } else if rm, ok := rmIntf.(authboss.RememberValuer); ok && !rm.GetShouldRemember() { return false, nil } diff --git a/remember/remember_test.go b/remember/remember_test.go index 81c06ac..85a7520 100644 --- a/remember/remember_test.go +++ b/remember/remember_test.go @@ -59,7 +59,7 @@ func TestRememberAfterAuth(t *testing.T) { user := &mocks.User{Email: "test@test.com"} r := mocks.Request("POST") - r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyRM, true)) + r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyValues, mocks.Values{Remember: true})) r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyUser, user)) rec := httptest.NewRecorder() w := h.ab.NewResponse(rec, r) @@ -101,7 +101,7 @@ func TestRememberAfterAuthSkip(t *testing.T) { t.Error("expected no tokens to be created") } - r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyRM, false)) + r = r.WithContext(context.WithValue(r.Context(), authboss.CTXKeyValues, mocks.Values{Remember: false})) if handled, err := h.remember.RememberAfterAuth(w, r, false); err != nil { t.Fatal(err) diff --git a/values.go b/values.go index 0c43f5a..b16768d 100644 --- a/values.go +++ b/values.go @@ -65,6 +65,17 @@ type RecoverEndValuer interface { GetToken() string } +// RememberValuer allows auth/oauth2 to pass along the remember +// bool from the user to the remember module unobtrusively. +type RememberValuer interface { + // Intentionally omitting validator + + // GetShouldRemember is the checkbox or what have you that + // tells the remember module if it should remember that user's + // authentication or not. + GetShouldRemember() bool +} + // ArbitraryValuer provides the "rest" of the fields // that aren't strictly needed for anything in particular, // address, secondary e-mail, etc.