summaryrefslogtreecommitdiff
path: root/alarm/node_modules/pronote-api/src/auth.js
blob: b19b97efc3464de7fbd660107de6175279fafc42 (plain)
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
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
};