summaryrefslogtreecommitdiff
path: root/src/core/Authentication.ts
blob: f298bdf494205136b3122b91612827b0d85dc467 (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
import AutoreportBase from "./AutoreportBase";
import axios from "axios";
import { readFileSync, writeFileSync } from "node:fs";
import { randomBytes } from "crypto";

export default class Authentication extends AutoreportBase {
    public static getToken(token) {
        let tokens = JSON.parse(readFileSync(AutoreportBase.getRoot() + "/data/tokens.json").toString());

        if (Object.keys(tokens).includes(token) && new Date(tokens[token].date).getTime() - new Date().getTime() <= 31000000) {
            return tokens[token].info;
        } else {
            return false;
        }
    }

    private static saveToken(userInfo) {
        let tokens = JSON.parse(readFileSync(AutoreportBase.getRoot() + "/data/tokens.json").toString());
        let token = randomBytes(64).toString("base64url");

        tokens[token] = {
            date: new Date().getTime(),
            info: userInfo
        };
        writeFileSync(AutoreportBase.getRoot() + "/data/tokens.json", JSON.stringify(tokens));

        return token;
    }

    public static startFlow(req, res) {
        res.redirect(`${AutoreportBase.config.authentication.server}/api/rest/oauth2/auth?client_id=${AutoreportBase.config.authentication.id}&response_type=code&redirect_uri=${AutoreportBase.config.authentication.redirect}&scope=Hub&request_credentials=default&access_type=offline`);
    }

    public static checkAuthentication(req) {
        let _cookies = req.headers.cookie ?? "";
        let _tokens = _cookies.split(";").map(i => i.trim().split("=")).filter(i => i[0] === "AutoreportToken");
        let __tokens = _tokens[0] ?? [];
        let token = __tokens[1] ?? null;

        return !(!token || !this.getToken(token));
    }

    public static async callback(req, res) {
        if (!req.query.code) {
            res.redirect("/");
        }

        let token = (await axios.post(`${AutoreportBase.config.authentication.server}/api/rest/oauth2/token`, `grant_type=authorization_code&redirect_uri=${encodeURIComponent(AutoreportBase.config.authentication.redirect)}&code=${req.query.code}`, {
            headers: {
                'Authorization': `Basic ${Buffer.from(`${AutoreportBase.config.authentication.id}:${AutoreportBase.config.authentication.secret}`).toString("base64")}`,
                'Accept': "application/json",
                'Content-Type': "application/x-www-form-urlencoded"
            }
        })).data.access_token;

        let userInfo = (await axios.get(`${AutoreportBase.config.authentication.server}/api/rest/users/me`, {
            headers: {
                'Authorization': `Bearer ${token}`,
                'Accept': "application/json"
            }
        })).data;

        let userToken = Authentication.saveToken(userInfo);
        res.cookie('AutoreportToken', userToken, { maxAge: 31000000, httpOnly: true });
        res.redirect("/");
    }

    public static testEndpoint(req, res) {
        if (Authentication.checkAuthentication(req)) {
            res.send("Authenticated");
        } else {
            res.send("NOT authenticated");
        }
    }

    public static protectedAPI(req, res, next) {
        if ([null, undefined, ""].includes(req.get("authorization"))) {
            return res.status(401).json({
                code: 401,
                message: "Please provide an Authorization header."
            });
        }

        if (req.get("authorization") !== AutoreportBase.config.api.token) {
            return res.status(403).json( {
                code: 403,
                message: "You do not have permission to use this endpoint."
            });
        }

        next();
    }
}