diff --git a/src/passport-saml/algorithms.ts b/src/passport-saml/algorithms.ts index fc0e4029..3405dacf 100644 --- a/src/passport-saml/algorithms.ts +++ b/src/passport-saml/algorithms.ts @@ -1,4 +1,4 @@ -import crypto from 'crypto'; +import * as crypto from 'crypto'; export function getSigningAlgorithm (shortName: string): string { switch(shortName) { diff --git a/src/passport-saml/index.ts b/src/passport-saml/index.ts index c01e65b1..2dbfd75e 100644 --- a/src/passport-saml/index.ts +++ b/src/passport-saml/index.ts @@ -1,6 +1,6 @@ import type { CacheItem, CacheProvider} from './inmemory-cache-provider'; import { SAML } from './saml'; -import Strategy from './strategy'; +import Strategy = require('./strategy'); import type { Profile, VerifiedCallback, VerifyWithRequest, VerifyWithoutRequest } from './types'; export { SAML, Strategy, CacheItem, CacheProvider, Profile, VerifiedCallback, VerifyWithRequest, VerifyWithoutRequest }; diff --git a/src/passport-saml/multiSamlStrategy.ts b/src/passport-saml/multiSamlStrategy.ts index 0d6b9d36..d66aaa85 100644 --- a/src/passport-saml/multiSamlStrategy.ts +++ b/src/passport-saml/multiSamlStrategy.ts @@ -1,7 +1,7 @@ -import util from 'util'; +import * as util from 'util'; import * as saml from './saml'; import {CacheProvider as InMemoryCacheProvider} from './inmemory-cache-provider'; -import SamlStrategy from './strategy'; +import SamlStrategy = require('./strategy'); function MultiSamlStrategy (options, verify) { if (!options || typeof options.getSamlOptions != 'function') { diff --git a/src/passport-saml/saml.ts b/src/passport-saml/saml.ts index 54a381a5..e0ed1138 100644 --- a/src/passport-saml/saml.ts +++ b/src/passport-saml/saml.ts @@ -1,15 +1,15 @@ import Debug from 'debug'; const debug = Debug('passport-saml'); -import zlib from 'zlib'; -import xml2js from 'xml2js'; -import xmlCrypto, { xpath } from 'xml-crypto'; -import crypto, { KeyLike } from 'crypto'; -import xmldom from 'xmldom'; -import url from 'url'; -import querystring from 'querystring'; -import xmlbuilder from 'xmlbuilder'; -import xmlenc from 'xml-encryption'; -import util, { promisify } from 'util'; +import * as zlib from 'zlib'; +import * as xml2js from 'xml2js'; +import * as xmlCrypto from 'xml-crypto'; +import * as crypto from 'crypto'; +import * as xmldom from 'xmldom'; +import * as url from 'url'; +import * as querystring from 'querystring'; +import * as xmlbuilder from 'xmlbuilder'; +import * as xmlenc from 'xml-encryption'; +import * as util from 'util'; import {CacheProvider as InMemoryCacheProvider} from './inmemory-cache-provider'; import * as algorithms from './algorithms'; import { signAuthnRequestPost } from './saml-post-signing'; @@ -69,7 +69,7 @@ function processValidlySignedSamlLogout(self: SAML, doc, dom, callback) { } function callBackWithNameID(nameid, callback) { - const format = xpath(nameid, "@Format") as Node[]; + const format = xmlCrypto.xpath(nameid, "@Format") as Node[]; return callback(null, { value: nameid.textContent, format: format && format[0] && format[0].nodeValue @@ -241,7 +241,7 @@ class SAML { (async () => { if(this.options.validateInResponseTo) { - return promisify(this.cacheProvider.save).bind(this.cacheProvider)(id, instant); + return util.promisify(this.cacheProvider.save).bind(this.cacheProvider)(id, instant); } else { return; } @@ -619,7 +619,7 @@ class SAML { "namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#' and " + "descendant::*[local-name(.)='Reference' and @URI='#"+currentNode.getAttribute('ID')+"']" + "]"; - const signatures = xpath(currentNode, xpathSigQuery); + const signatures = xmlCrypto.xpath(currentNode, xpathSigQuery); // This function is expecting to validate exactly one signature, so if we find more or fewer // than that, reject. if (signatures.length != 1) { @@ -653,7 +653,7 @@ class SAML { return false; // If we find any extra referenced nodes, reject. (xml-crypto only verifies one digest, so // multiple candidate references is bad news) - const totalReferencedNodes = xpath(currentNode.ownerDocument, + const totalReferencedNodes = xmlCrypto.xpath(currentNode.ownerDocument, "//*[@" + idAttribute + "='" + refId + "']"); if (totalReferencedNodes.length > 1) { @@ -673,7 +673,7 @@ class SAML { if (!Object.prototype.hasOwnProperty.call(doc, 'documentElement')) throw new Error('SAMLResponse is not valid base64-encoded XML'); - inResponseTo = xpath(doc, "/*[local-name()='Response']/@InResponseTo"); + inResponseTo = xmlCrypto.xpath(doc, "/*[local-name()='Response']/@InResponseTo"); if (inResponseTo) { inResponseTo = inResponseTo.length ? inResponseTo[0].nodeValue : null; @@ -689,8 +689,8 @@ class SAML { validSignature = true; } - const assertions = xpath(doc, "/*[local-name()='Response']/*[local-name()='Assertion']"); - const encryptedAssertions = xpath(doc, + const assertions = xmlCrypto.xpath(doc, "/*[local-name()='Response']/*[local-name()='Assertion']"); + const encryptedAssertions = xmlCrypto.xpath(doc, "/*[local-name()='Response']/*[local-name()='EncryptedAssertion']"); if (assertions.length + encryptedAssertions.length > 1) { @@ -718,7 +718,7 @@ class SAML { return util.promisify(xmlenc.decrypt).bind(xmlenc)(encryptedAssertionXml, xmlencOptions) .then(decryptedXml => { const decryptedDoc = new xmldom.DOMParser().parseFromString(decryptedXml); - const decryptedAssertions = xpath(decryptedDoc, "/*[local-name()='Assertion']"); + const decryptedAssertions = xmlCrypto.xpath(decryptedDoc, "/*[local-name()='Assertion']"); if (decryptedAssertions.length != 1) throw new Error('Invalid EncryptedAssertion content'); @@ -1194,8 +1194,8 @@ class SAML { } getNameID(self, doc, callback) { - const nameIds = xpath(doc, "/*[local-name()='LogoutRequest']/*[local-name()='NameID']"); - const encryptedIds = xpath(doc, + const nameIds = xmlCrypto.xpath(doc, "/*[local-name()='LogoutRequest']/*[local-name()='NameID']"); + const encryptedIds = xmlCrypto.xpath(doc, "/*[local-name()='LogoutRequest']/*[local-name()='EncryptedID']") as Node[]; if (nameIds.length + encryptedIds.length > 1) { @@ -1209,7 +1209,7 @@ class SAML { return callback(new Error('No decryption key for encrypted SAML response')); } - const encryptedDatas = xpath(encryptedIds[0], "./*[local-name()='EncryptedData']"); + const encryptedDatas = xmlCrypto.xpath(encryptedIds[0], "./*[local-name()='EncryptedData']"); if (encryptedDatas.length !== 1) { return callback(new Error('Invalid LogoutRequest')); @@ -1220,7 +1220,7 @@ class SAML { return util.promisify(xmlenc.decrypt).bind(xmlenc)(encryptedDataXml, xmlencOptions) .then(function (decryptedXml) { const decryptedDoc = new xmldom.DOMParser().parseFromString(decryptedXml); - const decryptedIds = xpath(decryptedDoc, "/*[local-name()='NameID']"); + const decryptedIds = xmlCrypto.xpath(decryptedDoc, "/*[local-name()='NameID']"); if (decryptedIds.length !== 1) { return callback(new Error('Invalid EncryptedAssertion content')); } @@ -1325,7 +1325,7 @@ class SAML { return xmlbuilder.create(metadata).end({ pretty: true, indent: ' ', newline: '\n' }); } - keyToPEM(key: KeyLike) { + keyToPEM(key: crypto.KeyLike) { if (!key || typeof key !== 'string') return key; const lines = key.split('\n'); diff --git a/src/passport-saml/strategy.ts b/src/passport-saml/strategy.ts index 086f5eb2..d6668d92 100644 --- a/src/passport-saml/strategy.ts +++ b/src/passport-saml/strategy.ts @@ -1,7 +1,7 @@ -import passport from 'passport-strategy'; -import util from 'util'; +import * as passport from 'passport-strategy'; +import * as util from 'util'; import * as saml from './saml'; -import url from 'url'; +import * as url from 'url'; import { AuthenticateOptions, AuthorizeOptions, SamlConfig, VerifyWithoutRequest, VerifyWithRequest } from './types'; import type { Request } from 'express'; import { Profile } from './types'; diff --git a/src/passport-saml/types.ts b/src/passport-saml/types.ts index 91fdc665..944e0161 100644 --- a/src/passport-saml/types.ts +++ b/src/passport-saml/types.ts @@ -1,5 +1,5 @@ -import type express from 'express'; -import passport from 'passport'; +import type * as express from 'express'; +import * as passport from 'passport'; import type { CacheProvider } from './inmemory-cache-provider'; export type CertCallback = (callback: (err: Error | null, cert?: string | string[]) => void) => void; @@ -73,10 +73,9 @@ export type Profile = { } & { [attributeName: string]: unknown; // arbitrary `AttributeValue`s }; - + export type VerifiedCallback = (err: Error | null, user?: Record, info?: Record) => void; export type VerifyWithRequest = (req: express.Request, profile: Profile, done: VerifiedCallback) => void; export type VerifyWithoutRequest = (profile: Profile, done: VerifiedCallback) => void; - \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 4925ce4c..88d203b4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -48,7 +48,7 @@ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */