"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SamlProvider = void 0;
const samlp = require("samlp");
const Config_1 = require("./Config");
const Audit_1 = require("./Audit");
const openflow_api_1 = require("@openiap/openflow-api");
const Logger_1 = require("./Logger");
class SamlProvider {
    static profileMapper(pu) {
        return {
            pu: pu,
            getClaims: function () {
                const claims = {};
                const k = Object.keys(this.pu);
                k.forEach(key => {
                    if (key.indexOf("http://") === 0) {
                        claims[key] = this.pu[key];
                    }
                    else {
                        switch (key) {
                            case "id":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] = this.pu[key];
                                break;
                            case "displayName":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"] = this.pu[key];
                                break;
                            case "name":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"] = this.pu[key];
                                break;
                            case "mobile":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobile"] = this.pu[key];
                                break;
                            case "username":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] = this.pu[key];
                                break;
                            case "emails":
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"] = this.pu[key][0];
                                claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] = this.pu[key][0];
                                break;
                            case "roles":
                                const roles = [];
                                this.pu[key].forEach(role => {
                                    roles.push(role.name);
                                });
                                claims["http://schemas.xmlsoap.org/claims/Group"] = roles;
                        }
                    }
                });
                return claims;
            },
            getNameIdentifier: function () {
                const claims = this.getClaims();
                return {
                    nameIdentifier: claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"] ||
                        claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"] ||
                        claims["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
                };
            }
        };
    }
    static remoteip(req) {
        let remoteip = req.socket.remoteAddress;
        if (req.headers["X-Forwarded-For"] != null)
            remoteip = req.headers["X-Forwarded-For"];
        if (req.headers["X-real-IP"] != null)
            remoteip = req.headers["X-real-IP"];
        if (req.headers["x-forwarded-for"] != null)
            remoteip = req.headers["x-forwarded-for"];
        if (req.headers["x-real-ip"] != null)
            remoteip = req.headers["x-real-ip"];
        return remoteip;
    }
    static configure(app, baseurl) {
        const cert = Buffer.from(Config_1.Config.signing_crt, "base64").toString("ascii");
        const key = Buffer.from(Config_1.Config.singing_key, "base64").toString("ascii");
        const samlpoptions = {
            issuer: Config_1.Config.saml_issuer,
            cert: cert,
            key: key,
            getPostURL: (wtrealm, wreply, req, callback) => {
                (async () => {
                    if (typeof wreply === "object") {
                        wreply = wreply.documentElement.getAttribute("AssertionConsumerServiceURL");
                    }
                    return callback(null, wreply);
                })();
            },
            getUserFromRequest: (req) => {
                const span = Logger_1.Logger.otel.startSpan("SAML.getUserFromRequest");
                try {
                    const tuser = openflow_api_1.TokenUser.From(req.user);
                    const remoteip = SamlProvider.remoteip(req);
                    span === null || span === void 0 ? void 0 : span.setAttribute("remoteip", remoteip);
                    Audit_1.Audit.LoginSuccess(tuser, "tokenissued", "saml", remoteip, "samlverify", "unknown", span).catch((e) => {
                        Logger_1.Logger.instanse.error("SamlProvider", "getUserFromRequest", e);
                    });
                }
                catch (error) {
                    span === null || span === void 0 ? void 0 : span.recordException(error);
                }
                finally {
                    Logger_1.Logger.otel.endSpan(span);
                }
                return req.user;
            },
            profileMapper: SamlProvider.profileMapper,
            lifetimeInSeconds: (3600 * 24)
        };
        app.get("/issue/", (req, res, next) => {
            if (req.query.SAMLRequest !== undefined && req.query.SAMLRequest !== null) {
                if ((req.user === undefined || req.user === null)) {
                    try {
                        // tslint:disable-next-line: max-line-length
                        samlp.parseRequest(req, samlpoptions, async (_err, samlRequestDom) => {
                            res.cookie("originalUrl", req.originalUrl, { maxAge: 900000, httpOnly: true });
                            res.redirect("/");
                        });
                    }
                    catch (error) {
                        res.body(error.message ? error.message : error);
                        res.end();
                        Logger_1.Logger.instanse.error("SamlProvider", "/issue", error);
                    }
                }
                else {
                    // continue with issuing token using samlp
                    next();
                }
            }
            else {
                res.send("Please login again");
                res.end();
            }
        });
        app.get("/issue/", samlp.auth(samlpoptions));
        app.get("/issue/FederationMetadata/2007-06/FederationMetadata.xml", samlp.metadata({
            issuer: Config_1.Config.saml_issuer,
            cert: cert,
        }));
        // TODO: FIX !!!!
        app.get('/wssignout', async (req, res, next) => {
            req.logout();
            let html = "<html><head></head><body>";
            html += "<h1>Du er nu logget ud</h1><br>";
            // html += "<br/><p><a href='/'>Til login</ifarame></p>";
            html += "</body></html>";
            res.send(html);
        });
        app.post('/wssignout', async (req, res, next) => {
            req.logout();
            let html = "<html><head></head><body>";
            html += "<h1>Du er nu logget ud</h1><br>";
            // html += "<br/><p><a href='/'>Til login</ifarame></p>";
            html += "</body></html>";
            res.send(html);
        });
        app.get('/logout', async (req, res, next) => {
            const referer = req.headers.referer;
            const providerid = req.cookies.provider;
            req.logout();
            if (!openflow_api_1.NoderedUtil.IsNullEmpty(providerid)) {
                var providers = await Logger_1.Logger.DBHelper.GetProviders(null);
                const p = providers.filter(x => x.id == providerid);
                if (p.length > 0) {
                    const provider = p[0];
                    if (!openflow_api_1.NoderedUtil.IsNullEmpty(provider.saml_signout_url)) {
                        let html = "<html><head></head><body>";
                        html += "<h1>Logud</h1><br>";
                        if (!openflow_api_1.NoderedUtil.IsNullEmpty(referer)) {
                            html += "<br/><p><a href='" + encodeURI(referer) + "'>Til login</a></p>";
                        }
                        else {
                            html += "<br/><p><a href='/'>Til login</a></p>";
                        }
                        html += "<iframe src='" + encodeURI(provider.saml_signout_url) + "'></iframe>";
                        if (!openflow_api_1.NoderedUtil.IsNullEmpty(referer)) {
                            html += "<br/><p><a href='" + encodeURI(referer) + "'>Til login</a></p>";
                        }
                        else {
                            html += "<br/><p><a href='/'>Til login</a></p>";
                        }
                        html += "</body></html>";
                        res.send(html);
                        return;
                    }
                }
            }
            if (!openflow_api_1.NoderedUtil.IsNullEmpty(referer)) {
                res.redirect(referer);
            }
            else {
                res.redirect("/");
            }
        });
        app.post('/logout', (req, res, next) => {
            samlp.logout({
                issuer: Config_1.Config.saml_issuer,
                protocolBinding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
                cert: cert,
                key: key
            })(req, res, next);
        });
    }
}
exports.SamlProvider = SamlProvider;
//# sourceMappingURL=SamlProvider.js.map