@pagopa/io-spid-commons
Version:
Common code for integrating SPID authentication
93 lines • 5.63 kB
JavaScript
;
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