summaryrefslogtreecommitdiff
path: root/alarm/node_modules/pronote-api/src/auth.js
diff options
context:
space:
mode:
Diffstat (limited to 'alarm/node_modules/pronote-api/src/auth.js')
-rw-r--r--alarm/node_modules/pronote-api/src/auth.js96
1 files changed, 96 insertions, 0 deletions
diff --git a/alarm/node_modules/pronote-api/src/auth.js b/alarm/node_modules/pronote-api/src/auth.js
new file mode 100644
index 0000000..b19b97e
--- /dev/null
+++ b/alarm/node_modules/pronote-api/src/auth.js
@@ -0,0 +1,96 @@
+const errors = require('./errors');
+const cas = require('./cas');
+const { decipher, getLoginKey } = require('./cipher');
+const getAccountType = require('./accounts');
+const PronoteSession = require('./session');
+
+const getParams = require('./fetch/pronote/params');
+const { getId, getAuthKey } = require('./fetch/pronote/auth');
+const getUser = require('./fetch/pronote/user');
+
+function loginFor(type)
+{
+ return (url, username, password, cas = 'none') => login(url, username, password, cas, getAccountType(type));
+}
+
+async function login(url, username, password, cas, account)
+{
+ const server = getServer(url);
+ const start = await getStart(server, username, password, cas, account);
+ const session = new PronoteSession({
+ serverURL: server,
+ sessionID: start.h,
+
+ type: account,
+
+ disableAES: !!start.sCrA,
+ disableCompress: !!start.sCoA,
+
+ keyModulus: start.MR,
+ keyExponent: start.ER
+ })
+
+ session.params = await getParams(session);
+ if (!session.params) {
+ throw errors.WRONG_CREDENTIALS.drop();
+ }
+ if (cas === 'none') {
+ await auth(session, username, password, false);
+ } else {
+ await auth(session, start.e, start.f, true);
+ }
+ session.user = await getUser(session);
+
+ return session;
+}
+
+function getServer(url)
+{
+ if (url.endsWith('.html')) {
+ return url.substring(0, url.lastIndexOf('/') + 1);
+ }
+
+ if (!url.endsWith('/')) {
+ url += '/';
+ }
+
+ return url;
+}
+
+async function getStart(url, username, password, casName, type)
+{
+ if (casName === 'names' || casName === 'getCAS' || !cas[casName]) {
+ throw errors.UNKNOWN_CAS.drop(casName);
+ }
+
+ const account = typeof type === 'string' ? getAccountType(type) : type;
+ return await cas[casName](url, account, username, password);
+}
+
+async function auth(session, username, password, fromCas)
+{
+ const id = await getId(session, username, fromCas);
+ const key = getLoginKey(username, password, id.scramble, fromCas);
+
+ let challenge;
+ try {
+ challenge = decipher(session, id.challenge, { scrambled: true, key });
+ } catch (e) {
+ throw errors.WRONG_CREDENTIALS.drop();
+ }
+
+ const userKey = await getAuthKey(session, challenge, key);
+ if (!userKey) {
+ throw errors.WRONG_CREDENTIALS.drop();
+ }
+
+ session.aesKey = decipher(session, userKey, { key, asBytes: true });
+}
+
+module.exports = {
+ loginStudent: loginFor('student'),
+ loginParent: loginFor('parent'),
+
+ getStart,
+ auth
+};