internal/testhelpers/janitor_test_helper.go
// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package testhelpers
import (
"context"
"fmt"
"net/url"
"testing"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/ory/fosite"
"github.com/ory/fosite/handler/openid"
"github.com/ory/hydra/v2/client"
"github.com/ory/hydra/v2/consent"
"github.com/ory/hydra/v2/driver"
"github.com/ory/hydra/v2/driver/config"
"github.com/ory/hydra/v2/flow"
"github.com/ory/hydra/v2/internal"
"github.com/ory/hydra/v2/oauth2"
"github.com/ory/hydra/v2/oauth2/trust"
"github.com/ory/hydra/v2/x"
"github.com/ory/x/contextx"
"github.com/ory/x/logrusx"
"github.com/ory/x/sqlxx"
)
type JanitorConsentTestHelper struct {
uniqueName string
flushLoginRequests []*flow.LoginRequest
flushConsentRequests []*flow.OAuth2ConsentRequest
flushAccessRequests []*fosite.Request
flushRefreshRequests []*fosite.AccessRequest
flushGrants []*createGrantRequest
conf *config.DefaultProvider
Lifespan time.Duration
}
type createGrantRequest struct {
grant trust.Grant
pk jose.JSONWebKey
}
const lifespan = time.Hour
func NewConsentJanitorTestHelper(uniqueName string) *JanitorConsentTestHelper {
conf := internal.NewConfigurationWithDefaults()
conf.MustSet(context.Background(), config.KeyScopeStrategy, "DEPRECATED_HIERARCHICAL_SCOPE_STRATEGY")
conf.MustSet(context.Background(), config.KeyIssuerURL, "http://hydra.localhost")
conf.MustSet(context.Background(), config.KeyAccessTokenLifespan, lifespan)
conf.MustSet(context.Background(), config.KeyRefreshTokenLifespan, lifespan)
conf.MustSet(context.Background(), config.KeyConsentRequestMaxAge, lifespan)
conf.MustSet(context.Background(), config.KeyLogLevel, "trace")
return &JanitorConsentTestHelper{
uniqueName: uniqueName,
conf: conf,
flushLoginRequests: genLoginRequests(uniqueName, lifespan),
flushConsentRequests: genConsentRequests(uniqueName, lifespan),
flushAccessRequests: getAccessRequests(uniqueName, lifespan),
flushRefreshRequests: getRefreshRequests(uniqueName, lifespan),
flushGrants: getGrantRequests(uniqueName, lifespan),
Lifespan: lifespan,
}
}
func (j *JanitorConsentTestHelper) GetDSN() string {
return j.conf.DSN()
}
func (j *JanitorConsentTestHelper) GetConfig() *config.DefaultProvider {
return j.conf
}
func (j *JanitorConsentTestHelper) GetNotAfterTestCycles() map[string]time.Duration {
return map[string]time.Duration{
"notAfter24h": j.Lifespan * 24,
"notAfter1h30m": j.Lifespan + time.Hour/2,
"notAfterNow": 0,
}
}
func (j *JanitorConsentTestHelper) GetRegistry(ctx context.Context, dbname string) (driver.Registry, error) {
j.conf.MustSet(ctx, config.KeyDSN, fmt.Sprintf("sqlite://file:%s?mode=memory&_fk=true&cache=shared", dbname))
return driver.NewRegistryFromDSN(ctx, j.conf, logrusx.New("test_hydra", "master"), false, true, &contextx.Default{})
}
func (j *JanitorConsentTestHelper) AccessTokenNotAfterSetup(ctx context.Context, cl client.Manager, store x.FositeStorer) func(t *testing.T) {
return func(t *testing.T) {
// Create access token clients and session
for _, r := range j.flushAccessRequests {
require.NoError(t, cl.CreateClient(ctx, r.Client.(*client.Client)))
require.NoError(t, store.CreateAccessTokenSession(ctx, r.ID, r))
}
}
}
func (j *JanitorConsentTestHelper) AccessTokenNotAfterValidate(ctx context.Context, notAfter time.Time, store x.FositeStorer) func(t *testing.T) {
return func(t *testing.T) {
var err error
ds := new(oauth2.Session)
accessTokenLifespan := time.Now().Round(time.Second).Add(-j.conf.GetAccessTokenLifespan(ctx))
for _, r := range j.flushAccessRequests {
t.Logf("access flush check: %s", r.ID)
_, err = store.GetAccessTokenSession(ctx, r.ID, ds)
if j.notAfterCheck(notAfter, accessTokenLifespan, r.RequestedAt) {
require.Error(t, err)
} else {
require.NoError(t, err)
}
}
}
}
func (j *JanitorConsentTestHelper) RefreshTokenNotAfterSetup(ctx context.Context, cl client.Manager, store x.FositeStorer) func(t *testing.T) {
return func(t *testing.T) {
// Create refresh token clients and session
for _, fr := range j.flushRefreshRequests {
require.NoError(t, cl.CreateClient(ctx, fr.Client.(*client.Client)))
require.NoError(t, store.CreateRefreshTokenSession(ctx, fr.ID, fr))
}
}
}
func (j *JanitorConsentTestHelper) RefreshTokenNotAfterValidate(ctx context.Context, notAfter time.Time, store x.FositeStorer) func(t *testing.T) {
return func(t *testing.T) {
var err error
ds := new(oauth2.Session)
refreshTokenLifespan := time.Now().Round(time.Second).Add(-j.conf.GetRefreshTokenLifespan(ctx))
for _, r := range j.flushRefreshRequests {
t.Logf("refresh flush check: %s", r.ID)
_, err = store.GetRefreshTokenSession(ctx, r.ID, ds)
if j.notAfterCheck(notAfter, refreshTokenLifespan, r.RequestedAt) {
require.Error(t, err)
} else {
require.NoError(t, err)
}
}
}
}
func (j *JanitorConsentTestHelper) GrantNotAfterSetup(ctx context.Context, gr trust.GrantManager) func(t *testing.T) {
return func(t *testing.T) {
for _, fg := range j.flushGrants {
require.NoError(t, gr.CreateGrant(ctx, fg.grant, fg.pk))
}
}
}
func (j *JanitorConsentTestHelper) GrantNotAfterValidate(ctx context.Context, notAfter time.Time, gr trust.GrantManager) func(t *testing.T) {
return func(t *testing.T) {
var err error
// flush won't delete grants that have not yet expired, so use now to check that
deleteUntil := time.Now().Round(time.Second)
if deleteUntil.After(notAfter) {
deleteUntil = notAfter
}
for _, r := range j.flushGrants {
t.Logf("grant flush check: %s", r.grant.Issuer)
_, err = gr.GetConcreteGrant(ctx, r.grant.ID)
if deleteUntil.After(r.grant.ExpiresAt) {
require.Error(t, err)
} else {
require.NoError(t, err)
}
}
}
}
func (j *JanitorConsentTestHelper) LoginRejectionSetup(ctx context.Context, reg interface {
consent.ManagerProvider
client.ManagerProvider
flow.CipherProvider
}) func(t *testing.T) {
cm := reg.ConsentManager()
cl := reg.ClientManager()
return func(t *testing.T) {
// Create login requests
for _, r := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, r.Client))
f, err := cm.CreateLoginRequest(ctx, r)
require.NoError(t, err)
f.RequestedAt = time.Now() // we won't handle expired flows
f.LoginAuthenticatedAt = r.AuthenticatedAt
challenge := x.Must(f.ToLoginChallenge(ctx, reg))
// Explicit rejection
if r.ID == j.flushLoginRequests[0].ID {
// accept this one
_, err = cm.HandleLoginRequest(ctx, f, challenge, consent.NewHandledLoginRequest(
r.ID, false, r.RequestedAt, r.AuthenticatedAt))
require.NoError(t, err)
continue
}
// reject flush-login-2 and 3
_, err = cm.HandleLoginRequest(ctx, f, challenge, consent.NewHandledLoginRequest(
r.ID, true, r.RequestedAt, r.AuthenticatedAt))
require.NoError(t, err)
}
}
}
func (j *JanitorConsentTestHelper) LoginRejectionValidate(ctx context.Context, cm consent.Manager) func(t *testing.T) {
return func(t *testing.T) {
// flush-login-2 and 3 should be cleared now
for _, r := range j.flushLoginRequests {
t.Logf("check login: %s", r.ID)
_, err := cm.GetLoginRequest(ctx, r.ID)
// Login requests should never be persisted.
require.Error(t, err)
}
}
}
func (j *JanitorConsentTestHelper) LimitSetup(ctx context.Context, reg interface {
consent.ManagerProvider
client.ManagerProvider
flow.CipherProvider
}) func(t *testing.T) {
cl := reg.ClientManager()
cm := reg.ConsentManager()
return func(t *testing.T) {
var (
err error
f *flow.Flow
)
// Create login requests
for _, r := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, r.Client))
f, err = cm.CreateLoginRequest(ctx, r)
require.NoError(t, err)
// Reject each request
f.RequestedAt = time.Now() // we won't handle expired flows
f.LoginAuthenticatedAt = r.AuthenticatedAt
challenge := x.Must(f.ToLoginChallenge(ctx, reg))
_, err = cm.HandleLoginRequest(ctx, f, challenge, consent.NewHandledLoginRequest(
r.ID, true, r.RequestedAt, r.AuthenticatedAt))
require.NoError(t, err)
}
}
}
func (j *JanitorConsentTestHelper) LimitValidate(ctx context.Context, cm consent.Manager) func(t *testing.T) {
return func(t *testing.T) {
// flush-login-2 and 3 should be cleared now
for _, r := range j.flushLoginRequests {
t.Logf("check login: %s", r.ID)
_, err := cm.GetLoginRequest(ctx, r.ID)
// No Requests should have been persisted.
require.Error(t, err)
}
}
}
func (j *JanitorConsentTestHelper) ConsentRejectionSetup(ctx context.Context, reg interface {
consent.ManagerProvider
client.ManagerProvider
flow.CipherProvider
}) func(t *testing.T) {
cl := reg.ClientManager()
cm := reg.ConsentManager()
return func(t *testing.T) {
var (
err error
f *flow.Flow
)
// Create login requests
for i, loginRequest := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, loginRequest.Client))
f, err = cm.CreateLoginRequest(ctx, loginRequest)
require.NoError(t, err)
// Create consent requests
consentRequest := j.flushConsentRequests[i]
err = cm.CreateConsentRequest(ctx, f, consentRequest)
require.NoError(t, err)
f.RequestedAt = time.Now() // we won't handle expired flows
f.LoginAuthenticatedAt = consentRequest.AuthenticatedAt
// Reject the consents
if consentRequest.ID == j.flushConsentRequests[0].ID {
// accept this one
_, err = cm.HandleConsentRequest(ctx, f, consent.NewHandledConsentRequest(
consentRequest.ID, false, consentRequest.RequestedAt, consentRequest.AuthenticatedAt))
require.NoError(t, err)
continue
}
_, err = cm.HandleConsentRequest(ctx, f, consent.NewHandledConsentRequest(
consentRequest.ID, true, consentRequest.RequestedAt, consentRequest.AuthenticatedAt))
require.NoError(t, err)
}
}
}
func (j *JanitorConsentTestHelper) ConsentRejectionValidate(ctx context.Context, cm consent.Manager) func(t *testing.T) {
return func(t *testing.T) {
var err error
for _, r := range j.flushConsentRequests {
t.Logf("check consent: %s", r.ID)
_, err = cm.GetConsentRequest(ctx, r.ID)
// Consent requests should never be persisted.
require.Error(t, err)
}
}
}
func (j *JanitorConsentTestHelper) LoginTimeoutSetup(ctx context.Context, reg interface {
consent.ManagerProvider
client.ManagerProvider
flow.CipherProvider
}) func(t *testing.T) {
cl := reg.ClientManager()
cm := reg.ConsentManager()
return func(t *testing.T) {
var (
err error
f *flow.Flow
)
// Create login requests
for i, loginRequest := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, loginRequest.Client))
f, err = cm.CreateLoginRequest(ctx, loginRequest)
require.NoError(t, err)
if i == 0 {
// Creating at least 1 that has not timed out
challenge := x.Must(f.ToLoginChallenge(ctx, reg))
_, err = cm.HandleLoginRequest(ctx, f, challenge, &flow.HandledLoginRequest{
ID: loginRequest.ID,
RequestedAt: loginRequest.RequestedAt,
AuthenticatedAt: loginRequest.AuthenticatedAt,
WasHandled: true,
})
}
}
require.NoError(t, err)
}
}
func (j *JanitorConsentTestHelper) LoginTimeoutValidate(ctx context.Context, cm consent.Manager) func(t *testing.T) {
return func(t *testing.T) {
for _, r := range j.flushLoginRequests {
_, err := cm.GetLoginRequest(ctx, r.ID)
// Login requests should never be persisted.
require.Error(t, err)
}
}
}
func (j *JanitorConsentTestHelper) ConsentTimeoutSetup(ctx context.Context, reg interface {
consent.ManagerProvider
client.ManagerProvider
flow.CipherProvider
}) func(t *testing.T) {
cl := reg.ClientManager()
cm := reg.ConsentManager()
return func(t *testing.T) {
// Let's reset and accept all login requests to test the consent requests
for i, loginRequest := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, loginRequest.Client))
f, err := cm.CreateLoginRequest(ctx, loginRequest)
require.NoError(t, err)
f.RequestedAt = time.Now() // we won't handle expired flows
challenge := x.Must(f.ToLoginChallenge(ctx, reg))
_, err = cm.HandleLoginRequest(ctx, f, challenge, &flow.HandledLoginRequest{
ID: loginRequest.ID,
AuthenticatedAt: loginRequest.AuthenticatedAt,
RequestedAt: loginRequest.RequestedAt,
WasHandled: true,
})
require.NoError(t, err)
// Create consent requests
consentRequest := j.flushConsentRequests[i]
err = cm.CreateConsentRequest(ctx, f, consentRequest)
require.NoError(t, err)
if i == 0 {
// Create at least 1 consent request that has been accepted
_, err = cm.HandleConsentRequest(ctx, f, &flow.AcceptOAuth2ConsentRequest{
ID: consentRequest.ID,
WasHandled: true,
HandledAt: sqlxx.NullTime(time.Now()),
RequestedAt: consentRequest.RequestedAt,
AuthenticatedAt: consentRequest.AuthenticatedAt,
})
require.NoError(t, err)
}
}
}
}
func (j *JanitorConsentTestHelper) ConsentTimeoutValidate(ctx context.Context, cm consent.Manager) func(t *testing.T) {
return func(t *testing.T) {
var err error
for _, r := range j.flushConsentRequests {
_, err = cm.GetConsentRequest(ctx, r.ID)
require.Error(t, err, "Unverified consent requests are never pesisted")
}
}
}
func (j *JanitorConsentTestHelper) LoginConsentNotAfterSetup(ctx context.Context, cm consent.Manager, cl client.Manager) func(t *testing.T) {
return func(t *testing.T) {
var (
f *flow.Flow
err error
)
for _, r := range j.flushLoginRequests {
require.NoError(t, cl.CreateClient(ctx, r.Client))
f, err = cm.CreateLoginRequest(ctx, r)
require.NoError(t, err)
}
for _, r := range j.flushConsentRequests {
f.ID = r.LoginChallenge.String()
err = cm.CreateConsentRequest(ctx, f, r)
require.NoError(t, err)
}
}
}
func (j *JanitorConsentTestHelper) LoginConsentNotAfterValidate(
ctx context.Context,
notAfter time.Time,
consentRequestLifespan time.Time,
reg interface {
consent.ManagerProvider
flow.CipherProvider
},
) func(t *testing.T) {
return func(t *testing.T) {
var (
err error
f *flow.Flow
)
for _, r := range j.flushLoginRequests {
isExpired := r.RequestedAt.Before(consentRequestLifespan)
t.Logf("login flush check:\nNotAfter: %s\nLoginRequest: %s\nis expired: %v\n%+v\n",
notAfter.String(), consentRequestLifespan.String(), isExpired, r)
f = x.Must(reg.ConsentManager().CreateLoginRequest(ctx, r))
loginChallenge := x.Must(f.ToLoginChallenge(ctx, reg))
_, err = reg.ConsentManager().GetLoginRequest(ctx, loginChallenge)
// if the lowest between notAfter and consent-request-lifespan is greater than requested_at
// then the it should expect the value to be deleted.
if isExpired {
// value has been deleted here
require.Error(t, err)
} else {
// value has not been deleted here
require.NoError(t, err)
}
}
for _, r := range j.flushConsentRequests {
isExpired := r.RequestedAt.Before(consentRequestLifespan)
t.Logf("consent flush check:\nNotAfter: %s\nConsentRequest: %s\nis expired: %v\n%+v\n",
notAfter.String(), consentRequestLifespan.String(), isExpired, r)
f.ID = r.LoginChallenge.String()
require.NoError(t, reg.ConsentManager().CreateConsentRequest(ctx, f, r))
f.RequestedAt = r.RequestedAt
consentChallenge := x.Must(f.ToConsentChallenge(ctx, reg))
_, err = reg.ConsentManager().GetConsentRequest(ctx, consentChallenge)
// if the lowest between notAfter and consent-request-lifespan is greater than requested_at
// then the it should expect the value to be deleted.
if isExpired {
// value has been deleted here
require.Error(t, err)
} else {
// value has not been deleted here
require.NoError(t, err)
}
}
}
}
func (j *JanitorConsentTestHelper) GetConsentRequestLifespan(ctx context.Context) time.Duration {
return j.conf.ConsentRequestMaxAge(ctx)
}
func (j *JanitorConsentTestHelper) GetAccessTokenLifespan(ctx context.Context) time.Duration {
return j.conf.GetAccessTokenLifespan(ctx)
}
func (j *JanitorConsentTestHelper) GetRefreshTokenLifespan(ctx context.Context) time.Duration {
return j.conf.GetRefreshTokenLifespan(ctx)
}
func (j *JanitorConsentTestHelper) notAfterCheck(notAfter time.Time, lifespan time.Time, requestedAt time.Time) bool {
// The database deletes where requested_at time is smaller than the lowest between notAfter and consent-request-lifespan
// thus we get the lowest value here first to compare later to requested_at
var lesser time.Time
// if the lowest between notAfter and consent-request-lifespan is greater than requested_at
// then the it should expect the value to be deleted.
if notAfter.Unix() < lifespan.Unix() {
lesser = notAfter
} else {
lesser = lifespan
}
// true: value has been deleted
// false: value still exists
return lesser.Unix() > requestedAt.Unix()
}
func JanitorTests(
reg interface {
ConsentManager() consent.Manager
OAuth2Storage() x.FositeStorer
config.Provider
client.ManagerProvider
flow.CipherProvider
},
network string,
parallel bool,
) func(t *testing.T) {
return func(t *testing.T) {
consentManager := reg.ConsentManager()
clientManager := reg.ClientManager()
fositeManager := reg.OAuth2Storage()
if parallel {
t.Parallel()
}
ctx := context.Background()
jt := NewConsentJanitorTestHelper(network + t.Name())
reg.Config().MustSet(context.Background(), config.KeyConsentRequestMaxAge, jt.GetConsentRequestLifespan(ctx))
t.Run("case=flush-consent-request-not-after", func(t *testing.T) {
notAfterTests := jt.GetNotAfterTestCycles()
for k, v := range notAfterTests {
jt := NewConsentJanitorTestHelper(network + k)
t.Run(fmt.Sprintf("case=%s", k), func(t *testing.T) {
notAfter := time.Now().Round(time.Second).Add(-v)
consentRequestLifespan := time.Now().Round(time.Second).Add(-jt.GetConsentRequestLifespan(ctx))
// setup test
t.Run("step=setup", jt.LoginConsentNotAfterSetup(ctx, consentManager, clientManager))
// run the cleanup routine
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, notAfter, 1000, 100))
})
// validate test
t.Run("step=validate", jt.LoginConsentNotAfterValidate(ctx, notAfter, consentRequestLifespan, reg))
})
}
})
t.Run("case=flush-consent-request-limit", func(t *testing.T) {
jt := NewConsentJanitorTestHelper(network + "limit")
t.Run("case=limit", func(t *testing.T) {
// setup
t.Run("step=setup", jt.LimitSetup(ctx, reg))
// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 2, 1))
})
// validate
t.Run("step=validate", jt.LimitValidate(ctx, consentManager))
})
})
t.Run("case=flush-consent-request-rejection", func(t *testing.T) {
jt := NewConsentJanitorTestHelper(network + "loginRejection")
t.Run(fmt.Sprintf("case=%s", "loginRejection"), func(t *testing.T) {
// setup
t.Run("step=setup", jt.LoginRejectionSetup(ctx, reg))
// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 1000, 100))
})
// validate
t.Run("step=validate", jt.LoginRejectionValidate(ctx, consentManager))
})
jt = NewConsentJanitorTestHelper(network + "consentRejection")
t.Run(fmt.Sprintf("case=%s", "consentRejection"), func(t *testing.T) {
// setup
t.Run("step=setup", jt.ConsentRejectionSetup(ctx, reg))
// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 1000, 100))
})
// validate
t.Run("step=validate", jt.ConsentRejectionValidate(ctx, consentManager))
})
})
t.Run("case=flush-consent-request-timeout", func(t *testing.T) {
jt := NewConsentJanitorTestHelper(network + "loginTimeout")
t.Run(fmt.Sprintf("case=%s", "login-timeout"), func(t *testing.T) {
// setup
t.Run("step=setup", jt.LoginTimeoutSetup(ctx, reg))
// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 1000, 100))
})
// validate
t.Run("step=validate", jt.LoginTimeoutValidate(ctx, consentManager))
})
jt = NewConsentJanitorTestHelper(network + "consentTimeout")
t.Run(fmt.Sprintf("case=%s", "consent-timeout"), func(t *testing.T) {
// setup
t.Run("step=setup", jt.ConsentTimeoutSetup(ctx, reg))
// cleanup
t.Run("step=cleanup", func(t *testing.T) {
require.NoError(t, fositeManager.FlushInactiveLoginConsentRequests(ctx, time.Now().Round(time.Second), 1000, 100))
})
// validate
t.Run("step=validate", jt.ConsentTimeoutValidate(ctx, consentManager))
})
})
}
}
func getAccessRequests(uniqueName string, lifespan time.Duration) []*fosite.Request {
return []*fosite.Request{
{
ID: fmt.Sprintf("%s_flush-access-1", uniqueName),
RequestedAt: time.Now().Round(time.Second),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-access-1", uniqueName)},
RequestedScope: fosite.Arguments{"fa", "ba"},
GrantedScope: fosite.Arguments{"fa", "ba"},
Form: url.Values{"foo": []string{"bar", "baz"}},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
},
{
ID: fmt.Sprintf("%s_flush-access-2", uniqueName),
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Minute)),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-access-2", uniqueName)},
RequestedScope: fosite.Arguments{"fa", "ba"},
GrantedScope: fosite.Arguments{"fa", "ba"},
Form: url.Values{"foo": []string{"bar", "baz"}},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
},
{
ID: fmt.Sprintf("%s_flush-access-3", uniqueName),
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-access-3", uniqueName)},
RequestedScope: fosite.Arguments{"fa", "ba"},
GrantedScope: fosite.Arguments{"fa", "ba"},
Form: url.Values{"foo": []string{"bar", "baz"}},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
},
}
}
func getRefreshRequests(uniqueName string, lifespan time.Duration) []*fosite.AccessRequest {
var tokenSignature = "4c7c7e8b3a77ad0c3ec846a21653c48b45dbfa31" //nolint:gosec
return []*fosite.AccessRequest{
{
GrantTypes: []string{
"refresh_token",
},
Request: fosite.Request{
RequestedAt: time.Now().Round(time.Second),
ID: fmt.Sprintf("%s_flush-refresh-1", uniqueName),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-refresh-1", uniqueName)},
RequestedScope: []string{"offline"},
GrantedScope: []string{"offline"},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
Form: url.Values{
"refresh_token": []string{fmt.Sprintf("%s.%s", fmt.Sprintf("%s_flush-refresh-1", uniqueName), tokenSignature)},
},
},
},
{
GrantTypes: []string{
"refresh_token",
},
Request: fosite.Request{
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Minute)),
ID: fmt.Sprintf("%s_flush-refresh-2", uniqueName),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-refresh-2", uniqueName)},
RequestedScope: []string{"offline"},
GrantedScope: []string{"offline"},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
Form: url.Values{
"refresh_token": []string{fmt.Sprintf("%s.%s", fmt.Sprintf("%s_flush-refresh-2", uniqueName), tokenSignature)},
},
},
},
{
GrantTypes: []string{
"refresh_token",
},
Request: fosite.Request{
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)),
ID: fmt.Sprintf("%s_flush-refresh-3", uniqueName),
Client: &client.Client{ID: fmt.Sprintf("%s_flush-refresh-3", uniqueName)},
RequestedScope: []string{"offline"},
GrantedScope: []string{"offline"},
Session: &oauth2.Session{DefaultSession: &openid.DefaultSession{Subject: "bar"}},
Form: url.Values{
"refresh_token": []string{fmt.Sprintf("%s.%s", fmt.Sprintf("%s_flush-refresh-3", uniqueName), tokenSignature)},
},
},
},
}
}
func genLoginRequests(uniqueName string, lifespan time.Duration) []*flow.LoginRequest {
return []*flow.LoginRequest{
{
ID: fmt.Sprintf("%s_flush-login-1", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-login-1", uniqueName),
Client: &client.Client{
ID: fmt.Sprintf("%s_flush-login-consent-1", uniqueName),
RedirectURIs: []string{"http://redirect"},
},
RequestURL: "http://redirect",
RequestedAt: time.Now().Round(time.Second),
AuthenticatedAt: sqlxx.NullTime(time.Now().Round(time.Second)),
Verifier: fmt.Sprintf("%s_flush-login-1", uniqueName),
},
{
ID: fmt.Sprintf("%s_flush-login-2", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-login-2", uniqueName),
Client: &client.Client{
ID: fmt.Sprintf("%s_flush-login-consent-2", uniqueName),
RedirectURIs: []string{"http://redirect"},
},
RequestURL: "http://redirect",
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + 10*time.Minute)),
AuthenticatedAt: sqlxx.NullTime(time.Now().Round(time.Second).Add(-(lifespan + 10*time.Minute))),
Verifier: fmt.Sprintf("%s_flush-login-2", uniqueName),
},
{
ID: fmt.Sprintf("%s_flush-login-3", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-login-3", uniqueName),
Client: &client.Client{
ID: fmt.Sprintf("%s_flush-login-consent-3", uniqueName),
RedirectURIs: []string{"http://redirect"},
},
RequestURL: "http://redirect",
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)),
AuthenticatedAt: sqlxx.NullTime(time.Now().Round(time.Second).Add(-(lifespan + time.Hour))),
Verifier: fmt.Sprintf("%s_flush-login-3", uniqueName),
},
}
}
func genConsentRequests(uniqueName string, lifespan time.Duration) []*flow.OAuth2ConsentRequest {
return []*flow.OAuth2ConsentRequest{
{
ID: fmt.Sprintf("%s_flush-consent-1", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-consent-1", uniqueName),
OpenIDConnectContext: nil,
ClientID: fmt.Sprintf("%s_flush-login-consent-1", uniqueName),
RequestURL: "http://redirect",
LoginChallenge: sqlxx.NullString(fmt.Sprintf("%s_flush-login-1", uniqueName)),
RequestedAt: time.Now().Round(time.Second),
Verifier: fmt.Sprintf("%s_flush-consent-1", uniqueName),
CSRF: fmt.Sprintf("%s_flush-consent-1", uniqueName),
},
{
ID: fmt.Sprintf("%s_flush-consent-2", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-consent-2", uniqueName),
OpenIDConnectContext: nil,
ClientID: fmt.Sprintf("%s_flush-login-consent-2", uniqueName),
RequestURL: "http://redirect",
LoginChallenge: sqlxx.NullString(fmt.Sprintf("%s_flush-login-2", uniqueName)),
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Minute)),
Verifier: fmt.Sprintf("%s_flush-consent-2", uniqueName),
CSRF: fmt.Sprintf("%s_flush-consent-2", uniqueName),
},
{
ID: fmt.Sprintf("%s_flush-consent-3", uniqueName),
RequestedScope: []string{"foo", "bar"},
Subject: fmt.Sprintf("%s_flush-consent-3", uniqueName),
OpenIDConnectContext: nil,
ClientID: fmt.Sprintf("%s_flush-login-consent-3", uniqueName),
RequestURL: "http://redirect",
LoginChallenge: sqlxx.NullString(fmt.Sprintf("%s_flush-login-3", uniqueName)),
RequestedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)),
Verifier: fmt.Sprintf("%s_flush-consent-3", uniqueName),
CSRF: fmt.Sprintf("%s_flush-consent-3", uniqueName),
},
}
}
func getGrantRequests(uniqueName string, lifespan time.Duration) []*createGrantRequest {
return []*createGrantRequest{
{
grant: trust.Grant{
ID: uuid.New().String(),
Issuer: fmt.Sprintf("%s_flush-grant-iss-1", uniqueName),
Subject: fmt.Sprintf("%s_flush-grant-sub-1", uniqueName),
Scope: []string{"foo", "bar"},
PublicKey: trust.PublicKey{
Set: fmt.Sprintf("%s_flush-grant-iss-1", uniqueName),
KeyID: fmt.Sprintf("%s_flush-grant-kid-1", uniqueName),
},
CreatedAt: time.Now().Round(time.Second),
ExpiresAt: time.Now().Round(time.Second).Add(lifespan),
},
pk: jose.JSONWebKey{
Key: []byte("asdf"),
KeyID: fmt.Sprintf("%s_flush-grant-kid-1", uniqueName),
},
},
{
grant: trust.Grant{
ID: uuid.New().String(),
Issuer: fmt.Sprintf("%s_flush-grant-iss-2", uniqueName),
Subject: fmt.Sprintf("%s_flush-grant-sub-2", uniqueName),
Scope: []string{"foo", "bar"},
PublicKey: trust.PublicKey{
Set: fmt.Sprintf("%s_flush-grant-iss-2", uniqueName),
KeyID: fmt.Sprintf("%s_flush-grant-kid-2", uniqueName),
},
CreatedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Minute)),
ExpiresAt: time.Now().Round(time.Second).Add(-(lifespan + time.Minute)).Add(lifespan),
},
pk: jose.JSONWebKey{
Key: []byte("asdf"),
KeyID: fmt.Sprintf("%s_flush-grant-kid-2", uniqueName),
},
},
{
grant: trust.Grant{
ID: uuid.New().String(),
Issuer: fmt.Sprintf("%s_flush-grant-iss-3", uniqueName),
Subject: fmt.Sprintf("%s_flush-grant-sub-3", uniqueName),
Scope: []string{"foo", "bar"},
PublicKey: trust.PublicKey{
Set: fmt.Sprintf("%s_flush-grant-iss-3", uniqueName),
KeyID: fmt.Sprintf("%s_flush-grant-kid-3", uniqueName),
},
CreatedAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)),
ExpiresAt: time.Now().Round(time.Second).Add(-(lifespan + time.Hour)).Add(lifespan),
},
pk: jose.JSONWebKey{
Key: []byte("asdf"),
KeyID: fmt.Sprintf("%s_flush-grant-kid-3", uniqueName),
},
},
}
}