argo-cd/test/e2e/logout_test.go
Anand Francis Joseph d9c83da78f
fix(server): invalidate JWT tokens on logout (#26388)
Signed-off-by: anandf <anjoseph@redhat.com>
2026-03-10 09:03:48 -04:00

172 lines
4.4 KiB
Go

package e2e
import (
"testing"
"github.com/stretchr/testify/require"
sessionFixture "github.com/argoproj/argo-cd/v3/test/e2e/fixture/session"
)
// TestLogoutRevokesToken verifies that after logging out via the /auth/logout endpoint,
// the JWT token is revoked and can no longer be used for API calls.
func TestLogoutRevokesToken(t *testing.T) {
sessionFixture.Given(t).
When().
Login("token1").
GetUserInfo("token1").
ListAccounts("token1").
Then().
ActionShouldSucceed().
When().
Logout("token1").
GetUserInfo("token1").
ListAccounts("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
})
}
// TestLogoutDoesNotAffectOtherSessions verifies that revoking one session token
// does not invalidate a different session token for the same user.
func TestLogoutDoesNotAffectOtherSessions(t *testing.T) {
sessionFixture.Given(t).
When().
Login("token1").
Login("token2").
GetUserInfo("token1").
GetUserInfo("token2").
ListAccounts("token1").
Then().
ActionShouldSucceed().
When().
GetUserInfo("token2").
ListAccounts("token2").
Then().
ActionShouldSucceed().
When().
Logout("token1").
GetUserInfo("token1").
ListApplications("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
When().
ListApplications("token2").
Then().
ActionShouldSucceed()
}
// TestLogoutRevokedTokenCannotAccessAPIs verifies that a revoked token is rejected
// across different API endpoints, not just GetUserInfo.
func TestLogoutRevokedTokenCannotAccessAPIs(t *testing.T) {
sessionFixture.Given(t).
When().
Login("token1").
GetUserInfo("token1").
Logout("token1").
GetUserInfo("token1").
ListAccounts("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
// Project API
When().
ListProjects("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
// Repository API
When().
ListRepositories("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
// Application API
When().
ListApplications("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
})
}
// TestLogoutRevokesOIDCToken verifies that token revocation works for tokens
// issued directly by an external OIDC provider (bypassing Dex). This exercises
// the IDP token verification and revocation code path in SessionManager.VerifyToken.
func TestLogoutRevokesOIDCToken(t *testing.T) {
sessionFixture.Given(t).
When().
WithDirectOIDC().
LoginWithSSO("token1").
ListApplications("token1").
Then().
ActionShouldSucceed().
When().
Logout("token1").
ListApplications("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
})
}
// TestLogoutDoesNotAffectOtherOIDCSessions verifies that revoking one OIDC session
// token does not invalidate a different OIDC session token.
func TestLogoutDoesNotAffectOtherOIDCSessions(t *testing.T) {
sessionFixture.Given(t).
When().
WithDirectOIDC().
LoginWithSSO("token1").
LoginWithSSO("token2").
ListApplications("token1").
Then().
ActionShouldSucceed().
When().
Logout("token1").
ListApplications("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
When().
ListApplications("token2").
Then().
ActionShouldSucceed()
}
// TestLogoutRevokedOIDCTokenCannotAccessAPIs verifies that a revoked OIDC token
// is rejected across different API endpoints.
func TestLogoutRevokedOIDCTokenCannotAccessAPIs(t *testing.T) {
sessionFixture.Given(t).
When().
WithDirectOIDC().
LoginWithSSO("token1").
GetUserInfo("token1").
Logout("token1").
GetUserInfo("token1").
ListApplications("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
// Project API
When().
ListProjects("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
}).
// Repository API
When().
ListRepositories("token1").
Then().
ActionShouldFail(func(err error) {
require.Contains(t, err.Error(), "token is revoked")
})
}