file author Orange
*  desc import { wording , StatusCode } from './urn' ; import { BindingContext , SimpleSignComputedContext } from './entity' ; import libsaml from './libsaml' ; import utility , { get } from './utility' ; const binding = wording . binding ; const urlParams = wording . urlParams ; export interface BuildSimpleSignConfig { type : string ; context : string ; entitySetting : any ; relayState ? : string ; } export interface BindingSimpleSignContext { id : string ; context : string ; signature : any ; sigAlg : string ; } private desc param { string } param param { string } value param { boolean } first return { string } function pvPair ( param , value , first ? ) { return ( first === true ? '?' : '&' ) + param + '=' + value ; } private desc param { string } type param { string } rawSamlRequest param { object } entitySetting return { string } function buildSimpleSignature ( opts ) { const { type , context , entitySetting , } = opts ; let { relayState = '' } = opts ; const queryParam = libsaml . getQueryParamByType ( type ) ; if ( relayState !== '' ) { relayState = pvPair ( urlParams . relayState , relayState ) ; } const sigAlg = pvPair ( urlParams . sigAlg , entitySetting . requestSignatureAlgorithm ) ; const octetString = context + relayState + sigAlg ; return libsaml . constructMessageSignature ( queryParam + '=' + octetString , entitySetting . privateKey , entitySetting . privateKeyPass , undefined , entitySetting . requestSignatureAlgorithm ) . toString ( ) ; } desc param { string } referenceTagXPath param { object } entity param { function } customTagReplacement function base64LoginRequest ( entity , customTagReplacement ? ) { const metadata = { idp : entity . idp . entityMeta , sp : entity . sp . entityMeta } ; const spSetting = entity . sp . entitySetting ; let id = '' ; if ( metadata && metadata . idp && metadata . sp ) { const base = metadata . idp . getSingleSignOnService ( binding . simpleSign ) ; let rawSamlRequest ; if ( spSetting . loginRequestTemplate && customTagReplacement ) { const info = customTagReplacement ( spSetting . loginRequestTemplate . context ) ; id = get ( info , 'id' , null ) ; rawSamlRequest = get ( info , 'context' , null ) ; } else { const nameIDFormat = spSetting . nameIDFormat ; const selectedNameIDFormat = Array . isArray ( nameIDFormat ) ? nameIDFormat [ 0 ] : nameIDFormat ; id = spSetting . generateID ( ) ; rawSamlRequest = libsaml . replaceTagsByValue ( libsaml . defaultLoginRequestTemplate . context , { ID : id , Destination : base , Issuer : metadata . sp . getEntityID ( ) , IssueInstant : new Date ( ) . toISOString ( ) , AssertionConsumerServiceURL : metadata . sp . getAssertionConsumerService ( binding . simpleSign ) , EntityID : metadata . sp . getEntityID ( ) , AllowCreate : spSetting . allowCreate , NameIDFormat : selectedNameIDFormat } as any ) ; } let simpleSignatureContext = null ; if ( metadata . idp . isWantAuthnRequestsSigned ( ) ) { const simpleSignature = buildSimpleSignature ( { type : urlParams . samlRequest , context : rawSamlRequest , entitySetting : spSetting , relayState : spSetting . relayState , } ) ; simpleSignatureContext = { signature : simpleSignature , sigAlg : spSetting . requestSignatureAlgorithm , } ; } return { id , context : utility . base64Encode ( rawSamlRequest ) , ... simpleSignatureContext , } ; } throw new Error ( 'ERR_GENERATE_POST_SIMPLESIGN_LOGIN_REQUEST_MISSING_METADATA' ) ; } desc param { object } requestInfo param { object } entity param { object } user param { string } relayState param { function } customTagReplacement async function base64LoginResponse ( requestInfo = { } , entity , user = { } , relayState ? , customTagReplacement ? ) { const idpSetting = entity . idp . entitySetting ; const spSetting = entity . sp . entitySetting ; const id = idpSetting . generateID ( ) ; const metadata = { idp : entity . idp . entityMeta , sp : entity . sp . entityMeta , } ; const nameIDFormat = idpSetting . nameIDFormat ; const selectedNameIDFormat = Array . isArray ( nameIDFormat ) ? nameIDFormat [ 0 ] : nameIDFormat ; if ( metadata && metadata . idp && metadata . sp ) { const base = metadata . sp . getAssertionConsumerService ( binding . simpleSign ) ; let rawSamlResponse ; const nowTime = new Date ( ) ; const fiveMinutesLaterTime = new Date ( nowTime . getTime ( ) + 300000 ) ; const tvalue = { ID : id , AssertionID : idpSetting . generateID ( ) , Destination : base , Audience : metadata . sp . getEntityID ( ) , EntityID : metadata . sp . getEntityID ( ) , SubjectRecipient : base , Issuer : metadata . idp . getEntityID ( ) , IssueInstant : nowTime . toISOString ( ) , AssertionConsumerServiceURL : base , StatusCode : StatusCode . Success , ConditionsNotBefore : nowTime . toISOString ( ) , ConditionsNotOnOrAfter : fiveMinutesLaterTime . toISOString ( ) , SubjectConfirmationDataNotOnOrAfter : fiveMinutesLaterTime . toISOString ( ) , NameIDFormat : selectedNameIDFormat , NameID : user . email || '' , InResponseTo : get ( requestInfo , 'extract.request.id' , '' ) , AuthnStatement : '' , AttributeStatement : '' , } ; if ( idpSetting . loginResponseTemplate && customTagReplacement ) { const template = customTagReplacement ( idpSetting . loginResponseTemplate . context ) ; rawSamlResponse = get ( template , 'context' , null ) ; } else { if ( requestInfo !== null ) { tvalue . InResponseTo = requestInfo . extract . request . id ; } rawSamlResponse = libsaml . replaceTagsByValue ( libsaml . defaultLoginResponseTemplate . context , tvalue ) ; } const { privateKey , privateKeyPass , requestSignatureAlgorithm : signatureAlgorithm } = idpSetting ; const config = { privateKey , privateKeyPass , signatureAlgorithm , signingCert : metadata . idp . getX509Certificate ( 'signing' ) , isBase64Output : false , } ; if ( metadata . sp . isWantAssertionsSigned ( ) ) { rawSamlResponse = libsaml . constructSAMLSignature ( { ... config , rawSamlMessage : rawSamlResponse , transformationAlgorithms : spSetting . transformationAlgorithms , referenceTagXPath : "/*[local-name(.)='Response']/*[local-name(.)='Assertion']" , signatureConfig : { prefix : 'ds' , location : { reference : "/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Issuer']" , action : 'after' } , } , } ) ; } let simpleSignature = '' ; simpleSignature = buildSimpleSignature ( { type : urlParams . samlResponse , context : rawSamlResponse , entitySetting : idpSetting , relayState : relayState , } ) ; return Promise . resolve ( { id , context : utility . base64Encode ( rawSamlResponse ) , signature : simpleSignature , sigAlg : idpSetting . requestSignatureAlgorithm , } ) ; } throw new Error ( 'ERR_GENERATE_POST_SIMPLESIGN_LOGIN_RESPONSE_MISSING_METADATA' ) ; } const simpleSignBinding = { base64LoginRequest , base64LoginResponse , } ; export default simpleSignBinding ;