-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
Authentication.js
102 lines (89 loc) · 4.48 KB
/
Authentication.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import requireParameters from './requireParameters';
import * as Network from './Network';
import * as NetworkStore from './Network/NetworkStore';
import updateSessionAuthTokens from './actions/Session/updateSessionAuthTokens';
import CONFIG from '../CONFIG';
import redirectToSignIn from './actions/SignInRedirect';
import CONST from '../CONST';
import Log from './Log';
import * as ErrorUtils from './ErrorUtils';
/**
* @param {Object} parameters
* @param {Boolean} [parameters.useExpensifyLogin]
* @param {String} parameters.partnerName
* @param {String} parameters.partnerPassword
* @param {String} parameters.partnerUserID
* @param {String} parameters.partnerUserSecret
* @param {String} [parameters.twoFactorAuthCode]
* @param {String} [parameters.email]
* @param {String} [parameters.authToken]
* @returns {Promise}
*/
function Authenticate(parameters) {
const commandName = 'Authenticate';
requireParameters(['partnerName', 'partnerPassword', 'partnerUserID', 'partnerUserSecret'], parameters, commandName);
return Network.post(commandName, {
// When authenticating for the first time, we pass useExpensifyLogin as true so we check
// for credentials for the expensify partnerID to let users Authenticate with their expensify user
// and password.
useExpensifyLogin: parameters.useExpensifyLogin,
partnerName: parameters.partnerName,
partnerPassword: parameters.partnerPassword,
partnerUserID: parameters.partnerUserID,
partnerUserSecret: parameters.partnerUserSecret,
twoFactorAuthCode: parameters.twoFactorAuthCode,
authToken: parameters.authToken,
shouldRetry: false,
// Force this request to be made because the network queue is paused when re-authentication is happening
forceNetworkRequest: true,
// Add email param so the first Authenticate request is logged on the server w/ this email
email: parameters.email,
});
}
/**
* Reauthenticate using the stored credentials and redirect to the sign in page if unable to do so.
*
* @param {String} [command] command name for logging purposes
* @returns {Promise}
*/
function reauthenticate(command = '') {
// Prevent any more requests from being processed while authentication happens
NetworkStore.setIsAuthenticating(true);
const credentials = NetworkStore.getCredentials();
return Authenticate({
useExpensifyLogin: false,
partnerName: CONFIG.EXPENSIFY.PARTNER_NAME,
partnerPassword: CONFIG.EXPENSIFY.PARTNER_PASSWORD,
partnerUserID: credentials.autoGeneratedLogin,
partnerUserSecret: credentials.autoGeneratedPassword,
}).then((response) => {
if (response.jsonCode === CONST.JSON_CODE.UNABLE_TO_RETRY) {
// If authentication fails, then the network can be unpaused
NetworkStore.setIsAuthenticating(false);
// When a fetch() fails due to a network issue and an error is thrown we won't log the user out. Most likely they
// have a spotty connection and will need to try to reauthenticate when they come back online. We will error so it
// can be handled by callers of reauthenticate().
throw new Error('Unable to retry Authenticate request');
}
// If authentication fails and we are online then log the user out
if (response.jsonCode !== 200) {
const errorMessage = ErrorUtils.getAuthenticateErrorMessage(response);
NetworkStore.setIsAuthenticating(false);
Log.hmmm('Redirecting to Sign In because we failed to reauthenticate', {
command,
error: errorMessage,
});
redirectToSignIn(errorMessage);
return;
}
// Update authToken in Onyx and in our local variables so that API requests will use the new authToken
updateSessionAuthTokens(response.authToken, response.encryptedAuthToken);
// Note: It is important to manually set the authToken that is in the store here since any requests that are hooked into
// reauthenticate .then() will immediate post and use the local authToken. Onyx updates subscribers lately so it is not
// enough to do the updateSessionAuthTokens() call above.
NetworkStore.setAuthToken(response.authToken);
// The authentication process is finished so the network can be unpaused to continue processing requests
NetworkStore.setIsAuthenticating(false);
});
}
export {reauthenticate, Authenticate};