diff --git a/packages/asc-web-common/api/settings/index.js b/packages/asc-web-common/api/settings/index.js index ecedbfcaf2..19df9888dd 100644 --- a/packages/asc-web-common/api/settings/index.js +++ b/packages/asc-web-common/api/settings/index.js @@ -376,7 +376,7 @@ export function getTfaSettings() { export function setTfaSettings(type) { return request({ method: "put", - url: "/settings/tfaapp", + url: "/settings/tfaappwithlink", data: { type: type }, }); } @@ -424,17 +424,21 @@ export function getTfaSecretKeyAndQR(confirmKey = null) { return request(options); } -export function validateTfaCode(code) { +export function validateTfaCode(code, confirmKey = null) { const data = { code, }; - return request({ + const options = { method: "post", url: "/settings/tfaapp/validate", skipLogout: true, data, - }); + }; + + if (confirmKey) options.headers = { confirm: confirmKey }; + + return request(options); } export function getBackupStorage() { diff --git a/packages/asc-web-common/store/AuthStore.js b/packages/asc-web-common/store/AuthStore.js index 7ed6702ee1..334449edf4 100644 --- a/packages/asc-web-common/store/AuthStore.js +++ b/packages/asc-web-common/store/AuthStore.js @@ -53,6 +53,8 @@ class AuthStore { if (this.isAuthenticated && !skipModules) { this.userStore.user && requests.push(this.moduleStore.init()); + !this.settingsStore.passwordSettings && + requests.push(this.settingsStore.getPortalPasswordSettings()); } return Promise.all(requests); diff --git a/packages/asc-web-common/store/TfaStore.js b/packages/asc-web-common/store/TfaStore.js index 02c3902326..8aeda4b698 100644 --- a/packages/asc-web-common/store/TfaStore.js +++ b/packages/asc-web-common/store/TfaStore.js @@ -54,8 +54,8 @@ class TfaStore { return api.user.loginWithTfaCode(userName, passwordHash, code); }; - loginWithCodeAndCookie = async (code) => { - return api.settings.validateTfaCode(code); + loginWithCodeAndCookie = async (code, confirmKey = null) => { + return api.settings.validateTfaCode(code, confirmKey); }; getBackupCodes = async () => { diff --git a/products/ASC.People/Client/src/components/dialogs/ResetApplicationDialog/index.js b/products/ASC.People/Client/src/components/dialogs/ResetApplicationDialog/index.js index 9c7e7fc9f4..4ed7b0c49e 100644 --- a/products/ASC.People/Client/src/components/dialogs/ResetApplicationDialog/index.js +++ b/products/ASC.People/Client/src/components/dialogs/ResetApplicationDialog/index.js @@ -4,6 +4,7 @@ import ModalDialog from "@appserver/components/modal-dialog"; import Button from "@appserver/components/button"; import Text from "@appserver/components/text"; import { withTranslation } from "react-i18next"; +import { withRouter } from "react-router"; import ModalDialogContainer from "../ModalDialogContainer"; import toastr from "studio/toastr"; @@ -13,11 +14,11 @@ class ResetApplicationDialogComponent extends React.Component { } resetApp = async () => { - const { resetTfaApp, history, id } = this.props; - + const { resetTfaApp, id, onClose, history } = this.props; + onClose && onClose(); try { const res = await resetTfaApp(id); - if (res) history.push(res); + if (res) history.push(res.replace(window.location.origin, "")); } catch (e) { toastr.error(e); } @@ -60,10 +61,11 @@ class ResetApplicationDialogComponent extends React.Component { } } -const ResetApplicationDialog = withTranslation([ - "ResetApplicationDialog", - "Common", -])(ResetApplicationDialogComponent); +const ResetApplicationDialog = withRouter( + withTranslation(["ResetApplicationDialog", "Common"])( + ResetApplicationDialogComponent + ) +); ResetApplicationDialog.propTypes = { visible: PropTypes.bool.isRequired, diff --git a/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js b/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js index 8d62544257..0174fd656e 100644 --- a/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js +++ b/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js @@ -588,7 +588,7 @@ class SectionBodyContent extends React.PureComponent { export default withRouter( inject(({ auth, peopleStore }) => { - const { isAdmin, userStore, settingsStore, tfaStore } = auth; + const { isAdmin, userStore, settingsStore, tfaStore, logout } = auth; const { user: viewer, changeTheme } = userStore; const { @@ -649,6 +649,7 @@ export default withRouter( changeTheme, selectedTheme: viewer.theme, setIsLoading: loadingStore.setIsLoading, + logout, }; })( observer( diff --git a/web/ASC.Web.Api/Api/Settings/TfaappController.cs b/web/ASC.Web.Api/Api/Settings/TfaappController.cs index df1941ee16..9ba2699c14 100644 --- a/web/ASC.Web.Api/Api/Settings/TfaappController.cs +++ b/web/ASC.Web.Api/Api/Settings/TfaappController.cs @@ -45,6 +45,7 @@ public class TfaappController : BaseSettingsController private readonly StudioSmsNotificationSettingsHelper _studioSmsNotificationSettingsHelper; private readonly InstanceCrypto _instanceCrypto; private readonly Signature _signature; + private readonly SecurityContext _securityContext; public TfaappController( MessageService messageService, @@ -65,6 +66,7 @@ public class TfaappController : BaseSettingsController IMemoryCache memoryCache, InstanceCrypto instanceCrypto, Signature signature, + SecurityContext securityContext, IHttpContextAccessor httpContextAccessor) : base(apiContext, memoryCache, webItemManager, httpContextAccessor) { _smsProviderManager = smsProviderManager; @@ -82,6 +84,7 @@ public class TfaappController : BaseSettingsController _studioSmsNotificationSettingsHelper = studioSmsNotificationSettingsHelper; _instanceCrypto = instanceCrypto; _signature = signature; + _securityContext = securityContext; } [HttpGet("tfaapp")] @@ -119,11 +122,12 @@ public class TfaappController : BaseSettingsController } [HttpPost("tfaapp/validate")] - [Authorize(AuthenticationSchemes = "confirm", Roles = "TfaActivation,Everyone")] + [Authorize(AuthenticationSchemes = "confirm", Roles = "TfaActivation,TfaAuth,Everyone")] public bool TfaValidateAuthCode(TfaValidateRequestsDto inDto) { ApiContext.AuthByClaim(); var user = _userManager.GetUsers(_authContext.CurrentAccount.ID); + _securityContext.Logout(); return _tfaManager.ValidateAuthCode(user, inDto.Code); } @@ -235,6 +239,17 @@ public class TfaappController : BaseSettingsController return result; } + [HttpPut("tfaappwithlink")] + public async Task TfaSettingsLink(TfaRequestsDto inDto) + { + if (await TfaSettings(inDto)) + { + return TfaConfirmUrl(); + } + + return string.Empty; + } + [HttpGet("tfaapp/setup")] [Authorize(AuthenticationSchemes = "confirm", Roles = "TfaActivation")] public SetupCode TfaAppGenerateSetupCode() @@ -296,10 +311,10 @@ public class TfaappController : BaseSettingsController } [HttpPut("tfaappnewapp")] - public object TfaAppNewApp(TfaRequestsDto inDto) + public async Task TfaAppNewApp(TfaRequestsDto inDto) { var id = inDto?.Id ?? Guid.Empty; - var isMe = id.Equals(Guid.Empty) || id.Equals(_authContext.CurrentAccount.ID); + var isMe = id.Equals(Guid.Empty) || id.Equals(_authContext.CurrentAccount.ID); var user = _userManager.GetUsers(id); @@ -323,6 +338,7 @@ public class TfaappController : BaseSettingsController if (isMe) { + await _cookiesManager.ResetTenantCookie(); return _commonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.TfaActivation); } diff --git a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaActivation.js b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaActivation.js index 99e8f4d237..26e5d8d1fc 100644 --- a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaActivation.js +++ b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaActivation.js @@ -89,6 +89,7 @@ const TfaActivationForm = withLoader((props) => { const onSubmit = async () => { try { const { user, hash } = (location && location.state) || {}; + const { linkData } = props; setIsLoading(true); @@ -96,7 +97,7 @@ const TfaActivationForm = withLoader((props) => { const url = await loginWithCode(user, hash, code); history.push(url || "/"); } else { - const url = await loginWithCodeAndCookie(code); + const url = await loginWithCodeAndCookie(code, linkData.confirmHeader); history.push(url || "/"); } } catch (e) { diff --git a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaAuth.js b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaAuth.js index a445322e73..d4ad72bd51 100644 --- a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaAuth.js +++ b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/tfaAuth.js @@ -60,6 +60,7 @@ const TfaAuthForm = withLoader((props) => { const onSubmit = async () => { try { const { user, hash } = (location && location.state) || {}; + const { linkData } = props; setIsLoading(true); @@ -67,7 +68,7 @@ const TfaAuthForm = withLoader((props) => { const url = await loginWithCode(user, hash, code); history.push(url || "/"); } else { - const url = await loginWithCodeAndCookie(code); + const url = await loginWithCodeAndCookie(code, linkData.confirmHeader); history.push(url || "/"); } } catch (e) { diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/security/access-portal/tfa.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/security/access-portal/tfa.js index f26f4dd540..099852303f 100644 --- a/web/ASC.Web.Client/src/components/pages/Settings/categories/security/access-portal/tfa.js +++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/security/access-portal/tfa.js @@ -94,17 +94,16 @@ const TwoFactorAuth = (props) => { setIsSaving(true); try { - await setTfaSettings(type); + const res = await setTfaSettings(type); toastr.success(t("SuccessfullySaveSettingsMessage")); saveToSessionStorage("defaultTfaSettings", type); setIsSaving(false); setShowReminder(false); - if (type !== "none") { + if (res) { setIsInit(false); - const link = await getTfaConfirmLink(); - history.push(link.replace(window.location.origin, "")); + history.push(res.replace(window.location.origin, "")); } } catch (error) { toastr.error(error); @@ -117,7 +116,6 @@ const TwoFactorAuth = (props) => { setShowReminder(false); }; - if (isMobile && !isInit && !isLoading) { return ; } diff --git a/web/ASC.Web.Core/CookiesManager.cs b/web/ASC.Web.Core/CookiesManager.cs index c60d3e6ad6..fdb6e1ebb2 100644 --- a/web/ASC.Web.Core/CookiesManager.cs +++ b/web/ASC.Web.Core/CookiesManager.cs @@ -261,8 +261,6 @@ public class CookiesManager _tenantCookieSettingsHelper.SetForTenant(tenant.Id, settings); await _dbLoginEventsManager.LogOutAllActiveConnectionsForTenant(tenant.Id); - - AuthenticateMeAndSetCookies(tenant.Id, _securityContext.CurrentAccount.ID, MessageAction.LoginSuccess); } public string AuthenticateMeAndSetCookies(int tenantId, Guid userId, MessageAction action, bool session = false)