SAML 2.0 解析器和验证器
一个用于Node.js的 SAML 2.0 库:它验证了 SAML 响应,并创建和剖析 Authn Requests, 登录消息和元数据. 它开始作为叉子 萨姆尔20 从那时起,他背离了它。 Ory维护它,它出版于npm作为 @boxyhq/saml20。 。 。 .
安装
$ npm install @boxyhq/saml20
使用量
validate() 返回一个承诺.
saml.validate( 缩写, 选项)
验证一个 SAML 响应(或一个孤独的 Assertion),并与用户的配置解析. 当一切失败的时候,它否认真理 StatusCode、缺失或无效的签名、过期的断言或失败的听众, InResponseTo, (中文(简体) ), Recipient 或者重新播放检查.
rawResponse 是 XML 作为字符串( 解码基数64) SAMLResponse 格式字段为先).
options (脚本 : ValidateOptions:
publicKey:可信任的IDP签名证书,作为Base64 DER或PEM. 几个证书(用于密钥旋转)用逗号分隔.thumbprint:信任证书的 SHA-1 拇指印,逗号分隔. 证书本身取自KeyInfo的签名。 也通过publicKey或者说thumbprint而不是两个.privateKey(可选):解密aEncryptedAssertion。 。 。 .audience:预期的观众,或被接受的观众名单. 每个AudienceRestriction在断言中,必须确切指明其中之一。 失败者Invalid audience.缺少或空值失败audience is required.inResponseTo(可选):AuthnRequest此回复答案 。 设定时, 签名的内容必须带有相同的InResponseTo; 缺少值失败。 失败者Invalid InResponseTo.recipient(可选). ACS URL的响应被张贴到,或者它可能已经张贴到的ACS URL列表(对于一个在几个地址接受响应的SP来说). 设定后,签名的内容必须命名(其中之一,每个候选人自行判断):签名Response/@Destination当任何携带者SubjectConfirmationData携带一个Recipient,一个无记名确认书必须既取名,又在自己的范围内NotBefore编号 :NotOnOrAfter窗口(如此)NotOnOrAfter需要为此而努力;bypassExpiration跳过此窗口检查, 但不是Recipient两者中至少有一人必须在场。 一个空的Recipient计数为当前且从未匹配。 未签名者Response包装从不使用。 失败者Invalid Recipient.空字符串、 空列表或带有空条目的列表失败recipient must be a non-empty URL or a non-empty list of them.assertionReplayValidator(可选) :(info) => boolean | Promise<boolean>,在每张支票后打来{ assertionId, sessionIndex, notOnOrAfter, inResponseTo }从签名的断言。 返回时true如果该断言已经使用,则该反应作为回放被拒绝。 每个条目至少保存到notOnOrAfter加上10分钟,时钟摇摆validate()允许.bypassExpiration(可选). 这种旗帜表示过期验证绕行(可用于测试,在生产环境中不推荐);allowedSignatureAlgorithms编号 :allowedHashAlgorithms(可选). 算法允许列表转发到validateSignature,见下文.maxSignatureReferences(可选). 上限SignedInfo/Reference页:1validateSignature,见下文.
const saml = require('@boxyhq/saml20').default;
const profile = await saml.validate(rawResponse, {
publicKey: 'MIICDzCCAXygAwIBAgIQVWXAvbbQyI5Bc...',
audience: 'https://sp.example.com',
inResponseTo: requestId,
recipient: 'https://sp.example.com/acs',
});
const { claims, issuer, sessionIndex, assertionId, notOnOrAfter } = profile;
错误是 Errors 有固定消息。 当原因更为具体(例如,为什么签名失败)时,错误是 WrapError 和原因在 error.inner。 。 。 .
saml.parseIssuer( 缩写响应)
返回 Issuer 无法验证任何东西。 用它来找出一个响应的IP声称来自哪一个, 这样你就可以选择证书传递给 validate()。 。 。 .
const issuer = saml.parseIssuer(rawResponse);
saml.validate Signature(xml,公钥,指印,选项?)
验证 XML 签名于 xml 并返回已签名的 XML 。 从返回值而不是从 xml:只覆盖已签名的内容. 它在签名无效或无法检查时丢出; 不验证失败的签名 invalid signature: the signature does not verify。通过 publicKey (一个证书,或用逗号分隔若干个键旋转)或 thumbprint而不是两个.
options (可选)限制哪些算法被接受 :
allowedSignatureAlgorithms——已接受SignatureMethod(原始内容存档于2018-10-21). URIs.allowedHashAlgorithms——已接受DigestMethod(原始内容存档于2018-10-21). URIs.
省略允许列表时, 默认设置从 xml-crypto 应用(RSA-SHA1,RSA-SHA256,RSA-SHA512和SHA-1,SHA-256,SHA-512摘要). 当给出一个时,一个使用任何其他算法的文档会被拒绝;一个空列表会拒绝一切.
maxSignatureReferences——最大数量Reference签字时接受的要素SignedInfo(默认16). 一个SAML的签名就有一个 天花板束缚着工作xml-crypto在核查之前SignatureValue:每个引用都先被cononicalized,所以一个没有被约束的列表是未经认证的CPU拒绝服务. 超过上限的文件被拒绝invalid signature: SignedInfo declares N References; at most M are allowed,在任何卡通化之前.
var saml = require('@boxyhq/saml20').default;
var signedXml = saml.validateSignature(xml, publicKey, null, {
allowedSignatureAlgorithms: [
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512',
],
allowedHashAlgorithms: [
'http://www.w3.org/2001/04/xmlenc#sha256',
'http://www.w3.org/2001/04/xmlenc#sha512',
],
});
升级到 2. 0
2.0 删除已贬值或波利斯不再使用的API:
- 只有包根可以被导入.
package.json现在有一个exports地图,所以软件包中的路径如下:@boxyhq/saml20/dist/typings失败ERR_PACKAGE_PATH_NOT_EXPORTED(与TS2307一起)moduleResolutionnode16, (中文(简体) ),nodenext或者说bundler) (中文(简体) ). 例如从根导入import type { SAMLProfile } from '@boxyhq/saml20'。所有根输出都列在test/lib/compat.spec.ts。 。 。 . parse()不见了 它在不检查签名,过期,观众或其他任何内容的情况下还原了一个剖面图,因此其输出可以被伪造. 使用validate()认证回复,以及parseIssuer()在验证前读取发行人(例如,选择IDP证书).decryptXml财务报告和审定财务报表PubKeyInfo不再从软件包根导出。 他们是内部帮手validate()财务报告和审定财务报表sign()。 。 。 .hasValidSignature删除。 使用validateSignature(),它也拒绝给予证书和拇指印.isMultiRootedXMLError删除。 以错误拒绝多根文档multirooted xml not allowed.strictAudienceValidation观众总是被精确对比 在2.0之前,没有这个选项Audience仅仅从预期价值开始就被接受(https://sp.example.com/metadata.evil.example通过了https://sp.example.com/metadata) (中文(简体) ). 如果你依赖前缀匹配,通过所有接受的观众在audience换句话说.validateSignature()当签名无法校验时, 丢出它用来返回的地方null。它现在要么返回签名的 XML ,要么丢出.audience需要时间。 在2.0之前,留它出去跳过观众检查,所以为其他信任同一IP的服务提供商发布的断言被接受.parseMetadata(), (中文(简体) ),parseSAMLRequest(), (中文(简体) ),parseLogoutRequest()财务报告和审定财务报表parseLogoutResponse()用相同的 XML 解析器解析为validate()(单位:千美元)@xmldom/xmldom改为xml2js。它们现在拒绝一个有多个根元素的文档。 文档使用的名称空间前缀而不声明它仍然被接受(前缀不参与结果),以及带有属性的证书元素. 文本和属性值得到线程和白空常态 XML 需要,所以用 CRLF 线程结尾粘贴的证书会在 LF 中返回publicKey(数量)thumbprint原文不变)。 例如, 解析器信件中存在错误的文档失败missing root element改为Non-whitespace before first tag.,则&不开始引用( e)a & b失败Invalid XML.- 那个XML
request(), (中文(简体) ),createSAMLResponse(), (中文(简体) ),createLogoutRequest(), (中文(简体) ),createLogoutResponse(), (中文(简体) ),createIdPMetadataXML()财务报告和审定财务报表createSPMetadataXML()产品按序列排列xmlbuilder2改为xmlbuilder。这些文档是相同的,只是已经存在于一个祖先范围内的命名空间声明不会在后人身上重复,带有空文本的元素写成<a></a>而不是说<a/>A级saml:Assertion从createSAMLResponse()仍然声明它使用的每一个前缀,所以当它从它的samlp:Response。 。 。 .
测试
$ npm test # node:test with coverage
$ npm run typecheck # type-checks lib/ and test/
$ npm run lint # oxlint
修补者住在 test/assets。需要新有效性窗口的测试,或固定装置没有、构建和在辅助工具中签名的形状 test/helpers/fixtures.ts。 。 。 .
捐款
谢谢你花时间捐款! 贡献使得开放源码社区成为学习、激励和创造的惊人场所。 你所做的任何贡献都将造福所有人,并受到赞赏.
报告错误 GitHub 问题。请尝试创建以下错误报告:
- 可复制. 包括复制问题的步骤.
- 具体. 包括尽可能多的细节:哪个版本,什么环境等.
- 独出一辙. 不重复已打开的问题 .
- 范围为单虫. 每个报告一个错误.
报告安全问题
许可证
麻省理工学院