From f3ebea1c30071188718834a2d0ed251b09c84fb1 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Wed, 21 Aug 2024 20:32:41 +0300 Subject: [PATCH] Remove the undocumented login-with-token page There are several problems with this feature: 1. To use it, you have to put the user's token in the URL. This token lasts forever (unless the user explicitly logs out), so it is nearly as sensitive as the user's password. Embedding such sensitive information in the URL is problematic, because URLs are saved in the browser history, dumped to server logs and displayed on the screen, none of which are secure locations. A user could also accidentally share a URL with an embedded token. 2. If an attacker can get a user to follow a malicious link, they could forcibly log that user into the attacker's account (AKA "login CSRF"). This by itself is just a nuisance, but the attacker could potentially use this to trick the victim into, for example, uploading confidential data to the attacker's account. 3. By design, it requires the use of token authentication, whose drawbacks I have explained in #8289. In fairness, when originally implemented, this feature set the session cookie rather than the token, but this cannot work if the user is already logged in, as the `sessionid` cookie is marked `HTTPOnly` and cannot be overridden by JavaScript. So the only way for this feature to work in all circumstances is to set the token. Generally, the use cases of this feature are better served by single sign-on protocols, which don't suffer from these drawbacks. --- ...240822_134319_roman_rm_login_with_token.md | 4 +++ cvat-ui/package.json | 2 +- cvat-ui/src/components/cvat-app.tsx | 11 -------- .../login-with-token/login-with-token.tsx | 25 ------------------- .../actions_users/issue_1810_login_logout.js | 18 ------------- 5 files changed, 5 insertions(+), 55 deletions(-) create mode 100644 changelog.d/20240822_134319_roman_rm_login_with_token.md delete mode 100644 cvat-ui/src/components/login-with-token/login-with-token.tsx diff --git a/changelog.d/20240822_134319_roman_rm_login_with_token.md b/changelog.d/20240822_134319_roman_rm_login_with_token.md new file mode 100644 index 000000000000..45d1631c8931 --- /dev/null +++ b/changelog.d/20240822_134319_roman_rm_login_with_token.md @@ -0,0 +1,4 @@ +### Removed + +- Removed the `/auth/login-with-token` page + () diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 89baa2e1dfa9..4f46788fb2a9 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.64.6", + "version": "1.65.0", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index c9ebea4d12ea..1282ac21bcaf 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -17,7 +17,6 @@ import Text from 'antd/lib/typography/Text'; import LogoutComponent from 'components/logout-component'; import LoginPageContainer from 'containers/login-page/login-page'; -import LoginWithTokenComponent from 'components/login-with-token/login-with-token'; import RegisterPageContainer from 'containers/register-page/register-page'; import ResetPasswordPageConfirmComponent from 'components/reset-password-confirm-page/reset-password-confirm-page'; import ResetPasswordPageComponent from 'components/reset-password-page/reset-password-page'; @@ -501,11 +500,6 @@ class CVATApplication extends React.PureComponent - @@ -590,11 +584,6 @@ class CVATApplication extends React.PureComponent - {isPasswordResetEnabled && ( )} diff --git a/cvat-ui/src/components/login-with-token/login-with-token.tsx b/cvat-ui/src/components/login-with-token/login-with-token.tsx deleted file mode 100644 index bdfbdbf5244d..000000000000 --- a/cvat-ui/src/components/login-with-token/login-with-token.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2022-2023 CVAT.ai Corporation -// -// SPDX-License-Identifier: MIT - -import React, { useEffect } from 'react'; -import LoadingSpinner from 'components/common/loading-spinner'; -import { useParams, useLocation } from 'react-router'; - -export default function LoginWithTokenComponent(): JSX.Element { - const location = useLocation(); - const { token } = useParams<{ token: string }>(); - const search = new URLSearchParams(location.search); - - useEffect( - () => { - localStorage.setItem('token', token); - const next = search.get('next') ?? '/'; - (window as Window).location = next; - }, - [token], - ); - - return (); -} diff --git a/tests/cypress/e2e/actions_users/issue_1810_login_logout.js b/tests/cypress/e2e/actions_users/issue_1810_login_logout.js index 391c04b1a1f8..8f7b7e368679 100644 --- a/tests/cypress/e2e/actions_users/issue_1810_login_logout.js +++ b/tests/cypress/e2e/actions_users/issue_1810_login_logout.js @@ -58,24 +58,6 @@ context('When clicking on the Logout button, get the user session closed.', () = cy.contains('.cvat-task-details-task-name', `${taskName}`).should('be.visible'); }); - it('Logout and login to task via token', () => { - cy.logout(); - // get token and login to task - cy.request({ - method: 'POST', - url: '/api/auth/login', - body: { - username: Cypress.env('user'), - email: Cypress.env('email'), - password: Cypress.env('password'), - }, - }).then(async (response) => { - const token = response.body.key; - cy.visit(`/auth/login-with-token/${token}?next=/tasks/${taskId}`); - cy.contains('.cvat-task-details-task-name', `${taskName}`).should('be.visible'); - }); - }); - it('Login via email', () => { cy.logout(); login(Cypress.env('email'), Cypress.env('password'));