mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
fix: avoid redirect loop on workspace proxies (#9389)
* fix: avoid redirect loop on workspace proxies --------- Co-authored-by: Steven Masley <stevenmasley@coder.com>
This commit is contained in:
@ -2,9 +2,13 @@ package workspaceapps_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -46,6 +50,29 @@ func Test_TokenMatchesRequest(t *testing.T) {
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "NormalizePath",
|
||||
req: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodPath,
|
||||
BasePath: "/app",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "qux",
|
||||
},
|
||||
token: workspaceapps.SignedToken{
|
||||
Request: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodPath,
|
||||
// With trailing slash
|
||||
BasePath: "/app/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "qux",
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "DifferentAccessMethod",
|
||||
req: workspaceapps.Request{
|
||||
@ -283,6 +310,62 @@ func Test_GenerateToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_FromRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("MultipleTokens", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
|
||||
// Add an invalid token
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: codersdk.SignedAppTokenCookie,
|
||||
Value: "invalid",
|
||||
})
|
||||
|
||||
token := workspaceapps.SignedToken{
|
||||
Request: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
BasePath: "/",
|
||||
UsernameOrID: "user",
|
||||
WorkspaceAndAgent: "workspace/agent",
|
||||
WorkspaceNameOrID: "workspace",
|
||||
AgentNameOrID: "agent",
|
||||
AppSlugOrPort: "app",
|
||||
},
|
||||
Expiry: time.Now().Add(time.Hour),
|
||||
UserID: uuid.New(),
|
||||
WorkspaceID: uuid.New(),
|
||||
AgentID: uuid.New(),
|
||||
AppURL: "/",
|
||||
}
|
||||
|
||||
// Add an expired cookie
|
||||
expired := token
|
||||
expired.Expiry = time.Now().Add(time.Hour * -1)
|
||||
expiredStr, err := coderdtest.AppSecurityKey.SignToken(token)
|
||||
require.NoError(t, err)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: codersdk.SignedAppTokenCookie,
|
||||
Value: expiredStr,
|
||||
})
|
||||
|
||||
// Add a valid token
|
||||
validStr, err := coderdtest.AppSecurityKey.SignToken(token)
|
||||
require.NoError(t, err)
|
||||
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: codersdk.SignedAppTokenCookie,
|
||||
Value: validStr,
|
||||
})
|
||||
|
||||
signed, ok := workspaceapps.FromRequest(r, coderdtest.AppSecurityKey)
|
||||
require.True(t, ok, "expected a token to be found")
|
||||
// Confirm it is the correct token.
|
||||
require.Equal(t, signed.UserID, token.UserID)
|
||||
})
|
||||
}
|
||||
|
||||
// The ParseToken fn is tested quite thoroughly in the GenerateToken test as
|
||||
// well.
|
||||
func Test_ParseToken(t *testing.T) {
|
||||
|
Reference in New Issue
Block a user