mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-08 17:37:01 +00:00
refactor(session/data): separate into object groups
This commit is contained in:
@@ -174,29 +174,29 @@ func TestHandler_SessionInfo(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
allowedSkew := 5 * time.Second
|
||||
assert.WithinDuration(t, time.Now(), data.SessionCreatedAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now().Add(cfg.Session.MaxLifetime), data.SessionEndsAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now().Add(idp.ProviderHandler.TokenDuration), data.TokensExpireAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now(), data.TokensRefreshedAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now(), data.Session.CreatedAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now().Add(cfg.Session.MaxLifetime), data.Session.EndsAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now().Add(idp.ProviderHandler.TokenDuration), data.Tokens.ExpireAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now(), data.Tokens.RefreshedAt, allowedSkew)
|
||||
|
||||
sessionEndDuration := time.Duration(data.SessionEndsInSeconds) * time.Second
|
||||
sessionEndDuration := time.Duration(data.Session.EndsInSeconds) * time.Second
|
||||
// 1 second < time until session ends <= configured max session lifetime
|
||||
assert.LessOrEqual(t, sessionEndDuration, cfg.Session.MaxLifetime)
|
||||
assert.Greater(t, sessionEndDuration, time.Second)
|
||||
|
||||
tokenExpiryDuration := time.Duration(data.TokensExpireInSeconds) * time.Second
|
||||
tokenExpiryDuration := time.Duration(data.Tokens.ExpireInSeconds) * time.Second
|
||||
// 1 second < time until token expires <= max duration for tokens from IDP
|
||||
assert.LessOrEqual(t, tokenExpiryDuration, idp.ProviderHandler.TokenDuration)
|
||||
assert.Greater(t, tokenExpiryDuration, time.Second)
|
||||
|
||||
// 1 second < next token refresh <= seconds until token expires
|
||||
assert.LessOrEqual(t, data.TokensNextRefreshInSeconds, data.TokensExpireInSeconds)
|
||||
assert.Greater(t, data.TokensNextRefreshInSeconds, int64(1))
|
||||
assert.LessOrEqual(t, data.Tokens.NextAutoRefreshInSeconds, data.Tokens.ExpireInSeconds)
|
||||
assert.Greater(t, data.Tokens.NextAutoRefreshInSeconds, int64(1))
|
||||
|
||||
assert.True(t, data.TokensRefreshCooldown)
|
||||
assert.True(t, data.Tokens.RefreshCooldown)
|
||||
// 1 second < refresh cooldown <= minimum refresh interval
|
||||
assert.LessOrEqual(t, data.TokensRefreshCooldownSeconds, session.RefreshMinInterval)
|
||||
assert.Greater(t, data.TokensRefreshCooldownSeconds, int64(1))
|
||||
assert.LessOrEqual(t, data.Tokens.RefreshCooldownSeconds, session.RefreshMinInterval)
|
||||
assert.Greater(t, data.Tokens.RefreshCooldownSeconds, int64(1))
|
||||
}
|
||||
|
||||
func TestHandler_SessionInfo_Disabled(t *testing.T) {
|
||||
@@ -249,7 +249,7 @@ func TestHandler_SessionRefresh(t *testing.T) {
|
||||
err = json.Unmarshal([]byte(resp.Body), &temp)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if !temp.TokensRefreshCooldown {
|
||||
if !temp.Tokens.RefreshCooldown {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -264,35 +264,35 @@ func TestHandler_SessionRefresh(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// session create and end times should be unchanged
|
||||
assert.WithinDuration(t, data.SessionCreatedAt, refreshedData.SessionCreatedAt, 0)
|
||||
assert.WithinDuration(t, data.SessionEndsAt, refreshedData.SessionEndsAt, 0)
|
||||
assert.WithinDuration(t, data.Session.CreatedAt, refreshedData.Session.CreatedAt, 0)
|
||||
assert.WithinDuration(t, data.Session.EndsAt, refreshedData.Session.EndsAt, 0)
|
||||
|
||||
// token expiration and refresh times should be later than before
|
||||
assert.True(t, refreshedData.TokensExpireAt.After(data.TokensExpireAt))
|
||||
assert.True(t, refreshedData.TokensRefreshedAt.After(data.TokensRefreshedAt))
|
||||
assert.True(t, refreshedData.Tokens.ExpireAt.After(data.Tokens.ExpireAt))
|
||||
assert.True(t, refreshedData.Tokens.RefreshedAt.After(data.Tokens.RefreshedAt))
|
||||
|
||||
allowedSkew := 5 * time.Second
|
||||
assert.WithinDuration(t, time.Now().Add(idp.ProviderHandler.TokenDuration), refreshedData.TokensExpireAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now(), refreshedData.TokensRefreshedAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now().Add(idp.ProviderHandler.TokenDuration), refreshedData.Tokens.ExpireAt, allowedSkew)
|
||||
assert.WithinDuration(t, time.Now(), refreshedData.Tokens.RefreshedAt, allowedSkew)
|
||||
|
||||
sessionEndDuration := time.Duration(refreshedData.SessionEndsInSeconds) * time.Second
|
||||
sessionEndDuration := time.Duration(refreshedData.Session.EndsInSeconds) * time.Second
|
||||
// 1 second < time until session ends <= configured max session lifetime
|
||||
assert.LessOrEqual(t, sessionEndDuration, cfg.Session.MaxLifetime)
|
||||
assert.Greater(t, sessionEndDuration, time.Second)
|
||||
|
||||
tokenExpiryDuration := time.Duration(refreshedData.TokensExpireInSeconds) * time.Second
|
||||
tokenExpiryDuration := time.Duration(refreshedData.Tokens.ExpireInSeconds) * time.Second
|
||||
// 1 second < time until token expires <= max duration for tokens from IDP
|
||||
assert.LessOrEqual(t, tokenExpiryDuration, idp.ProviderHandler.TokenDuration)
|
||||
assert.Greater(t, tokenExpiryDuration, time.Second)
|
||||
|
||||
// 1 second < next token refresh <= seconds until token expires
|
||||
assert.LessOrEqual(t, refreshedData.TokensNextRefreshInSeconds, refreshedData.TokensExpireInSeconds)
|
||||
assert.Greater(t, refreshedData.TokensNextRefreshInSeconds, int64(1))
|
||||
assert.LessOrEqual(t, refreshedData.Tokens.NextAutoRefreshInSeconds, refreshedData.Tokens.ExpireInSeconds)
|
||||
assert.Greater(t, refreshedData.Tokens.NextAutoRefreshInSeconds, int64(1))
|
||||
|
||||
assert.True(t, refreshedData.TokensRefreshCooldown)
|
||||
assert.True(t, refreshedData.Tokens.RefreshCooldown)
|
||||
// 1 second < refresh cooldown <= minimum refresh interval
|
||||
assert.LessOrEqual(t, refreshedData.TokensRefreshCooldownSeconds, session.RefreshMinInterval)
|
||||
assert.Greater(t, refreshedData.TokensRefreshCooldownSeconds, int64(1))
|
||||
assert.LessOrEqual(t, refreshedData.Tokens.RefreshCooldownSeconds, session.RefreshMinInterval)
|
||||
assert.Greater(t, refreshedData.Tokens.RefreshCooldownSeconds, int64(1))
|
||||
}
|
||||
|
||||
func TestHandler_SessionRefresh_Disabled(t *testing.T) {
|
||||
|
||||
@@ -100,28 +100,40 @@ func (in *Data) HasRefreshToken() bool {
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
// SessionCreatedAt is the time when the session was created.
|
||||
SessionCreatedAt time.Time `json:"session_created_at"`
|
||||
// SessionEndsAt is the time when the session will end, i.e. the absolute lifetime/time-to-live for the session.
|
||||
SessionEndsAt time.Time `json:"session_ends_at"`
|
||||
// TokensExpireAt is the time when the tokens within the session expires.
|
||||
TokensExpireAt time.Time `json:"tokens_expire_at"`
|
||||
// TokensRefreshedAt is the time when the tokens within the session was refreshed.
|
||||
TokensRefreshedAt time.Time `json:"tokens_refreshed_at"`
|
||||
Session MetadataSession `json:"session"`
|
||||
Tokens MetadataTokens `json:"tokens"`
|
||||
}
|
||||
|
||||
type MetadataSession struct {
|
||||
// CreatedAt is the time when the session was created.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// EndsAt is the time when the session will end, i.e. the absolute lifetime/time-to-live for the session.
|
||||
EndsAt time.Time `json:"ends_at"`
|
||||
}
|
||||
|
||||
type MetadataTokens struct {
|
||||
// ExpireAt is the time when the tokens will expire.
|
||||
ExpireAt time.Time `json:"expire_at"`
|
||||
// RefreshedAt is the time when the tokens were last refreshed.
|
||||
RefreshedAt time.Time `json:"refreshed_at"`
|
||||
}
|
||||
|
||||
func NewMetadata(expiresIn time.Duration, endsIn time.Duration) *Metadata {
|
||||
now := time.Now()
|
||||
return &Metadata{
|
||||
SessionCreatedAt: now,
|
||||
SessionEndsAt: now.Add(endsIn),
|
||||
TokensRefreshedAt: now,
|
||||
TokensExpireAt: now.Add(expiresIn),
|
||||
Session: MetadataSession{
|
||||
CreatedAt: now,
|
||||
EndsAt: now.Add(endsIn),
|
||||
},
|
||||
Tokens: MetadataTokens{
|
||||
ExpireAt: now.Add(expiresIn),
|
||||
RefreshedAt: now,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (in *Metadata) IsExpired() bool {
|
||||
return time.Now().After(in.TokensExpireAt)
|
||||
return time.Now().After(in.Tokens.ExpireAt)
|
||||
}
|
||||
|
||||
func (in *Metadata) IsRefreshOnCooldown() bool {
|
||||
@@ -130,7 +142,7 @@ func (in *Metadata) IsRefreshOnCooldown() bool {
|
||||
|
||||
func (in *Metadata) NextRefresh() time.Time {
|
||||
// subtract the leeway to ensure that we refresh before expiry
|
||||
next := in.TokensExpireAt.Add(-RefreshLeeway)
|
||||
next := in.Tokens.ExpireAt.Add(-RefreshLeeway)
|
||||
|
||||
// try to refresh at the first opportunity if the next refresh is in the past
|
||||
if next.Before(time.Now()) {
|
||||
@@ -142,12 +154,12 @@ func (in *Metadata) NextRefresh() time.Time {
|
||||
|
||||
func (in *Metadata) Refresh(nextExpirySeconds int64) {
|
||||
now := time.Now()
|
||||
in.TokensRefreshedAt = now
|
||||
in.TokensExpireAt = now.Add(time.Duration(nextExpirySeconds) * time.Second)
|
||||
in.Tokens.RefreshedAt = now
|
||||
in.Tokens.ExpireAt = now.Add(time.Duration(nextExpirySeconds) * time.Second)
|
||||
}
|
||||
|
||||
func (in *Metadata) RefreshCooldown() time.Time {
|
||||
refreshed := in.TokensRefreshedAt
|
||||
refreshed := in.Tokens.RefreshedAt
|
||||
tokenLifetime := in.TokenLifetime()
|
||||
|
||||
// if token lifetime is less than the minimum refresh interval * 2, we'll allow refreshes at the token half-life
|
||||
@@ -167,33 +179,47 @@ func (in *Metadata) ShouldRefresh() bool {
|
||||
}
|
||||
|
||||
func (in *Metadata) TokenLifetime() time.Duration {
|
||||
return in.TokensExpireAt.Sub(in.TokensRefreshedAt)
|
||||
return in.Tokens.ExpireAt.Sub(in.Tokens.RefreshedAt)
|
||||
}
|
||||
|
||||
func (in *Metadata) Verbose() MetadataVerbose {
|
||||
now := time.Now()
|
||||
|
||||
expireTime := in.TokensExpireAt
|
||||
endTime := in.SessionEndsAt
|
||||
expireTime := in.Tokens.ExpireAt
|
||||
endTime := in.Session.EndsAt
|
||||
nextRefreshTime := in.NextRefresh()
|
||||
|
||||
return MetadataVerbose{
|
||||
Metadata: *in,
|
||||
SessionEndsInSeconds: toSeconds(endTime.Sub(now)),
|
||||
TokensExpireInSeconds: toSeconds(expireTime.Sub(now)),
|
||||
TokensNextRefreshInSeconds: toSeconds(nextRefreshTime.Sub(now)),
|
||||
TokensRefreshCooldown: in.IsRefreshOnCooldown(),
|
||||
TokensRefreshCooldownSeconds: toSeconds(in.RefreshCooldown().Sub(now)),
|
||||
Session: MetadataSessionVerbose{
|
||||
MetadataSession: in.Session,
|
||||
EndsInSeconds: toSeconds(endTime.Sub(now)),
|
||||
},
|
||||
Tokens: MetadataTokensVerbose{
|
||||
MetadataTokens: in.Tokens,
|
||||
ExpireInSeconds: toSeconds(expireTime.Sub(now)),
|
||||
NextAutoRefreshInSeconds: toSeconds(nextRefreshTime.Sub(now)),
|
||||
RefreshCooldown: in.IsRefreshOnCooldown(),
|
||||
RefreshCooldownSeconds: toSeconds(in.RefreshCooldown().Sub(now)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type MetadataVerbose struct {
|
||||
Metadata
|
||||
SessionEndsInSeconds int64 `json:"session_ends_in_seconds"`
|
||||
TokensExpireInSeconds int64 `json:"tokens_expire_in_seconds"`
|
||||
TokensNextRefreshInSeconds int64 `json:"tokens_next_refresh_in_seconds"`
|
||||
TokensRefreshCooldown bool `json:"tokens_refresh_cooldown"`
|
||||
TokensRefreshCooldownSeconds int64 `json:"tokens_refresh_cooldown_seconds"`
|
||||
Session MetadataSessionVerbose `json:"session"`
|
||||
Tokens MetadataTokensVerbose `json:"tokens"`
|
||||
}
|
||||
|
||||
type MetadataSessionVerbose struct {
|
||||
MetadataSession
|
||||
EndsInSeconds int64 `json:"ends_in_seconds"`
|
||||
}
|
||||
|
||||
type MetadataTokensVerbose struct {
|
||||
MetadataTokens
|
||||
ExpireInSeconds int64 `json:"expire_in_seconds"`
|
||||
NextAutoRefreshInSeconds int64 `json:"next_auto_refresh_in_seconds"`
|
||||
RefreshCooldown bool `json:"refresh_cooldown"`
|
||||
RefreshCooldownSeconds int64 `json:"refresh_cooldown_seconds"`
|
||||
}
|
||||
|
||||
func toSeconds(d time.Duration) int64 {
|
||||
|
||||
@@ -12,6 +12,14 @@ func TestData_HasRefreshToken(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_IsExpired(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_IsRefreshOnCooldown(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_NextRefresh(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
@@ -24,15 +32,11 @@ func TestMetadata_RefreshCooldown(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_RefreshOnCooldown(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_ShouldRefresh(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestMetadata_TokenAge(t *testing.T) {
|
||||
func TestMetadata_TokenLifetime(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ func decryptedEqual(t *testing.T, expected, actual *session.Data) {
|
||||
assert.Equal(t, expected.IDTokenJwtID, actual.IDTokenJwtID)
|
||||
assert.Equal(t, expected.ExternalSessionID, actual.ExternalSessionID)
|
||||
|
||||
assert.WithinDuration(t, expected.Metadata.SessionCreatedAt, actual.Metadata.SessionCreatedAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.SessionEndsAt, actual.Metadata.SessionEndsAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.TokensExpireAt, actual.Metadata.TokensExpireAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.TokensRefreshedAt, actual.Metadata.TokensRefreshedAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.Session.CreatedAt, actual.Metadata.Session.CreatedAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.Session.EndsAt, actual.Metadata.Session.EndsAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.Tokens.ExpireAt, actual.Metadata.Tokens.ExpireAt, 0)
|
||||
assert.WithinDuration(t, expected.Metadata.Tokens.RefreshedAt, actual.Metadata.Tokens.RefreshedAt, 0)
|
||||
}
|
||||
|
||||
func makeCrypter(t *testing.T) crypto.Crypter {
|
||||
|
||||
Reference in New Issue
Block a user