@@ -604,3 +604,167 @@ describe("getSignedCookies", () => {
604604 expect ( verifySignature ( denormalizeBase64 ( result [ "CloudFront-Signature" ] ) , policy ) ) . toBeTruthy ( ) ;
605605 } ) ;
606606} ) ;
607+
608+ describe ( "getSignedUrl- when signing a URL with a date range" , ( ) => {
609+ const dateString = "2024-05-17T12:30:45.000Z" ;
610+ const dateGreaterThanString = "2024-05-16T12:30:45.000Z" ;
611+ const dateNumber = 1125674245900 ;
612+ const dateGreaterThanNumber = 1716034245000 ;
613+ const dateObject = new Date ( dateString ) ;
614+ const dateGreaterThanObject = new Date ( dateGreaterThanString ) ;
615+ it ( "allows string input compatible with Date constructor" , ( ) => {
616+ const epochDateLessThan = Math . round ( new Date ( dateString ) . getTime ( ) / 1000 ) ;
617+ const resultUrl = getSignedUrl ( {
618+ url,
619+ keyPairId,
620+ dateLessThan : dateString ,
621+ privateKey,
622+ passphrase,
623+ } ) ;
624+ const resultCookies = getSignedCookies ( {
625+ url,
626+ keyPairId,
627+ dateLessThan : dateString ,
628+ privateKey,
629+ passphrase,
630+ } ) ;
631+
632+ expect ( resultUrl ) . toContain ( `Expires=${ epochDateLessThan } ` ) ;
633+ expect ( resultCookies [ "CloudFront-Expires" ] ) . toBe ( epochDateLessThan ) ;
634+ } ) ;
635+
636+ it ( "allows number input in milliseconds compatible with Date constructor" , ( ) => {
637+ const epochDateLessThan = Math . round ( new Date ( dateNumber ) . getTime ( ) / 1000 ) ;
638+ const resultUrl = getSignedUrl ( {
639+ url,
640+ keyPairId,
641+ dateLessThan : dateNumber ,
642+ privateKey,
643+ passphrase,
644+ } ) ;
645+ const resultCookies = getSignedCookies ( {
646+ url,
647+ keyPairId,
648+ dateLessThan : dateNumber ,
649+ privateKey,
650+ passphrase,
651+ } ) ;
652+
653+ expect ( resultUrl ) . toContain ( `Expires=${ epochDateLessThan } ` ) ;
654+ expect ( resultCookies [ "CloudFront-Expires" ] ) . toBe ( epochDateLessThan ) ;
655+ } ) ;
656+ it ( "allows Date object input" , ( ) => {
657+ const epochDateLessThan = Math . round ( dateObject . getTime ( ) / 1000 ) ;
658+ const resultUrl = getSignedUrl ( {
659+ url,
660+ keyPairId,
661+ dateLessThan : dateObject ,
662+ privateKey,
663+ passphrase,
664+ } ) ;
665+ const resultCookies = getSignedCookies ( {
666+ url,
667+ keyPairId,
668+ dateLessThan : dateObject ,
669+ privateKey,
670+ passphrase,
671+ } ) ;
672+
673+ expect ( resultUrl ) . toContain ( `Expires=${ epochDateLessThan } ` ) ;
674+ expect ( resultCookies [ "CloudFront-Expires" ] ) . toBe ( epochDateLessThan ) ;
675+ } ) ;
676+ it ( "allows string input for date range" , ( ) => {
677+ const result = getSignedUrl ( {
678+ url,
679+ keyPairId,
680+ dateLessThan : dateString ,
681+ dateGreaterThan : dateGreaterThanString ,
682+ privateKey,
683+ passphrase,
684+ } ) ;
685+
686+ const policyStr = JSON . stringify ( {
687+ Statement : [
688+ {
689+ Resource : url ,
690+ Condition : {
691+ DateLessThan : {
692+ "AWS:EpochTime" : Math . round ( new Date ( dateString ) . getTime ( ) / 1000 ) ,
693+ } ,
694+ DateGreaterThan : {
695+ "AWS:EpochTime" : Math . round ( new Date ( dateGreaterThanString ) . getTime ( ) / 1000 ) ,
696+ } ,
697+ } ,
698+ } ,
699+ ] ,
700+ } ) ;
701+
702+ const parsedUrl = parseUrl ( result ) ;
703+ expect ( parsedUrl ) . toBeDefined ( ) ;
704+ const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
705+ expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
706+ } ) ;
707+
708+ it ( "allows number input for date range" , ( ) => {
709+ const result = getSignedUrl ( {
710+ url,
711+ keyPairId,
712+ dateLessThan : dateNumber ,
713+ dateGreaterThan : dateGreaterThanNumber ,
714+ privateKey,
715+ passphrase,
716+ } ) ;
717+
718+ const policyStr = JSON . stringify ( {
719+ Statement : [
720+ {
721+ Resource : url ,
722+ Condition : {
723+ DateLessThan : {
724+ "AWS:EpochTime" : Math . round ( dateNumber / 1000 ) ,
725+ } ,
726+ DateGreaterThan : {
727+ "AWS:EpochTime" : Math . round ( dateGreaterThanNumber / 1000 ) ,
728+ } ,
729+ } ,
730+ } ,
731+ ] ,
732+ } ) ;
733+
734+ const parsedUrl = parseUrl ( result ) ;
735+ expect ( parsedUrl ) . toBeDefined ( ) ;
736+ const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
737+ expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
738+ } ) ;
739+ it ( "allows Date object input for date range" , ( ) => {
740+ const result = getSignedUrl ( {
741+ url,
742+ keyPairId,
743+ dateLessThan : dateObject ,
744+ dateGreaterThan : dateGreaterThanObject ,
745+ privateKey,
746+ passphrase,
747+ } ) ;
748+
749+ const policyStr = JSON . stringify ( {
750+ Statement : [
751+ {
752+ Resource : url ,
753+ Condition : {
754+ DateLessThan : {
755+ "AWS:EpochTime" : Math . round ( dateObject . getTime ( ) / 1000 ) ,
756+ } ,
757+ DateGreaterThan : {
758+ "AWS:EpochTime" : Math . round ( dateGreaterThanObject . getTime ( ) / 1000 ) ,
759+ } ,
760+ } ,
761+ } ,
762+ ] ,
763+ } ) ;
764+
765+ const parsedUrl = parseUrl ( result ) ;
766+ expect ( parsedUrl ) . toBeDefined ( ) ;
767+ const signatureQueryParam = denormalizeBase64 ( parsedUrl . query ! [ "Signature" ] as string ) ;
768+ expect ( verifySignature ( signatureQueryParam , policyStr ) ) . toBeTruthy ( ) ;
769+ } ) ;
770+ } ) ;
0 commit comments