diff options
Diffstat (limited to 'alarm/node_modules/pronote-api/src/auth.js')
-rw-r--r-- | alarm/node_modules/pronote-api/src/auth.js | 96 |
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 +}; |