diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx index 7b697092f7c62..052af8793f406 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.story.tsx @@ -44,6 +44,7 @@ const doc: types.DocumentAuthorizeWebSession = { redirectUri: '', token: '', id: '', + username: 'alice', }, }; @@ -62,6 +63,31 @@ export function DeviceNotTrusted() { ); } +export function RequestedUserNotLoggedIn() { + const rootCluster = makeRootCluster({ + loggedInUser: makeLoggedInUser({ isDeviceTrusted: true }), + }); + const docForDifferentUser: types.DocumentAuthorizeWebSession = { + ...doc, + webSessionRequest: { + ...doc.webSessionRequest, + username: 'bob', + }, + }; + const appContext = new MockAppContext(); + appContext.clustersService.setState(draftState => { + draftState.clusters.set(rootCluster.uri, rootCluster); + }); + + return ( + + + + + + ); +} + export function DeviceTrusted() { const rootCluster = makeRootCluster({ loggedInUser: makeLoggedInUser({ isDeviceTrusted: true }), diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx index c06ff109ff93c..67f47026cde36 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.test.tsx @@ -40,10 +40,11 @@ const doc: types.DocumentAuthorizeWebSession = { redirectUri: '', token: '', id: '', + username: 'alice', }, }; -test('authorize button is disabled when device is not trusted', async () => { +test('warning is visible and authorize button is disabled when device is not trusted', async () => { const rootCluster = makeRootCluster({ loggedInUser: makeLoggedInUser({ isDeviceTrusted: false }), }); @@ -64,6 +65,29 @@ test('authorize button is disabled when device is not trusted', async () => { expect(await screen.findByText(/Authorize Session/)).toBeDisabled(); }); +test('warning is visible and authorize button is disabled when requested user is not logged in', async () => { + const rootCluster = makeRootCluster({ + loggedInUser: makeLoggedInUser({ isDeviceTrusted: true, name: 'bob' }), + }); + const appContext = new MockAppContext(); + appContext.clustersService.setState(draftState => { + draftState.clusters.set(rootCluster.uri, rootCluster); + }); + + render( + + + + + + ); + + expect( + await screen.findByText(/Requested user is not logged in/) + ).toBeVisible(); + expect(await screen.findByText(/Authorize Session/)).toBeDisabled(); +}); + test('authorizing a session opens its URL and closes document', async () => { jest.spyOn(window, 'open').mockImplementation(); const rootCluster = makeRootCluster({ diff --git a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx index fa85eb296c48b..92331f996fd9c 100644 --- a/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx +++ b/web/packages/teleterm/src/ui/DocumentAuthorizeWebSession/DocumentAuthorizeWebSession.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Text, Alert, ButtonPrimary, H1, ButtonText } from 'design'; +import { Text, Alert, ButtonPrimary, H1, ButtonText, Link } from 'design'; import Flex from 'design/Flex'; import { useAsync, Attempt } from 'shared/hooks/useAsync'; import { processRedirectUri } from 'shared/redirects'; @@ -50,7 +50,10 @@ export function DocumentAuthorizeWebSession(props: { return confirmationToken; }); const clusterName = routing.parseClusterName(props.doc.rootClusterUri); - const canAuthorize = rootCluster.loggedInUser?.isDeviceTrusted; + const isDeviceTrusted = rootCluster.loggedInUser?.isDeviceTrusted; + const isRequestedUserLoggedIn = + props.doc.webSessionRequest.username === rootCluster.loggedInUser?.name; + const canAuthorize = isDeviceTrusted && isRequestedUserLoggedIn; async function authorizeAndCloseDocument() { const [confirmationToken, error] = await authorize(); @@ -95,7 +98,7 @@ export function DocumentAuthorizeWebSession(props: {

Authorize Web Session

{/*It's technically possible to open a deep link to authorize a session on a device that is not enrolled.*/} - {!canAuthorize && ( + {!isDeviceTrusted && ( This device is not trusted. @@ -111,6 +114,32 @@ export function DocumentAuthorizeWebSession(props: { )} + {!isRequestedUserLoggedIn && ( + + + Requested user is not logged in. +
+ You are logged in as {rootCluster.loggedInUser?.name}. To + authorize this web session request, please{' '} + { + ctx.commandLauncher.executeCommand('cluster-logout', { + clusterUri: rootCluster.uri, + }); + }} + > + log out + {' '} + in Teleport Connect and log in again as{' '} + {props.doc.webSessionRequest.username}. +
+ Then click Launch Teleport Connect again in the browser. +
+
+ )} {authorizeAttempt.status === 'error' && ( Could not authorize the session: {authorizeAttempt.statusText} diff --git a/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts b/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts index 6083df679f626..ea98c9a51ef40 100644 --- a/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts +++ b/web/packages/teleterm/src/ui/services/deepLinks/deepLinksService.ts @@ -117,6 +117,7 @@ export class DeepLinksService { webSessionRequest: { id, token, + username: url.username, redirectUri: redirect_uri, }, }); diff --git a/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts b/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts index 0c7fd36952285..00238ae5b35fd 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/documentsService/types.ts @@ -237,6 +237,7 @@ export interface DocumentAuthorizeWebSession extends DocumentBase { export interface WebSessionRequest { id: string; token: string; + username: string; redirectUri: string; } diff --git a/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts b/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts index ded2d08080df5..ccb1add834217 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/workspacesService.test.ts @@ -218,6 +218,7 @@ describe('state persistence', () => { id: '', token: '', redirectUri: '', + username: '', }, }, ],