chore(coderd): add tests for big oidc tokens (#12424)

- Adds two test cases for a 64k+ ID token and a 64k+ userinfo payload.
- Reformats the entire test cases array as instructed by CI
This commit is contained in:
Cian Johnston 2024-03-05 14:46:00 +00:00 committed by GitHub
parent b1f9a6dc31
commit 4343998c37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 229 additions and 176 deletions

View File

@ -19,6 +19,7 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/coderd"
"github.com/coder/coder/v2/coderd/audit"
@ -30,6 +31,7 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/promoauth"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/cryptorand"
"github.com/coder/coder/v2/testutil"
)
@ -742,7 +744,8 @@ func TestUserOIDC(t *testing.T) {
StatusCode int
IgnoreEmailVerified bool
IgnoreUserInfo bool
}{{
}{
{
Name: "EmailOnly",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -750,7 +753,8 @@ func TestUserOIDC(t *testing.T) {
AllowSignups: true,
StatusCode: http.StatusOK,
Username: "kyle",
}, {
},
{
Name: "EmailNotVerified",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -758,7 +762,8 @@ func TestUserOIDC(t *testing.T) {
},
AllowSignups: true,
StatusCode: http.StatusForbidden,
}, {
},
{
Name: "EmailNotAString",
IDTokenClaims: jwt.MapClaims{
"email": 3.14159,
@ -766,7 +771,8 @@ func TestUserOIDC(t *testing.T) {
},
AllowSignups: true,
StatusCode: http.StatusBadRequest,
}, {
},
{
Name: "EmailNotVerifiedIgnored",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -776,7 +782,8 @@ func TestUserOIDC(t *testing.T) {
StatusCode: http.StatusOK,
Username: "kyle",
IgnoreEmailVerified: true,
}, {
},
{
Name: "NotInRequiredEmailDomain",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -787,7 +794,8 @@ func TestUserOIDC(t *testing.T) {
"coder.com",
},
StatusCode: http.StatusForbidden,
}, {
},
{
Name: "EmailDomainCaseInsensitive",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@KWC.io",
@ -798,7 +806,8 @@ func TestUserOIDC(t *testing.T) {
"kwc.io",
},
StatusCode: http.StatusOK,
}, {
},
{
Name: "EmailDomainSubset",
IDTokenClaims: jwt.MapClaims{
"email": "colin@gmail.com",
@ -809,19 +818,22 @@ func TestUserOIDC(t *testing.T) {
"mail.com",
},
StatusCode: http.StatusForbidden,
}, {
},
{
Name: "EmptyClaims",
IDTokenClaims: jwt.MapClaims{},
AllowSignups: true,
StatusCode: http.StatusBadRequest,
}, {
},
{
Name: "NoSignups",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
"email_verified": true,
},
StatusCode: http.StatusForbidden,
}, {
},
{
Name: "UsernameFromEmail",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -830,7 +842,8 @@ func TestUserOIDC(t *testing.T) {
Username: "kyle",
AllowSignups: true,
StatusCode: http.StatusOK,
}, {
},
{
Name: "UsernameFromClaims",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -840,7 +853,8 @@ func TestUserOIDC(t *testing.T) {
Username: "hotdog",
AllowSignups: true,
StatusCode: http.StatusOK,
}, {
},
{
// Services like Okta return the email as the username:
// https://developer.okta.com/docs/reference/api/oidc/#base-claims-always-present
Name: "UsernameAsEmail",
@ -852,7 +866,8 @@ func TestUserOIDC(t *testing.T) {
Username: "kyle",
AllowSignups: true,
StatusCode: http.StatusOK,
}, {
},
{
// See: https://github.com/coder/coder/issues/4472
Name: "UsernameIsEmail",
IDTokenClaims: jwt.MapClaims{
@ -861,7 +876,8 @@ func TestUserOIDC(t *testing.T) {
Username: "kyle",
AllowSignups: true,
StatusCode: http.StatusOK,
}, {
},
{
Name: "WithPicture",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -873,7 +889,8 @@ func TestUserOIDC(t *testing.T) {
AllowSignups: true,
AvatarURL: "/example.png",
StatusCode: http.StatusOK,
}, {
},
{
Name: "WithUserInfoClaims",
IDTokenClaims: jwt.MapClaims{
"email": "kyle@kwc.io",
@ -887,7 +904,8 @@ func TestUserOIDC(t *testing.T) {
AllowSignups: true,
AvatarURL: "/example.png",
StatusCode: http.StatusOK,
}, {
},
{
Name: "GroupsDoesNothing",
IDTokenClaims: jwt.MapClaims{
"email": "coolin@coder.com",
@ -895,7 +913,8 @@ func TestUserOIDC(t *testing.T) {
},
AllowSignups: true,
StatusCode: http.StatusOK,
}, {
},
{
Name: "UserInfoOverridesIDTokenClaims",
IDTokenClaims: jwt.MapClaims{
"email": "internaluser@internal.domain",
@ -910,7 +929,8 @@ func TestUserOIDC(t *testing.T) {
AllowSignups: true,
IgnoreEmailVerified: false,
StatusCode: http.StatusOK,
}, {
},
{
Name: "InvalidUserInfo",
IDTokenClaims: jwt.MapClaims{
"email": "internaluser@internal.domain",
@ -922,7 +942,8 @@ func TestUserOIDC(t *testing.T) {
AllowSignups: true,
IgnoreEmailVerified: false,
StatusCode: http.StatusInternalServerError,
}, {
},
{
Name: "IgnoreUserInfo",
IDTokenClaims: jwt.MapClaims{
"email": "user@internal.domain",
@ -937,7 +958,29 @@ func TestUserOIDC(t *testing.T) {
IgnoreUserInfo: true,
AllowSignups: true,
StatusCode: http.StatusOK,
}} {
},
{
Name: "HugeIDToken",
IDTokenClaims: inflateClaims(t, jwt.MapClaims{
"email": "user@domain.tld",
"email_verified": true,
}, 65536),
Username: "user",
AllowSignups: true,
StatusCode: http.StatusOK,
},
{
Name: "HugeClaims",
IDTokenClaims: jwt.MapClaims{
"email": "user@domain.tld",
"email_verified": true,
},
UserInfoClaims: inflateClaims(t, jwt.MapClaims{}, 65536),
Username: "user",
AllowSignups: true,
StatusCode: http.StatusOK,
},
} {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
@ -956,7 +999,7 @@ func TestUserOIDC(t *testing.T) {
})
auditor := audit.NewMock()
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true})
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
owner := coderdtest.New(t, &coderdtest.Options{
Auditor: auditor,
OIDCConfig: cfg,
@ -1287,3 +1330,13 @@ func authCookieValue(cookies []*http.Cookie) string {
}
return ""
}
// inflateClaims 'inflates' a jwt.MapClaims from a seed by
// adding a ridiculously large key-value pair of length size.
func inflateClaims(t testing.TB, seed jwt.MapClaims, size int) jwt.MapClaims {
t.Helper()
junk, err := cryptorand.String(size)
require.NoError(t, err)
seed["random_data"] = junk
return seed
}