diff --git a/.changeset/active-devices-agent-sessions.md b/.changeset/active-devices-agent-sessions.md
new file mode 100644
index 00000000000..8efd5e0774e
--- /dev/null
+++ b/.changeset/active-devices-agent-sessions.md
@@ -0,0 +1,5 @@
+---
+'@clerk/ui': patch
+---
+
+Fix the Active devices list in `` treating Agent Task sessions as impersonation. Agent sessions no longer show the "Other impersonator device" badge, and an agent viewing the list no longer sees a red "This device" badge or "User device" badges on the user's other devices.
diff --git a/packages/ui/src/components/UserProfile/ActiveDevicesSection.tsx b/packages/ui/src/components/UserProfile/ActiveDevicesSection.tsx
index a8215cd8c94..9c5a767d9c7 100644
--- a/packages/ui/src/components/UserProfile/ActiveDevicesSection.tsx
+++ b/packages/ui/src/components/UserProfile/ActiveDevicesSection.tsx
@@ -93,8 +93,8 @@ const DeviceItem = ({ session }: { session: SessionWithActivitiesResource }) =>
const DeviceInfo = (props: { session: SessionWithActivitiesResource }) => {
const { session } = useSession();
const isCurrent = session?.id === props.session.id;
- const isCurrentlyImpersonating = !!session?.actor;
- const isImpersonationSession = !!props.session.actor;
+ const isCurrentlyImpersonating = !!session?.actor && !session.agent;
+ const isImpersonationSession = !!props.session.actor && props.session.actor.type !== 'agent';
const { city, country, browserName, browserVersion, deviceType, ipAddress, isMobile } = props.session.latestActivity;
const title = deviceType ? deviceType : isMobile ? 'Mobile device' : 'Desktop device';
const browser = `${browserName || ''} ${browserVersion || ''}`.trim() || 'Web browser';
diff --git a/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx b/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx
index 01884a4a37a..58132eb700c 100644
--- a/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx
+++ b/packages/ui/src/components/UserProfile/__tests__/SecurityPage.test.tsx
@@ -1,4 +1,4 @@
-import type { SessionWithActivitiesResource } from '@clerk/shared/types';
+import type { ActClaim, SessionWithActivitiesResource } from '@clerk/shared/types';
import { within } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
@@ -367,6 +367,48 @@ describe('SecurityPage', () => {
});
});
+ it('does not label agent sessions as impersonation', async () => {
+ const agentActor: ActClaim = { sub: 'agent_123', type: 'agent', task_id: 'agt_task_123' };
+ const makeSession = (id: string, deviceType: string, actor: ActClaim | null) =>
+ ({
+ pathRoot: '/me/sessions',
+ id,
+ status: 'active',
+ expireAt: '2022-12-01T01:55:44.636Z',
+ abandonAt: '2022-12-24T01:55:44.636Z',
+ lastActiveAt: '2022-11-24T12:11:49.328Z',
+ latestActivity: {
+ id: `sess_activity_${id}`,
+ deviceType,
+ browserName: 'Chrome',
+ browserVersion: '107.0.0.0',
+ country: 'Greece',
+ city: 'Athens',
+ isMobile: false,
+ },
+ actor,
+ revoke: vi.fn().mockResolvedValue({}),
+ }) as any as SessionWithActivitiesResource;
+
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withUser({ email_addresses: ['test@clerk.com'], actor: agentActor });
+ });
+ fixtures.clerk.user!.getSessions.mockReturnValue(
+ Promise.resolve([
+ makeSession(fixtures.clerk.session!.id, 'Macintosh', agentActor),
+ makeSession('sess_agent', 'Macintosh', { ...agentActor, task_id: 'agt_task_456' }),
+ makeSession('sess_impersonator', 'Windows', { sub: 'user_impersonator' }),
+ makeSession('sess_user', 'Macintosh', null),
+ ]),
+ );
+
+ render(, { wrapper });
+
+ expect(await screen.findByText('This device')).toHaveAttribute('data-color', 'primary');
+ expect(screen.getByText('Other impersonator device').parentElement).toHaveTextContent('Windows');
+ expect(screen.queryByText('User device')).not.toBeInTheDocument();
+ });
+
it('does not leak the previous user device activity across a user switch', async () => {
const makeSession = (sessionId: string, city: string) =>
({