From c9599f28051e5ff5f941dc41c1ebc7f52676d20a Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 7 Feb 2025 14:11:12 -0600 Subject: [PATCH 1/7] chore: prevent non-unqiue oidc subjects from authenticating Any IdP returning an empty field here breaks the assumption of a unique subject id. This is defined in the OIDC spec. --- coderd/userauth.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/coderd/userauth.go b/coderd/userauth.go index c5e95e44998b2..12b89cfe808e5 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -1096,6 +1096,15 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { return } + if idToken.Subject == "" { + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: "OIDC token missing 'sub' claim field or 'sub' claim field is empty.", + Detail: "'sub' claim field is required to be unique for all users by a given issue, " + + "an empty field is invalid and this authentication attempt is rejected.", + }) + return + } + logger := api.Logger.Named(userAuthLoggerName) // "email_verified" is an optional claim that changes the behavior From 846a50a0d0777686538ab87f8e27069105657a3d Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 7 Feb 2025 14:50:20 -0600 Subject: [PATCH 2/7] also log --- coderd/userauth.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/coderd/userauth.go b/coderd/userauth.go index 12b89cfe808e5..15eea78b5bc8c 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -1096,15 +1096,6 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { return } - if idToken.Subject == "" { - httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "OIDC token missing 'sub' claim field or 'sub' claim field is empty.", - Detail: "'sub' claim field is required to be unique for all users by a given issue, " + - "an empty field is invalid and this authentication attempt is rejected.", - }) - return - } - logger := api.Logger.Named(userAuthLoggerName) // "email_verified" is an optional claim that changes the behavior @@ -1121,6 +1112,20 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { return } + if idToken.Subject == "" { + logger.Error(ctx, "oauth2: missing 'sub' claim field in OIDC token", + slog.F("source", "id_token"), + slog.F("claim_fields", claimFields(idtokenClaims)), + slog.F("blank", blankFields(idtokenClaims)), + ) + httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ + Message: "OIDC token missing 'sub' claim field or 'sub' claim field is empty.", + Detail: "'sub' claim field is required to be unique for all users by a given issue, " + + "an empty field is invalid and this authentication attempt is rejected.", + }) + return + } + logger.Debug(ctx, "got oidc claims", slog.F("source", "id_token"), slog.F("claim_fields", claimFields(idtokenClaims)), From 08ea3e40eda508df9109a1b426bd9ff2c1e0d927 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 7 Feb 2025 15:00:26 -0600 Subject: [PATCH 3/7] test: add unit tests --- coderd/userauth_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index f0668507e38ba..ef585de3b0d1a 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -899,10 +899,19 @@ func TestUserOIDC(t *testing.T) { IgnoreEmailVerified bool IgnoreUserInfo bool }{ + { + Name: "NoSub", + IDTokenClaims: jwt.MapClaims{ + "email": "kyle@kwc.io", + }, + AllowSignups: true, + StatusCode: http.StatusBadRequest, + }, { Name: "EmailOnly", IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusOK, @@ -915,6 +924,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": false, + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusForbidden, @@ -924,6 +934,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": 3.14159, "email_verified": false, + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusBadRequest, @@ -933,6 +944,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": false, + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusOK, @@ -946,6 +958,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, EmailDomain: []string{ @@ -958,6 +971,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "cian@coder.com", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, EmailDomain: []string{ @@ -970,6 +984,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, EmailDomain: []string{ @@ -982,6 +997,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@KWC.io", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, AssertUser: func(t testing.TB, u codersdk.User) { @@ -997,6 +1013,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "colin@gmail.com", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, EmailDomain: []string{ @@ -1015,6 +1032,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": true, + "sub": uuid.NewString(), }, StatusCode: http.StatusForbidden, }, @@ -1023,6 +1041,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": true, + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "kyle", u.Username) @@ -1036,6 +1055,7 @@ func TestUserOIDC(t *testing.T) { "email": "kyle@kwc.io", "email_verified": true, "preferred_username": "hotdog", + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "hotdog", u.Username) @@ -1049,6 +1069,7 @@ func TestUserOIDC(t *testing.T) { "email": "kyle@kwc.io", "email_verified": true, "name": "Hot Dog", + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "Hot Dog", u.Name) @@ -1065,6 +1086,7 @@ func TestUserOIDC(t *testing.T) { // However, we should not fail to log someone in if their name is too long. // Just truncate it. "name": strings.Repeat("a", 129), + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusOK, @@ -1080,6 +1102,7 @@ func TestUserOIDC(t *testing.T) { // Full names must not have leading or trailing whitespace, but this is a // daft reason to fail a login. "name": " Bobby Whitespace ", + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusOK, @@ -1096,6 +1119,7 @@ func TestUserOIDC(t *testing.T) { "email_verified": true, "name": "Kylium Carbonate", "preferred_username": "kyle@kwc.io", + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "kyle", u.Username) @@ -1108,6 +1132,7 @@ func TestUserOIDC(t *testing.T) { Name: "UsernameIsEmail", IDTokenClaims: jwt.MapClaims{ "preferred_username": "kyle@kwc.io", + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "kyle", u.Username) @@ -1123,6 +1148,7 @@ func TestUserOIDC(t *testing.T) { "email_verified": true, "preferred_username": "kyle", "picture": "/example.png", + "sub": uuid.NewString(), }, AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "/example.png", u.AvatarURL) @@ -1136,6 +1162,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "kyle@kwc.io", "email_verified": true, + "sub": uuid.NewString(), }, UserInfoClaims: jwt.MapClaims{ "preferred_username": "potato", @@ -1155,6 +1182,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "coolin@coder.com", "groups": []string{"pingpong"}, + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusOK, @@ -1164,6 +1192,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "internaluser@internal.domain", "email_verified": false, + "sub": uuid.NewString(), }, UserInfoClaims: jwt.MapClaims{ "email": "externaluser@external.domain", @@ -1182,6 +1211,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "internaluser@internal.domain", "email_verified": false, + "sub": uuid.NewString(), }, UserInfoClaims: jwt.MapClaims{ "email": 1, @@ -1197,6 +1227,7 @@ func TestUserOIDC(t *testing.T) { "email_verified": true, "name": "User McName", "preferred_username": "user", + "sub": uuid.NewString(), }, UserInfoClaims: jwt.MapClaims{ "email": "user.mcname@external.domain", @@ -1216,6 +1247,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: inflateClaims(t, jwt.MapClaims{ "email": "user@domain.tld", "email_verified": true, + "sub": uuid.NewString(), }, 65536), AssertUser: func(t testing.TB, u codersdk.User) { assert.Equal(t, "user", u.Username) @@ -1228,6 +1260,7 @@ func TestUserOIDC(t *testing.T) { IDTokenClaims: jwt.MapClaims{ "email": "user@domain.tld", "email_verified": true, + "sub": uuid.NewString(), }, UserInfoClaims: inflateClaims(t, jwt.MapClaims{}, 65536), AssertUser: func(t testing.TB, u codersdk.User) { @@ -1242,6 +1275,7 @@ func TestUserOIDC(t *testing.T) { "iss": "https://mismatch.com", "email": "user@domain.tld", "email_verified": true, + "sub": uuid.NewString(), }, AllowSignups: true, StatusCode: http.StatusBadRequest, From 3a69f1a9aa49ad4746fd923b1ed4390ee716073a Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 7 Feb 2025 15:22:03 -0600 Subject: [PATCH 4/7] fix tests without subjects --- enterprise/coderd/userauth_test.go | 32 +++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/enterprise/coderd/userauth_test.go b/enterprise/coderd/userauth_test.go index d3e997608f316..267e1168f84cf 100644 --- a/enterprise/coderd/userauth_test.go +++ b/enterprise/coderd/userauth_test.go @@ -50,6 +50,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "alice@coder.com", + "sub": uuid.NewString(), } // Login a new client that signs up @@ -82,6 +83,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "alice@coder.com", + "sub": uuid.NewString(), } // Login a new client that signs up @@ -152,9 +154,11 @@ func TestUserOIDC(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedSettings.Field, settings.Field) + sub := uuid.NewString() claims := jwt.MapClaims{ "email": "alice@coder.com", "organization": []string{"first", "second"}, + "sub": sub, } // Then: a new user logs in with claims "second" and "third", they @@ -169,7 +173,7 @@ func TestUserOIDC(t *testing.T) { fields, err := runner.AdminClient.GetAvailableIDPSyncFields(ctx) require.NoError(t, err) require.ElementsMatch(t, []string{ - "aud", "exp", "iss", // Always included from jwt + "sub", "aud", "exp", "iss", // Always included from jwt "email", "organization", }, fields) @@ -204,6 +208,7 @@ func TestUserOIDC(t *testing.T) { runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", "organization": []string{"second"}, + "sub": sub, }) runner.AssertOrganizations(t, "alice", true, []uuid.UUID{orgTwo.ID}) }) @@ -238,10 +243,12 @@ func TestUserOIDC(t *testing.T) { }) fourth := dbgen.Organization(t, runner.API.Database, database.Organization{}) + sub := uuid.NewString() ctx := testutil.Context(t, testutil.WaitMedium) claims := jwt.MapClaims{ "email": "alice@coder.com", "organization": []string{"second", "third"}, + "sub": sub, } // Then: a new user logs in with claims "second" and "third", they @@ -265,6 +272,7 @@ func TestUserOIDC(t *testing.T) { runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", "organization": []string{"third"}, + "sub": sub, }) runner.AssertOrganizations(t, "alice", false, []uuid.UUID{third}) }) @@ -289,6 +297,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "alice@coder.com", + "sub": uuid.NewString(), } // Login a new client that signs up client, resp := runner.Login(t, claims) @@ -328,6 +337,7 @@ func TestUserOIDC(t *testing.T) { // This is sent as a **string** intentionally instead // of an array. "roles": oidcRoleName, + "sub": uuid.NewString(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertRoles(t, "alice", []string{rbac.RoleTemplateAdmin().String()}) @@ -398,9 +408,11 @@ func TestUserOIDC(t *testing.T) { }) // User starts with the owner role + sub := uuid.NewString() _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", "roles": []string{"random", oidcRoleName, rbac.RoleOwner().String()}, + "sub": sub, }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertRoles(t, "alice", []string{rbac.RoleTemplateAdmin().String(), rbac.RoleUserAdmin().String(), rbac.RoleOwner().String()}) @@ -409,6 +421,7 @@ func TestUserOIDC(t *testing.T) { _, resp = runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", "roles": []string{"random"}, + "sub": sub, }) require.Equal(t, http.StatusOK, resp.StatusCode) @@ -429,9 +442,11 @@ func TestUserOIDC(t *testing.T) { }, }) + sub := uuid.NewString() _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", "roles": []string{}, + "sub": sub, }) require.Equal(t, http.StatusOK, resp.StatusCode) // Try to manually update user roles, even though controlled by oidc @@ -476,6 +491,7 @@ func TestUserOIDC(t *testing.T) { _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{groupName}, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{groupName}) @@ -510,6 +526,7 @@ func TestUserOIDC(t *testing.T) { _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{oidcGroupName}, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{coderGroupName}) @@ -546,6 +563,7 @@ func TestUserOIDC(t *testing.T) { client, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{groupName}, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{groupName}) @@ -579,9 +597,11 @@ func TestUserOIDC(t *testing.T) { require.NoError(t, err) require.Len(t, group.Members, 0) + sub := uuid.NewString() _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{groupName}, + "sub": sub, }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{groupName}) @@ -589,6 +609,7 @@ func TestUserOIDC(t *testing.T) { // Refresh without the group claim _, resp = runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", + "sub": sub, }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{}) @@ -612,6 +633,7 @@ func TestUserOIDC(t *testing.T) { _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{"not-exists"}, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{}) @@ -637,6 +659,7 @@ func TestUserOIDC(t *testing.T) { _, resp := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{groupName}, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{groupName}) @@ -665,6 +688,7 @@ func TestUserOIDC(t *testing.T) { // This is sent as a **string** intentionally instead // of an array. groupClaim: groupName, + "sub": uuid.New(), }) require.Equal(t, http.StatusOK, resp.StatusCode) runner.AssertGroups(t, "alice", []string{groupName}) @@ -686,9 +710,11 @@ func TestUserOIDC(t *testing.T) { }) // Test forbidden + sub := uuid.NewString() _, resp := runner.AttemptLogin(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{"not-allowed"}, + "sub": sub, }) require.Equal(t, http.StatusForbidden, resp.StatusCode) @@ -696,6 +722,7 @@ func TestUserOIDC(t *testing.T) { client, _ := runner.Login(t, jwt.MapClaims{ "email": "alice@coder.com", groupClaim: []string{allowedGroup}, + "sub": sub, }) ctx := testutil.Context(t, testutil.WaitShort) @@ -719,6 +746,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "alice@coder.com", + "sub": uuid.NewString(), } // Login a new client that signs up client, resp := runner.Login(t, claims) @@ -747,6 +775,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "alice@coder.com", + "sub": uuid.NewString(), } // Login a new client that signs up client, resp := runner.Login(t, claims) @@ -921,6 +950,7 @@ func TestGroupSync(t *testing.T) { require.NoError(t, err, "user must be oidc type") // Log in the new user + tc.claims["sub"] = uuid.NewString() tc.claims["email"] = user.Email _, resp := runner.Login(t, tc.claims) require.Equal(t, http.StatusOK, resp.StatusCode) From 29314e413cf8e138bf28c37db3beab0c8dfb5553 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 10 Feb 2025 08:52:17 -0600 Subject: [PATCH 5/7] add sub field to more tests --- enterprise/coderd/scim_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/enterprise/coderd/scim_test.go b/enterprise/coderd/scim_test.go index a8d5c67ed4c0d..5396180b4a0d0 100644 --- a/enterprise/coderd/scim_test.go +++ b/enterprise/coderd/scim_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/golang-jwt/jwt/v4" + "github.com/google/uuid" "github.com/imulab/go-scim/pkg/v2/handlerutil" "github.com/imulab/go-scim/pkg/v2/spec" "github.com/stretchr/testify/assert" @@ -568,6 +569,7 @@ func TestScim(t *testing.T) { //nolint:bodyclose scimUserClient, _ := fake.Login(t, client, jwt.MapClaims{ "email": sUser.Emails[0].Value, + "sub": uuid.NewString(), }) scimUser, err = scimUserClient.User(ctx, codersdk.Me) require.NoError(t, err) @@ -836,6 +838,7 @@ func TestScim(t *testing.T) { //nolint:bodyclose scimUserClient, _ := fake.Login(t, client, jwt.MapClaims{ "email": sUser.Emails[0].Value, + "sub": uuid.NewString(), }) scimUser, err = scimUserClient.User(ctx, codersdk.Me) require.NoError(t, err) From ae4fe6f8b8010773ee1b8c688dac67e027ebe2b9 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 10 Feb 2025 09:02:39 -0600 Subject: [PATCH 6/7] add sub field to more tests --- coderd/oauthpki/okidcpki_test.go | 2 ++ coderd/userauth_test.go | 2 ++ coderd/users_test.go | 1 + 3 files changed, 5 insertions(+) diff --git a/coderd/oauthpki/okidcpki_test.go b/coderd/oauthpki/okidcpki_test.go index 144cb32901088..509da563a9145 100644 --- a/coderd/oauthpki/okidcpki_test.go +++ b/coderd/oauthpki/okidcpki_test.go @@ -13,6 +13,7 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/golang-jwt/jwt/v4" + "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/oauth2" @@ -169,6 +170,7 @@ func TestAzureAKPKIWithCoderd(t *testing.T) { const email = "alice@coder.com" claims := jwt.MapClaims{ "email": email, + "sub": uuid.NewString(), } helper := oidctest.NewLoginHelper(owner, fake) user, _ := helper.Login(t, claims) diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index ef585de3b0d1a..a90d389275844 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -72,6 +72,7 @@ func TestOIDCOauthLoginWithExisting(t *testing.T) { "email": "alice@coder.com", "email_verified": true, "preferred_username": username, + "sub": uuid.NewString(), } helper := oidctest.NewLoginHelper(client, fake) @@ -1828,6 +1829,7 @@ func TestOIDCSkipIssuer(t *testing.T) { userClient, _ := fake.Login(t, owner, jwt.MapClaims{ "iss": secondaryURLString, "email": "alice@coder.com", + "sub": uuid.NewString(), }) found, err := userClient.User(ctx, "me") require.NoError(t, err) diff --git a/coderd/users_test.go b/coderd/users_test.go index 53ec98b30d911..74c27da7ef6f5 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -831,6 +831,7 @@ func TestPostUsers(t *testing.T) { // Try to log in with OIDC. userClient, _ := fake.Login(t, client, jwt.MapClaims{ "email": email, + "sub": uuid.NewString(), }) found, err := userClient.User(ctx, "me") From ade4eb4ceaff9f07649ffcd9a7bd448c68190d44 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 10 Feb 2025 09:14:45 -0600 Subject: [PATCH 7/7] add sub field to more tests --- coderd/userauth_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index a90d389275844..b0a4dd80efa03 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -1366,6 +1366,7 @@ func TestUserOIDC(t *testing.T) { client, resp := fake.AttemptLogin(t, owner, jwt.MapClaims{ "email": user.Email, + "sub": uuid.NewString(), }) require.Equal(t, http.StatusOK, resp.StatusCode) @@ -1404,6 +1405,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": userData.Email, + "sub": uuid.NewString(), } var err error user.HTTPClient.Jar, err = cookiejar.New(nil) @@ -1474,6 +1476,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": userData.Email, + "sub": uuid.NewString(), } user.HTTPClient.Jar, err = cookiejar.New(nil) require.NoError(t, err) @@ -1544,6 +1547,7 @@ func TestUserOIDC(t *testing.T) { numLogs := len(auditor.AuditLogs()) claims := jwt.MapClaims{ "email": "jon@coder.com", + "sub": uuid.NewString(), } userClient, _ := fake.Login(t, client, claims) @@ -1664,6 +1668,7 @@ func TestUserOIDC(t *testing.T) { claims := jwt.MapClaims{ "email": "user@example.com", "email_verified": true, + "sub": uuid.NewString(), } // Perform the login