Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / components / containers / login / finalizeLogin.ts
blobc883cec12765703b26faff2b395a9a7c88940ec9
1 import { revoke } from '@proton/shared/lib/api/auth';
2 import { getSettings, upgradePassword } from '@proton/shared/lib/api/settings';
3 import { maybeResumeSessionByUser, persistSession } from '@proton/shared/lib/authentication/persistedSessionHelper';
4 import { APPS } from '@proton/shared/lib/constants';
5 import type { UserSettings } from '@proton/shared/lib/interfaces';
6 import { getDecryptedUserKeysHelper } from '@proton/shared/lib/keys';
7 import {
8     attemptDeviceRecovery,
9     getIsDeviceRecoveryAvailable,
10     removeDeviceRecovery,
11     storeDeviceRecovery,
12 } from '@proton/shared/lib/recoveryFile/deviceRecovery';
13 import { srpVerify } from '@proton/shared/lib/srp';
14 import { AUTH_VERSION } from '@proton/srp';
15 import noop from '@proton/utils/noop';
17 import type { AuthActionResponse, AuthCacheResult } from './interface';
18 import { AuthStep } from './interface';
19 import { syncAddresses, syncUser } from './syncCache';
21 /**
22  * Finalize login can be called without a key password in these cases:
23  * 1) The admin panel
24  * 2) Users who have no keys but are in 2-password mode
25  */
26 export const finalizeLogin = async ({
27     cache,
28     loginPassword,
29     keyPassword,
30     clearKeyPassword,
31     attemptResume = true,
32 }: {
33     cache: AuthCacheResult;
34     loginPassword: string;
35     keyPassword?: string;
36     clearKeyPassword?: string;
37     attemptResume?: boolean;
38 }): Promise<AuthActionResponse> => {
39     const { authResponse, authVersion, api, persistent, appName, preAuthKTVerifier } = cache;
41     if (authVersion < AUTH_VERSION) {
42         await srpVerify({
43             api,
44             credentials: { password: loginPassword },
45             config: upgradePassword(),
46         });
47     }
49     if (appName !== APPS.PROTONACCOUNT) {
50         const user = cache.data.user || (await syncUser(cache));
51         const trusted = false;
53         const { clientKey, offlineKey } = await persistSession({
54             ...authResponse,
55             clearKeyPassword: clearKeyPassword || '',
56             keyPassword,
57             User: user,
58             api,
59             persistent,
60             trusted,
61         });
63         return {
64             to: AuthStep.DONE,
65             session: {
66                 ...authResponse,
67                 keyPassword,
68                 clientKey,
69                 offlineKey,
70                 loginPassword,
71                 persistent,
72                 trusted,
73                 User: user,
74                 flow: 'login',
75             },
76         };
77     }
79     let [user, addresses] = await Promise.all([
80         cache.data.user || syncUser(cache),
81         cache.data.addresses || syncAddresses(cache),
82     ]);
84     const validatedSession = attemptResume ? await maybeResumeSessionByUser(api, user) : null;
85     if (validatedSession) {
86         await api(revoke()).catch(noop);
87         return {
88             to: AuthStep.DONE,
89             session: { ...validatedSession, loginPassword, flow: 'login' },
90         };
91     }
93     let trusted = false;
94     if (keyPassword) {
95         const numberOfReactivatedKeys = await attemptDeviceRecovery({
96             api,
97             user,
98             addresses,
99             keyPassword,
100             preAuthKTVerify: preAuthKTVerifier.preAuthKTVerify,
101         }).catch(noop);
103         if (numberOfReactivatedKeys !== undefined && numberOfReactivatedKeys > 0) {
104             cache.data.user = undefined;
105             cache.data.addresses = undefined;
106             [user, addresses] = await Promise.all([syncUser(cache), syncAddresses(cache)]);
107         }
109         // Store device recovery information
110         if (persistent) {
111             const [userKeys] = await Promise.all([getDecryptedUserKeysHelper(user, keyPassword)]);
112             const isDeviceRecoveryAvailable = getIsDeviceRecoveryAvailable({
113                 user,
114                 addresses,
115                 userKeys,
116                 appName,
117             });
119             if (isDeviceRecoveryAvailable) {
120                 const userSettings = await api<{ UserSettings: UserSettings }>(getSettings()).then(
121                     ({ UserSettings }) => UserSettings
122                 );
124                 if (userSettings.DeviceRecovery) {
125                     const deviceRecoveryUpdated = await storeDeviceRecovery({ api, user, userKeys }).catch(noop);
126                     if (deviceRecoveryUpdated) {
127                         // Storing device recovery (when setting a new recovery secret) modifies the user object
128                         cache.data.user = undefined;
129                         user = await syncUser(cache);
130                     }
131                     trusted = true;
132                 }
133             }
134         } else {
135             removeDeviceRecovery(user.ID);
136         }
137     }
139     const { clientKey, offlineKey } = await persistSession({
140         ...authResponse,
141         clearKeyPassword: clearKeyPassword || '',
142         keyPassword,
143         User: user,
144         api,
145         persistent,
146         trusted,
147     });
149     await preAuthKTVerifier.preAuthKTCommit(user.ID, api);
151     return {
152         to: AuthStep.DONE,
153         session: {
154             ...authResponse,
155             keyPassword,
156             loginPassword,
157             offlineKey,
158             clientKey,
159             persistent,
160             trusted,
161             User: user,
162             flow: 'login',
163         },
164     };