-
Notifications
You must be signed in to change notification settings - Fork 0
/
authenticator.js
124 lines (103 loc) · 3.73 KB
/
authenticator.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const fetch = require('node-fetch');
const FormData = require('form-data');
const https = require("https");
class Authenticator {
constructor(username, password, region, cookies = '') {
this.username = username;
this.password = password;
this.region = region;
this.cookies = cookies;
this.url = `https://www.credit-agricole.fr/ca-${this.region}/particulier`;
}
/**
* Creates a session and loads the cookies
* @param username
* @param password
* @param region
* @returns {Promise<Authenticator>}
*/
static async createSession(username, password, region) {
const session = new Authenticator(username, password, region);
await session.loadCookies();
return session;
}
/**
* Logging out the user and deleting the cookies
* @returns {Promise<void>}
*/
async logout() {
const logoutUrl = `${this.url}.npc.logout.html?resource=/content/ca/cr866/npc/fr/particulier.html`;
const sslVerify = true;
const headers = { 'Cookie': this.cookies }
const res = await fetch(logoutUrl, {
method: 'GET',
headers: headers,
agent: new https.Agent({
rejectUnauthorized: sslVerify
})
});
if (res.status !== 200) {
throw new Error(`Logout failed: ${res.status} - ${res.statusText}`)
}
this.cookies = '';
}
/**
* Load the login cookies and the keypad cookies
* @returns {Promise<void>}
*/
async loadCookies() {
if (this.cookies !== '') {
throw new Error('Cookies already loaded');
}
const sslVerify = true;
// password
const authKeypadUrl = `${this.url}/acceder-a-mes-comptes.authenticationKeypad.json`;
const res1 = await fetch(authKeypadUrl, {method: 'POST'});
if (res1.status !== 200) {
throw new Error(`Authentication failed: ${res1.status}`);
}
const data = await res1.json();
const keypadId = data.keypadId;
const mappedPassword = [...this.password].map(c => data.keyLayout.indexOf(c).toString());
const authKeypadCookies = res1.headers.raw()['set-cookie'].map((entry) => {
const parts = entry.split(';');
return parts[0];
}).join(';');
// login
const authUrl = `${this.url}/acceder-a-mes-comptes.html/j_security_check`;
const payload = {
'j_password': mappedPassword.join(','),
'path': '/content/npc/start',
'j_path_ressource': `%2Fca-${this.region}%2Fparticulier%2Foperations%2Fsynthese.html`,
'j_username': this.username,
'keypadId': keypadId,
'j_validate': 'true',
}
const form = new FormData();
for (const key in payload) {
form.append(key, payload[key]);
}
const headers = {
'Content-Type': 'multipart/form-data; boundary=' + form.getBoundary(),
'Cookie': authKeypadCookies
}
const res2 = await fetch(authUrl, {
method: 'POST',
body: form,
headers: headers,
agent: new https.Agent({
rejectUnauthorized: sslVerify
})
});
if (res2.status !== 200) {
throw new Error(`Authentication failed: ${res2.status} - ${res2.statusText}`)
}
const loginCookies = res2.headers.raw()['set-cookie'].map((entry) => {
const parts = entry.split(';');
return parts[0];
}).join(';')
// merge authKeyPadCookies and loginCookies
this.cookies = authKeypadCookies + ';' + loginCookies;
}
}
module.exports = Authenticator;