diff --git a/HISTORY.md b/HISTORY.md index 20b732541..8738a8aaf 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -13,6 +13,7 @@ to your composer if you need token introspection. * Session refactor: * The HMACSessionContainer was removed and replaced by `fosite.Session` / `fosite.DefaultSession`. All sessions must now implement this signature. The new session interface allows for better expiration time handling. + * The OpenID `DefaultSession` signature changed as well, it is now implementing the `fosite.Session` interface ## 0.4.0 diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index 6f54d5fec..55546b9b0 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -103,7 +103,7 @@ func (c *AuthorizeExplicitGrantHandler) PopulateTokenEndpointResponse(ctx contex responder.SetAccessToken(access) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan)) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now())) responder.SetScopes(requester.GetGrantedScopes()) if refresh != "" { responder.SetExtra("refresh_token", refresh) diff --git a/handler/oauth2/flow_authorize_implicit.go b/handler/oauth2/flow_authorize_implicit.go index 3300cdd38..d602c8e08 100644 --- a/handler/oauth2/flow_authorize_implicit.go +++ b/handler/oauth2/flow_authorize_implicit.go @@ -65,7 +65,7 @@ func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context ar.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) resp.AddFragment("access_token", token) - resp.AddFragment("expires_in", strconv.FormatInt(int64(getExpiresIn(ar, fosite.AccessToken, c.AccessTokenLifespan)/time.Second), 10)) + resp.AddFragment("expires_in", strconv.FormatInt(int64(getExpiresIn(ar, fosite.AccessToken, c.AccessTokenLifespan, time.Now())/time.Second), 10)) resp.AddFragment("token_type", "bearer") resp.AddFragment("state", ar.GetState()) resp.AddFragment("scope", strings.Join(ar.GetGrantedScopes(), " ")) diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 3d3104c8e..d14376319 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -90,7 +90,7 @@ func (c *RefreshTokenGrantHandler) PopulateTokenEndpointResponse(ctx context.Con responder.SetAccessToken(accessToken) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan)) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now())) responder.SetScopes(requester.GetGrantedScopes()) responder.SetExtra("refresh_token", refreshToken) return nil diff --git a/handler/oauth2/helper.go b/handler/oauth2/helper.go index 2cf04fbee..e94e23fb1 100644 --- a/handler/oauth2/helper.go +++ b/handler/oauth2/helper.go @@ -24,14 +24,14 @@ func (h *HandleHelper) IssueAccessToken(ctx context.Context, req *http.Request, responder.SetAccessToken(token) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, h.AccessTokenLifespan)) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, h.AccessTokenLifespan, time.Now())) responder.SetScopes(requester.GetGrantedScopes()) return nil } -func getExpiresIn(r fosite.Requester, key fosite.TokenType, defaultLifespan time.Duration) time.Duration { +func getExpiresIn(r fosite.Requester, key fosite.TokenType, defaultLifespan time.Duration, now time.Time) time.Duration { if r.GetSession().GetExpiresAt(key).IsZero() { return defaultLifespan } - return time.Duration(r.GetSession().GetExpiresAt(key).UnixNano() - time.Now().UnixNano()) + return time.Duration(r.GetSession().GetExpiresAt(key).UnixNano() - now.UnixNano()) } diff --git a/handler/oauth2/helper_test.go b/handler/oauth2/helper_test.go index df1048f79..835fdf020 100644 --- a/handler/oauth2/helper_test.go +++ b/handler/oauth2/helper_test.go @@ -14,12 +14,13 @@ import ( ) func TestGetExpiresIn(t *testing.T) { + now := time.Now() r := fosite.NewAccessRequest(&fosite.DefaultSession{ ExpiresAt: map[fosite.TokenType]time.Time{ - fosite.AccessToken: time.Now().Add(time.Hour), + fosite.AccessToken: now.Add(time.Hour).Round(time.Minute), }, }) - assert.Equal(t, time.Hour, getExpiresIn(r, fosite.AccessToken, time.Millisecond)) + assert.Equal(t, time.Hour, getExpiresIn(r, fosite.AccessToken, time.Millisecond, now)) } func TestIssueAccessToken(t *testing.T) { diff --git a/handler/oauth2/strategy_jwt_session.go b/handler/oauth2/strategy_jwt_session.go index e2de3647b..ce485c268 100644 --- a/handler/oauth2/strategy_jwt_session.go +++ b/handler/oauth2/strategy_jwt_session.go @@ -3,6 +3,7 @@ package oauth2 import ( "github.com/ory-am/fosite" "github.com/ory-am/fosite/token/jwt" + "time" ) type JWTSessionContainer interface { @@ -19,7 +20,9 @@ type JWTSessionContainer interface { type JWTSession struct { JWTClaims *jwt.JWTClaims JWTHeader *jwt.Headers - *fosite.DefaultSession + ExpiresAt map[fosite.TokenType]time.Time + Username string + Subject string } func (j *JWTSession) GetJWTClaims() *jwt.JWTClaims { @@ -35,3 +38,36 @@ func (j *JWTSession) GetJWTHeader() *jwt.Headers { } return j.JWTHeader } + +func (s *JWTSession) SetExpiresAt(key fosite.TokenType, exp time.Time) { + if s.ExpiresAt == nil { + s.ExpiresAt = make(map[fosite.TokenType]time.Time) + } + s.ExpiresAt[key] = exp +} + +func (s *JWTSession) GetExpiresAt(key fosite.TokenType) time.Time { + if s.ExpiresAt == nil { + s.ExpiresAt = make(map[fosite.TokenType]time.Time) + } + + if _, ok := s.ExpiresAt[key]; !ok { + return time.Time{} + } + return s.ExpiresAt[key] +} + +func (s *JWTSession) GetUsername() string { + if s == nil { + return "" + } + return s.Username +} + +func (s *JWTSession) GetSubject() string { + if s == nil { + return "" + } + + return s.Subject +}