diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 78f597fa55369..22bc720736148 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -515,7 +515,9 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo } var workspaceOwnerOIDCAccessToken string - if s.OIDCConfig != nil { + // The check `s.OIDCConfig != nil` is not as strict, since it can be an interface + // pointing to a typed nil. + if !reflect.ValueOf(s.OIDCConfig).IsNil() { workspaceOwnerOIDCAccessToken, err = obtainOIDCAccessToken(ctx, s.Database, s.OIDCConfig, owner.ID) if err != nil { return nil, failJob(fmt.Sprintf("obtain OIDC access token: %s", err)) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 3101346f5b43a..e5a5a1e513633 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -4349,3 +4349,51 @@ func TestWorkspaceTimings(t *testing.T) { require.Contains(t, err.Error(), "not found") }) } + +// TestOIDCRemoved emulates a user logging in with OIDC, then that OIDC +// auth method being removed. +func TestOIDCRemoved(t *testing.T) { + t.Parallel() + + owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ + IncludeProvisionerDaemon: true, + }) + first := coderdtest.CreateFirstUser(t, owner) + + user, userData := coderdtest.CreateAnotherUser(t, owner, first.OrganizationID, rbac.ScopedRoleOrgAdmin(first.OrganizationID)) + + ctx := testutil.Context(t, testutil.WaitMedium) + //nolint:gocritic // unit test + _, err := db.UpdateUserLoginType(dbauthz.AsSystemRestricted(ctx), database.UpdateUserLoginTypeParams{ + NewLoginType: database.LoginTypeOIDC, + UserID: userData.ID, + }) + require.NoError(t, err) + + //nolint:gocritic // unit test + _, err = db.InsertUserLink(dbauthz.AsSystemRestricted(ctx), database.InsertUserLinkParams{ + UserID: userData.ID, + LoginType: database.LoginTypeOIDC, + LinkedID: "random", + OAuthAccessToken: "foobar", + OAuthAccessTokenKeyID: sql.NullString{}, + OAuthRefreshToken: "refresh", + OAuthRefreshTokenKeyID: sql.NullString{}, + OAuthExpiry: time.Now().Add(time.Hour * -1), + Claims: database.UserLinkClaims{}, + }) + require.NoError(t, err) + + version := coderdtest.CreateTemplateVersion(t, owner, first.OrganizationID, nil) + _ = coderdtest.AwaitTemplateVersionJobCompleted(t, owner, version.ID) + template := coderdtest.CreateTemplate(t, owner, first.OrganizationID, version.ID) + + wrk := coderdtest.CreateWorkspace(t, user, template.ID) + coderdtest.AwaitWorkspaceBuildJobCompleted(t, owner, wrk.LatestBuild.ID) + + deleteBuild, err := owner.CreateWorkspaceBuild(ctx, wrk.ID, codersdk.CreateWorkspaceBuildRequest{ + Transition: codersdk.WorkspaceTransitionDelete, + }) + require.NoError(t, err, "delete the workspace") + coderdtest.AwaitWorkspaceBuildJobCompleted(t, owner, deleteBuild.ID) +}