Skip to content

Commit

Permalink
feat: option to update session cookie expiry time on session refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
aarmam committed Nov 4, 2022
1 parent 8d92030 commit 8f1b39c
Show file tree
Hide file tree
Showing 32 changed files with 181 additions and 1 deletion.
2 changes: 1 addition & 1 deletion consent/strategy_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ func (s *DefaultStrategy) verifyAuthentication(w http.ResponseWriter, r *http.Re
}
}

if !session.Remember || session.LoginRequest.Skip {
if !session.Remember || session.LoginRequest.Skip && !session.RefreshRememberFor {
// If the user doesn't want to remember the session, we do not store a cookie.
// If login was skipped, it means an authentication cookie was present and
// we don't want to touch it (in order to preserve its original expiry date)
Expand Down
96 changes: 96 additions & 0 deletions consent/strategy_oauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,102 @@ func TestStrategyLoginConsentNext(t *testing.T) {
})
})

t.Run("case=should pass if both login and consent are granted and check remember flows with refresh session cookie", func(t *testing.T) {

subject := "subject-1"
c := createDefaultClient(t)
testhelpers.NewLoginConsentUI(t, reg.Config(),
acceptLoginHandler(t, subject, &hydra.AcceptOAuth2LoginRequest{
Remember: pointerx.Bool(true),
}),
acceptConsentHandler(t, &hydra.AcceptOAuth2ConsentRequest{
Remember: pointerx.Bool(true),
GrantScope: []string{"openid"},
Session: &hydra.AcceptOAuth2ConsentRequestSession{
AccessToken: map[string]interface{}{"foo": "bar"},
IdToken: map[string]interface{}{"bar": "baz"},
},
}))

hc := testhelpers.NewEmptyJarClient(t)

followUpHandler := func(refreshRememberFor bool) {
rememberFor := int64(12345)
testhelpers.NewLoginConsentUI(t, reg.Config(),
checkAndAcceptLoginHandler(t, adminClient, subject, func(t *testing.T, res *hydra.OAuth2LoginRequest, err error) hydra.AcceptOAuth2LoginRequest {
require.NoError(t, err)
assert.True(t, res.Skip)
assert.Equal(t, subject, res.Subject)
assert.Empty(t, res.Client.ClientSecret)
return hydra.AcceptOAuth2LoginRequest{
Subject: subject,
Remember: pointerx.Bool(true),
RememberFor: pointerx.Int64(rememberFor),
RefreshRememberFor: pointerx.Bool(refreshRememberFor),
Context: map[string]interface{}{"foo": "bar"},
}
}),
checkAndAcceptConsentHandler(t, adminClient, func(t *testing.T, res *hydra.OAuth2ConsentRequest, err error) hydra.AcceptOAuth2ConsentRequest {
require.NoError(t, err)
assert.True(t, *res.Skip)
assert.Equal(t, subject, res.Subject)
assert.Empty(t, res.Client.ClientSecret)
return hydra.AcceptOAuth2ConsentRequest{
Remember: pointerx.Bool(true),
GrantScope: []string{"openid"},
Session: &hydra.AcceptOAuth2ConsentRequestSession{
AccessToken: map[string]interface{}{"foo": "bar"},
IdToken: map[string]interface{}{"bar": "baz"},
},
}
}))

hc := &http.Client{
Jar: hc.Jar,
Transport: &http.Transport{},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}

_, oauthRes := makeOAuth2Request(t, reg, hc, c, url.Values{"redirect_uri": {c.RedirectURIs[0]}, "scope": {"openid"}})
assert.EqualValues(t, http.StatusFound, oauthRes.StatusCode)
loginChallengeRedirect, err := oauthRes.Location()
require.NoError(t, err)
defer oauthRes.Body.Close()

loginChallengeRes, err := hc.Get(loginChallengeRedirect.String())
require.NoError(t, err)
defer loginChallengeRes.Body.Close()
loginVerifierRedirect, err := loginChallengeRes.Location()

loginVerifierRes, err := hc.Get(loginVerifierRedirect.String())
require.NoError(t, err)
defer loginVerifierRes.Body.Close()

setCookieHeader := loginVerifierRes.Header.Get("set-cookie")
assert.NotNil(t, setCookieHeader)
if refreshRememberFor {
assert.Regexp(t, fmt.Sprintf("ory_hydra_session_dev=.*; Path=/; Expires=.*Max-Age=%d; HttpOnly; SameSite=Lax", rememberFor), setCookieHeader)
} else {
assert.NotContains(t, setCookieHeader, "ory_hydra_session_dev")
}
}

t.Run("perform first flow", func(t *testing.T) {
makeRequestAndExpectCode(t, hc, c, url.Values{"redirect_uri": {c.RedirectURIs[0]},
"scope": {"openid"}})
})

t.Run("perform follow up flow with refresh_remember_for=false", func(t *testing.T) {
followUpHandler(false)
})

t.Run("perform follow up flow with refresh_remember_for=true", func(t *testing.T) {
followUpHandler(true)
})
})

t.Run("case=should pass and check if login context is set properly", func(t *testing.T) {
// This should pass because login was remembered and session id should be set and session context should also work
subject := "aeneas-rekkas"
Expand Down
4 changes: 4 additions & 0 deletions consent/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ type HandledLoginRequest struct {
// authorization will be remembered for the duration of the browser session (using a session cookie).
RememberFor int `json:"remember_for"`

// RefreshRememberFor, if set to true, session cookie expiry time will be updated when session is
// refreshed (login skip=true).
RefreshRememberFor bool `json:"refresh_remember_for"`

// ACR sets the Authentication AuthorizationContext Class Reference value for this authentication session. You can use it
// to express that, for example, a user authenticated using two factor authentication.
ACR string `json:"acr"`
Expand Down
6 changes: 6 additions & 0 deletions flow/flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ type Flow struct {
// authorization will be remembered for the duration of the browser session (using a session cookie).
LoginRememberFor int `db:"login_remember_for"`

// LoginRefreshRememberFor, if set to true, session cookie expiry time will be updated when session is
// refreshed (login skip=true).
LoginRefreshRememberFor bool `db:"login_refresh_remember_for"`

// ACR sets the Authentication AuthorizationContext Class Reference value for this authentication session. You can use it
// to express that, for example, a user authenticated using two factor authentication.
ACR string `db:"acr"`
Expand Down Expand Up @@ -288,6 +292,7 @@ func (f *Flow) HandleLoginRequest(h *consent.HandledLoginRequest) error {

f.LoginRemember = h.Remember
f.LoginRememberFor = h.RememberFor
f.LoginRefreshRememberFor = h.RefreshRememberFor
f.ACR = h.ACR
f.AMR = h.AMR
f.Context = h.Context
Expand All @@ -301,6 +306,7 @@ func (f *Flow) GetHandledLoginRequest() consent.HandledLoginRequest {
ID: f.ID,
Remember: f.LoginRemember,
RememberFor: f.LoginRememberFor,
RefreshRememberFor: f.LoginRefreshRememberFor,
ACR: f.ACR,
AMR: f.AMR,
Subject: f.Subject,
Expand Down
1 change: 1 addition & 0 deletions flow/flow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (f *Flow) setHandledLoginRequest(r *consent.HandledLoginRequest) {
f.ID = r.ID
f.LoginRemember = r.Remember
f.LoginRememberFor = r.RememberFor
f.LoginRefreshRememberFor = r.RefreshRememberFor
f.ACR = r.ACR
f.AMR = r.AMR
f.Subject = r.Subject
Expand Down
5 changes: 5 additions & 0 deletions internal/httpclient/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1870,6 +1870,11 @@ components:
\ the proper value, then authentication processes which have id_token_hint\
\ set might fail."
type: string
refresh_remember_for:
description: "RefreshRememberFor, if set to true, session cookie
expiry\
\ time will be updated when session is\nrefreshed (login skip=true)."
type: boolean
remember:
description: "Remember, if set to true, tells ORY Hydra to remember this\
\ user by telling the user agent (browser) to store\na cookie with authentication\
Expand Down
37 changes: 37 additions & 0 deletions internal/httpclient/model_accept_o_auth2_login_request.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 1,
"LoginRefreshRememberFor": false,
"ACR": "acr-0001",
"AMR": [],
"ForceSubjectIdentifier": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 2,
"LoginRefreshRememberFor": false,
"ACR": "acr-0002",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0002",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 3,
"LoginRefreshRememberFor": false,
"ACR": "acr-0003",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0003",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 4,
"LoginRefreshRememberFor": false,
"ACR": "acr-0004",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0004",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 5,
"LoginRefreshRememberFor": false,
"ACR": "acr-0005",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0005",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 6,
"LoginRefreshRememberFor": false,
"ACR": "acr-0006",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0006",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 7,
"LoginRefreshRememberFor": false,
"ACR": "acr-0007",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0007",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 8,
"LoginRefreshRememberFor": false,
"ACR": "acr-0008",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0008",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 9,
"LoginRefreshRememberFor": false,
"ACR": "acr-0009",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0009",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 10,
"LoginRefreshRememberFor": false,
"ACR": "acr-0010",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0010",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 11,
"LoginRefreshRememberFor": false,
"ACR": "acr-0011",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0011",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 12,
"LoginRefreshRememberFor": false,
"ACR": "acr-0012",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0012",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 13,
"LoginRefreshRememberFor": false,
"ACR": "acr-0013",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0013",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 14,
"LoginRefreshRememberFor": false,
"ACR": "acr-0014",
"AMR": [],
"ForceSubjectIdentifier": "force_subject_id-0014",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"State": 128,
"LoginRemember": true,
"LoginRememberFor": 15,
"LoginRefreshRememberFor": false,
"ACR": "acr-0015",
"AMR": [
"amr-0015-1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow DROP COLUMN login_refresh_remember_for;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow ADD login_refresh_remember_for BOOLEAN NOT NULL DEFAULT FALSE;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow DROP COLUMN login_refresh_remember_for;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow ADD COLUMN login_refresh_remember_for BOOLEAN NOT NULL DEFAULT FALSE;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow DROP COLUMN login_refresh_remember_for;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow ADD login_refresh_remember_for BOOLEAN NOT NULL DEFAULT FALSE;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow DROP COLUMN login_refresh_remember_for;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE hydra_oauth2_flow ADD login_refresh_remember_for BOOLEAN NOT NULL DEFAULT FALSE;
4 changes: 4 additions & 0 deletions spec/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@
"description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.",
"type": "string"
},
"refresh_remember_for": {
"description": "RefreshRememberFor, if set to true, session cookie expiry time will be updated when session is\nrefreshed (login skip=true).",
"type": "boolean"
},
"remember": {
"description": "Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store\na cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she\nwill not be asked to log in again.",
"type": "boolean"
Expand Down
4 changes: 4 additions & 0 deletions spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,10 @@
"description": "ForceSubjectIdentifier forces the \"pairwise\" user ID of the end-user that authenticated. The \"pairwise\" user ID refers to the\n(Pairwise Identifier Algorithm)[http://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg] of the OpenID\nConnect specification. It allows you to set an obfuscated subject (\"user\") identifier that is unique to the client.\n\nPlease note that this changes the user ID on endpoint /userinfo and sub claim of the ID Token. It does not change the\nsub claim in the OAuth 2.0 Introspection.\n\nPer default, ORY Hydra handles this value with its own algorithm. In case you want to set this yourself\nyou can use this field. Please note that setting this field has no effect if `pairwise` is not configured in\nORY Hydra or the OAuth 2.0 Client does not expect a pairwise identifier (set via `subject_type` key in the client's\nconfiguration).\n\nPlease also be aware that ORY Hydra is unable to properly compute this value during authentication. This implies\nthat you have to compute this value on every authentication process (probably depending on the client ID or some\nother unique value).\n\nIf you fail to compute the proper value, then authentication processes which have id_token_hint set might fail.",
"type": "string"
},
"refresh_remember_for": {
"description": "RefreshRememberFor, if set to true, session cookie expiry time will be updated when session is\nrefreshed (login skip=true).",
"type": "boolean"
},
"remember": {
"description": "Remember, if set to true, tells ORY Hydra to remember this user by telling the user agent (browser) to store\na cookie with authentication data. If the same user performs another OAuth 2.0 Authorization Request, he/she\nwill not be asked to log in again.",
"type": "boolean"
Expand Down

0 comments on commit 8f1b39c

Please sign in to comment.