-
-
Notifications
You must be signed in to change notification settings - Fork 961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: immutable sessions - change value using nonce #2761
Conversation
457c467
to
ee57c74
Compare
e8fd850
to
6a5cf7b
Compare
Codecov Report
@@ Coverage Diff @@
## master #2761 +/- ##
=======================================
Coverage 75.88% 75.88%
=======================================
Files 302 302
Lines 17806 17815 +9
=======================================
+ Hits 13512 13519 +7
- Misses 3258 3259 +1
- Partials 1036 1037 +1
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
06001d0
to
c954017
Compare
selfservice/flow/login/hook.go
Outdated
if err := e.d.SessionPersister().UpsertSession(r.Context(), s); err != nil { | ||
return errors.WithStack(err) | ||
// Update session identifiers when Re-Auth or session upgrade | ||
if a.Refresh || a.RequestedAAL > s.AuthenticatorAssuranceLevel { // TODO: Change to OR to allow block exec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about a helper func a.Equals(b)
selfservice/flow/login/hook.go
Outdated
|
||
s = ns | ||
|
||
if err := e.d.SessionManager().IssueCookie(r.Context(), w, r, s); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this re-issuing logic should be handled in issuecookie, and not it's consumers!
c954017
to
083d009
Compare
All you need to change - IMO - is the identifier which we use to look up the session. You don't need to actually create a new session, or revoke the old one. If the value of the cookie changes, or the session token value, we're good! |
For simplicity, I recommend first doing only the cookie stuff, as for the tokens we'll probably need a design first how refreshing would work there. |
a9867df
to
4240e69
Compare
d8bf375
to
5590341
Compare
selfservice/flow/login/hook.go
Outdated
var cookieModifiers []x.CookieModifier | ||
// Use nonce cookie modifier when Re-Auth or session upgrade and then issue cookie. | ||
// Using nonce modifies the cookie value without affecting the session attributes | ||
if a.Refresh || a.RequestedAAL > s.AuthenticatorAssuranceLevel { // TODO: Change to OR to allow block exec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this TODO? What speaks against using a new cookie identifier? Can we just use x.CookieValuesWithNonce()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO
comment wasn't cleaned up after I got it working. Considering - #2761 (comment), this if
seems unnecessary now. I'll remove it.
t.Run("type=api", func(t *testing.T) { | ||
user1 := testhelpers.NewHTTPClientWithArbitrarySessionToken(t, reg) | ||
_, body := initFlow(t, user1, true) | ||
var f kratos.SelfServiceSettingsFlow | ||
require.NoError(t, json.Unmarshal(body, &f)) | ||
|
||
actual, res := testhelpers.SettingsMakeRequest(t, true, false, &f, user1, `{"method":"profile", "numby": 15}`) | ||
assert.Equal(t, http.StatusOK, res.StatusCode) | ||
assert.Equal(t, "Your changes have been saved!", gjson.Get(actual, "ui.messages.0.text").String(), actual) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test isn't really doing anything new, maybe remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replaced with a test for spa
session/manager_http.go
Outdated
|
||
for _, mod := range cookieModifiers { | ||
mod(cookie) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this and just set the nonce at all times. We want immutable cookies always, not just sometimes. And it makes testing easier :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
session/manager_http.go
Outdated
@@ -49,12 +49,12 @@ func NewManagerHTTP(r managerHTTPDependencies) *ManagerHTTP { | |||
} | |||
} | |||
|
|||
func (s *ManagerHTTP) UpsertAndIssueCookie(ctx context.Context, w http.ResponseWriter, r *http.Request, ss *Session) error { | |||
func (s *ManagerHTTP) UpsertAndIssueCookie(ctx context.Context, w http.ResponseWriter, r *http.Request, ss *Session, cookieModifiers ...x.CookieModifier) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the nonce is optional (passed as an argument), there are a couple of places where UpsertAndIssueCookie
/ IssueCookie
are being called. There, the cookie would probably not be changed because the nonce is missing. Therefore, remove this parameter and just always set the nonce!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropped parameter
session/manager.go
Outdated
UpsertAndIssueCookie(context.Context, http.ResponseWriter, *http.Request, *Session, ...x.CookieModifier) error | ||
|
||
// IssueCookie issues a cookie for the given session. | ||
// | ||
// Also regenerates CSRF tokens due to assumed principal change. | ||
IssueCookie(context.Context, http.ResponseWriter, *http.Request, *Session) error | ||
IssueCookie(context.Context, http.ResponseWriter, *http.Request, *Session, ...x.CookieModifier) error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check all places where these two functions are being used and interpret whether they issue a new cookie with a new nonce or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 usages of Upsert and Issue -> all perform prior activation of session (followed by addition of nonce) which results in a new kratos session (Login, Code and Link recovery).
3 usages of Issue -> nonce addition to the values map results in a new kratos session (PostSettingsHook, Post Registration, Refresh cookie)
c2aac54
to
05ccad4
Compare
eea3255
to
16f2229
Compare
16f2229
to
f6bc54a
Compare
Quite a bit of timeouts in the E2E stages -
This is unrelated to the change here. I couldn't yet find the cause of this. @aeneasr |
It's not very likely that the timeouts are unrelated. Those typically happen if the server is unable to start and points to compile, run, or config issues! It could be related to the build failing because of a timeout but I did not check the logs. Let's see :) |
Changes -
Related issue(s)
#2701
Checklist
introduces a new feature.
contributing code guidelines.
vulnerability. If this pull request addresses a security vulnerability, I
confirm that I got the approval (please contact
security@ory.sh) from the maintainers to push
the changes.
works.
Further Comments