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