UNPKG

@pagopa/io-spid-commons

Version:

Common code for integrating SPID authentication

138 lines 6.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeSpidStrategy = exports.upsertSpidStrategyOption = exports.getSpidStrategyOption = exports.getSpidStrategyOptionsUpdater = exports.makeSpidStrategyOptions = exports.AggregatorType = exports.EntityType = exports.ContactType = void 0; /** * SPID Passport strategy */ const strings_1 = require("@pagopa/ts-commons/lib/strings"); const A = require("fp-ts/lib/Array"); const function_1 = require("fp-ts/lib/function"); const T = require("fp-ts/lib/Task"); const TE = require("fp-ts/lib/TaskEither"); const t = require("io-ts"); const config_1 = require("../config"); const spid_1 = require("../strategy/spid"); const metadata_1 = require("./metadata"); const saml_1 = require("./saml"); var ContactType; (function (ContactType) { ContactType["OTHER"] = "other"; })(ContactType = exports.ContactType || (exports.ContactType = {})); var EntityType; (function (EntityType) { EntityType["AGGREGATOR"] = "spid:aggregator"; })(EntityType = exports.EntityType || (exports.EntityType = {})); var AggregatorType; (function (AggregatorType) { AggregatorType["PublicServicesFullOperator"] = "PublicServicesFullOperator"; })(AggregatorType = exports.AggregatorType || (exports.AggregatorType = {})); const CommonExtension = t.interface({ FiscalCode: t.string, IPACode: t.string, VATNumber: t.string, }); const AggregatorExtension = t.intersection([ t.interface({ aggregatorType: t.literal(AggregatorType.PublicServicesFullOperator), }), CommonExtension, ]); const ContactPerson = t.intersection([ t.interface({ company: t.string, contactType: t.literal(ContactType.OTHER), email: strings_1.EmailString, entityType: t.literal(EntityType.AGGREGATOR), extensions: AggregatorExtension, }), t.partial({ phone: t.string, }), ]); /** * This method create a Spid Strategy Options object * extending the provided SamlOption with the service provider configuration * and the idps Options */ const makeSpidStrategyOptions = (samlConfig, serviceProviderConfig, idpOptionsRecord) => ({ idp: idpOptionsRecord, sp: Object.assign(Object.assign({}, samlConfig), { attributes: { attributes: serviceProviderConfig.requiredAttributes, name: serviceProviderConfig.requiredAttributes.name, }, identifierFormat: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient", organization: serviceProviderConfig.organization, signatureAlgorithm: "sha256" }), }); exports.makeSpidStrategyOptions = makeSpidStrategyOptions; /** * Merge strategy configuration with metadata from IDP. * * This is used to pass options to the SAML client * so it can discriminate between the IDP certificates. */ const getSpidStrategyOptionsUpdater = (samlConfig, serviceProviderConfig) => () => { const idpOptionsTasks = [ (0, function_1.pipe)((0, metadata_1.fetchIdpsMetadata)(serviceProviderConfig.IDPMetadataUrl, config_1.SPID_IDP_IDENTIFIERS), TE.getOrElseW(() => T.of({}))), ] .concat((0, function_1.pipe)(strings_1.NonEmptyString.is(serviceProviderConfig.spidValidatorUrl) ? [ (0, function_1.pipe)((0, metadata_1.fetchIdpsMetadata)(`${serviceProviderConfig.spidValidatorUrl}/metadata.xml`, { // "https://validator.spid.gov.it" or "http://localhost:8080" [serviceProviderConfig.spidValidatorUrl]: "xx_validator", }), TE.getOrElseW(() => T.of({}))), ] : [])) .concat(strings_1.NonEmptyString.is(serviceProviderConfig.spidCieUrl) ? [ (0, function_1.pipe)((0, metadata_1.fetchIdpsMetadata)(serviceProviderConfig.spidCieUrl, config_1.CIE_IDP_IDENTIFIERS), TE.getOrElseW(() => T.of({}))), ] : []) .concat(strings_1.NonEmptyString.is(serviceProviderConfig.spidCieTestUrl) ? [ (0, function_1.pipe)((0, metadata_1.fetchIdpsMetadata)(serviceProviderConfig.spidCieTestUrl, config_1.CIE_IDP_IDENTIFIERS), TE.getOrElseW(() => T.of({}))), ] : []) .concat(strings_1.NonEmptyString.is(serviceProviderConfig.spidTestEnvUrl) ? [ (0, function_1.pipe)((0, metadata_1.fetchIdpsMetadata)(`${serviceProviderConfig.spidTestEnvUrl}/metadata`, { [serviceProviderConfig.spidTestEnvUrl]: "xx_testenv2", }), TE.getOrElseW(() => T.of({}))), ] : []); return (0, function_1.pipe)(A.sequence(T.ApplicativePar)(idpOptionsTasks), T.map(A.reduce({}, (prev, current) => (Object.assign(Object.assign({}, prev), current)))), T.map((idpOptionsRecord) => { (0, saml_1.logSamlCertExpiration)(serviceProviderConfig.publicCert); return (0, exports.makeSpidStrategyOptions)(samlConfig, serviceProviderConfig, idpOptionsRecord); })); }; exports.getSpidStrategyOptionsUpdater = getSpidStrategyOptionsUpdater; const SPID_STRATEGY_OPTIONS_KEY = "spidStrategyOptions"; /** * SPID strategy calls getSamlOptions() for every * SAML request. It extracts the options from a * shared variable set into the express app. */ const getSpidStrategyOption = (app) => app.get(SPID_STRATEGY_OPTIONS_KEY); exports.getSpidStrategyOption = getSpidStrategyOption; /** * This method is called to set or update Spid Strategy Options. * A selective update is performed to replace only new configurations provided, * keeping the others already stored inside the express app. */ const upsertSpidStrategyOption = (app, newSpidStrategyOpts) => { const spidStrategyOptions = (0, exports.getSpidStrategyOption)(app); app.set(SPID_STRATEGY_OPTIONS_KEY, spidStrategyOptions ? { idp: Object.assign(Object.assign({}, spidStrategyOptions.idp), newSpidStrategyOpts.idp), sp: newSpidStrategyOpts.sp, } : newSpidStrategyOpts); }; exports.upsertSpidStrategyOption = upsertSpidStrategyOption; /** * SPID strategy factory function. */ const makeSpidStrategy = (options, getSamlOptions, redisClient, tamperAuthorizeRequest, tamperMetadata, preValidateResponse, doneCb, extraLoginRequestParamConfig) => new spid_1.SpidStrategy(Object.assign(Object.assign({}, options.sp), { passReqToCallback: true }), getSamlOptions, (_, profile, done) => { // at this point SAML authentication is successful // `done` is a passport callback that signals success done(null, profile); }, redisClient, tamperAuthorizeRequest, tamperMetadata, preValidateResponse, doneCb, extraLoginRequestParamConfig); exports.makeSpidStrategy = makeSpidStrategy; //# sourceMappingURL=middleware.js.map