diff --git a/introspection_response_writer.go b/introspection_response_writer.go index fdc8b2b69..4eefc4405 100644 --- a/introspection_response_writer.go +++ b/introspection_response_writer.go @@ -202,6 +202,11 @@ func (f *Fosite) WriteIntrospectionResponse(rw http.ResponseWriter, r Introspect return } + expiresAt := int64(0) + if !r.GetAccessRequester().GetSession().GetExpiresAt(AccessToken).IsZero() { + expiresAt = r.GetAccessRequester().GetSession().GetExpiresAt(AccessToken).Unix() + } + rw.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(rw).Encode(struct { Active bool `json:"active"` @@ -218,7 +223,7 @@ func (f *Fosite) WriteIntrospectionResponse(rw http.ResponseWriter, r Introspect Active: true, ClientID: r.GetAccessRequester().GetClient().GetID(), Scope: strings.Join(r.GetAccessRequester().GetGrantedScopes(), " "), - ExpiresAt: r.GetAccessRequester().GetSession().GetExpiresAt(AccessToken).Unix(), + ExpiresAt: expiresAt, IssuedAt: r.GetAccessRequester().GetRequestedAt().Unix(), Subject: r.GetAccessRequester().GetSession().GetSubject(), Audience: r.GetAccessRequester().GetGrantedAudience(), diff --git a/introspection_response_writer_test.go b/introspection_response_writer_test.go index b9062814a..fd3f34ae8 100644 --- a/introspection_response_writer_test.go +++ b/introspection_response_writer_test.go @@ -22,11 +22,16 @@ package fosite_test import ( + "encoding/json" "net/http" + "net/http/httptest" "testing" + "time" "github.com/golang/mock/gomock" "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" . "github.com/ory/fosite" "github.com/ory/fosite/internal" @@ -61,3 +66,74 @@ func TestWriteIntrospectionResponse(t *testing.T) { AccessRequester: NewAccessRequest(nil), }) } + +func TestWriteIntrospectionResponseBody(t *testing.T) { + f := new(Fosite) + ires := &IntrospectionResponse{} + rw := httptest.NewRecorder() + + for _, c := range []struct { + description string + setup func() + active bool + hasExp bool + }{ + { + description: "should success for not expired access token", + setup: func() { + ires.Active = true + ires.TokenType = AccessToken + sess := &DefaultSession{} + sess.SetExpiresAt(ires.TokenType, time.Now().Add(time.Hour*2)) + ires.AccessRequester = NewAccessRequest(sess) + }, + active: true, + hasExp: true, + }, + { + description: "should success for expired access token", + setup: func() { + ires.Active = false + ires.TokenType = AccessToken + sess := &DefaultSession{} + sess.SetExpiresAt(ires.TokenType, time.Now().Add(-time.Hour*2)) + ires.AccessRequester = NewAccessRequest(sess) + }, + active: false, + hasExp: false, + }, + { + description: "should success for ExpiresAt not set access token", + setup: func() { + ires.Active = true + ires.TokenType = AccessToken + sess := &DefaultSession{} + sess.SetExpiresAt(ires.TokenType, time.Time{}) + ires.AccessRequester = NewAccessRequest(sess) + }, + active: true, + hasExp: false, + }, + } { + t.Run(c.description, func(t *testing.T) { + c.setup() + f.WriteIntrospectionResponse(rw, ires) + var params struct { + Active bool `json:"active"` + Exp *int64 `json:"exp"` + Iat *int64 `json:"iat"` + } + err := json.NewDecoder(rw.Body).Decode(¶ms) + require.NoError(t, err) + assert.Equal(t, c.active, params.Active) + if c.active { + assert.NotNil(t, params.Iat) + if c.hasExp { + assert.NotNil(t, params.Exp) + } else { + assert.Nil(t, params.Exp) + } + } + }) + } +}