UNPKG

@pagopa/io-spid-commons

Version:

Common code for integrating SPID authentication

93 lines 5.63 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomSamlClient = void 0; const function_1 = require("fp-ts/lib/function"); const O = require("fp-ts/lib/Option"); const E = require("fp-ts/Either"); const TE = require("fp-ts/lib/TaskEither"); const PassportSaml = require("passport-saml"); const jwk_1 = require("@pagopa/ts-commons/lib/jwk"); const lollipop_1 = require("../types/lollipop"); class CustomSamlClient extends PassportSaml.SAML { // eslint-disable-next-line max-params constructor(config, extededCacheProvider, requestMapper, tamperAuthorizeRequest, preValidateResponse, doneCb) { // validateInResponseTo must be set to false to disable // internal cacheProvider of passport-saml super(Object.assign(Object.assign({}, config), { validateInResponseTo: false })); this.config = config; this.extededCacheProvider = extededCacheProvider; this.requestMapper = requestMapper; this.tamperAuthorizeRequest = tamperAuthorizeRequest; this.preValidateResponse = preValidateResponse; this.doneCb = doneCb; } /** * Custom version of `validatePostResponse` which checks * the response XML to satisfy SPID protocol constrains */ validatePostResponse(body, callback) { if (this.preValidateResponse) { return this.preValidateResponse(this.config, body, this.extededCacheProvider, this.doneCb, (err, isValid, AuthnRequestID) => { if (err) { return callback(err); } // go on with checks in case no error is found return super.validatePostResponse(body, (error, user, ___) => { if (!error && isValid && AuthnRequestID) { // eslint-disable-next-line @typescript-eslint/no-floating-promises (0, function_1.pipe)(this.extededCacheProvider.get(AuthnRequestID), TE.map((cachedData) => { const { // eslint-disable-next-line @typescript-eslint/no-unused-vars RequestXML, // eslint-disable-next-line @typescript-eslint/no-unused-vars createdAt, // eslint-disable-next-line @typescript-eslint/no-unused-vars idpIssuer } = cachedData, extraLoginRequestParams = __rest(cachedData, ["RequestXML", "createdAt", "idpIssuer"]); return extraLoginRequestParams; }), TE.chainFirst(() => this.extededCacheProvider.remove(AuthnRequestID)), TE.map((extraLoginRequestParams) => callback(error, // Do NOT change `extraLoginRequestParams` name, unless you change the one // used in `withSpidAuthMiddleware` accordingly user ? Object.assign(Object.assign({}, user), { extraLoginRequestParams }) : user, ___)), TE.mapLeft(callback))(); } else { callback(error, user, ___); } }); }); } super.validatePostResponse(body, callback); } /** * Custom version of `generateAuthorizeRequest` which tampers * the generated XML to satisfy SPID protocol constrains */ generateAuthorizeRequest(req, isPassive, isHttpPostBinding, callback) { const newCallback = (0, function_1.pipe)(O.fromNullable(this.tamperAuthorizeRequest), O.map((tamperAuthorizeRequest) => (e, xml) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/no-unused-expressions xml ? (0, function_1.pipe)(req.headers[lollipop_1.LOLLIPOP_PUB_KEY_HEADER_NAME], jwk_1.JwkPublicKeyFromToken.decode, O.fromEither, O.map((pubKey) => ({ hashAlgorithm: (0, function_1.pipe)(req.headers[lollipop_1.LOLLIPOP_PUB_KEY_HASHING_ALGO_HEADER_NAME], // The headers validation should happen into the Application layer. // If a unsupported value is provided, the application can return a validation error. // If the value is missing or unsupported the default value will be used (sha256). O.fromPredicate(lollipop_1.LollipopHashAlgorithm.is), O.toUndefined), pubKey, })), O.toUndefined, (lollipopParams) => tamperAuthorizeRequest(xml, lollipopParams), TE.chain((tamperedXml) => this.extededCacheProvider.save(tamperedXml, this.config, (0, function_1.pipe)(this.requestMapper, E.fromNullable(undefined), E.chainW((mapper) => mapper(req)), E.getOrElseW(() => undefined)))), TE.mapLeft((error) => callback(error)), TE.map((cache) => callback(null, cache.RequestXML)))() : callback(e); }), O.getOrElse(() => callback)); super.generateAuthorizeRequest(req, isPassive, isHttpPostBinding, newCallback); } } exports.CustomSamlClient = CustomSamlClient; //# sourceMappingURL=saml_client.js.map