mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: add session expiry control flags (#5976)
Adds --session-duration which lets admins customize the default session expiration for browser sessions. Adds --disable-session-expiry-refresh which allows admins to prevent session expiry from being automatically bumped upon the API key being used.
This commit is contained in:
@ -2,12 +2,17 @@ package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
@ -109,6 +114,58 @@ func TestTokenMaxLifetime(t *testing.T) {
|
||||
require.ErrorContains(t, err, "lifetime must be less")
|
||||
}
|
||||
|
||||
func TestSessionExpiry(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
dc := coderdtest.DeploymentConfig(t)
|
||||
|
||||
db, pubsub := dbtestutil.NewDB(t)
|
||||
adminClient := coderdtest.New(t, &coderdtest.Options{
|
||||
DeploymentConfig: dc,
|
||||
Database: db,
|
||||
Pubsub: pubsub,
|
||||
})
|
||||
adminUser := coderdtest.CreateFirstUser(t, adminClient)
|
||||
|
||||
// This is a hack, but we need the admin account to have a long expiry
|
||||
// otherwise the test will flake, so we only update the expiry config after
|
||||
// the admin account has been created.
|
||||
//
|
||||
// We don't support updating the deployment config after startup, but for
|
||||
// this test it works because we don't copy the value (and we use pointers).
|
||||
dc.SessionDuration.Value = time.Second
|
||||
|
||||
userClient := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
|
||||
|
||||
// Find the session cookie, and ensure it has the correct expiry.
|
||||
token := userClient.SessionToken()
|
||||
apiKey, err := db.GetAPIKeyByID(ctx, strings.Split(token, "-")[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
require.EqualValues(t, dc.SessionDuration.Value.Seconds(), apiKey.LifetimeSeconds)
|
||||
require.WithinDuration(t, apiKey.CreatedAt.Add(dc.SessionDuration.Value), apiKey.ExpiresAt, 2*time.Second)
|
||||
|
||||
// Update the session token to be expired so we can test that it is
|
||||
// rejected for extra points.
|
||||
err = db.UpdateAPIKeyByID(ctx, database.UpdateAPIKeyByIDParams{
|
||||
ID: apiKey.ID,
|
||||
LastUsed: apiKey.LastUsed,
|
||||
ExpiresAt: database.Now().Add(-time.Hour),
|
||||
IPAddress: apiKey.IPAddress,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = userClient.User(ctx, codersdk.Me)
|
||||
require.Error(t, err)
|
||||
var sdkErr *codersdk.Error
|
||||
if assert.ErrorAs(t, err, &sdkErr) {
|
||||
require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode())
|
||||
require.Contains(t, sdkErr.Message, "session has expired")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
|
Reference in New Issue
Block a user