/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠGood Data ĠCorporation Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . good data . oauth 2 . server . reactive Ċ Ċ import Ġcom . good data . oauth 2 . server . reactive . App Login Web Filter . Companion . APP _ LOGIN _ PATH Ċ import Ġcom . good data . oauth 2 . server . reactive . App Login Web Filter . Companion . RE DIRECT _ TO Ċ import Ġio . mock k . called Ċ import Ġio . mock k . every Ċ import Ġio . mock k . mock k Ċ import Ġio . mock k . verify Ċ import Ġorg . junit . jupiter . api . Test Ċ import Ġorg . springframework . http . HttpHeaders Ċ import Ġorg . springframework . http . HttpMethod Ċ import Ġorg . springframework . http . HttpStatus Ċ import Ġorg . springframework . http . server . Request Path Ċ import Ġorg . springframework . util . Multi Value Map Adapter Ċ import Ġorg . springframework . web . server . Server Web Exchange Ċ import Ġorg . springframework . web . server . Web FilterChain Ċ import Ġreactor . core . publisher . Mono Ċ import Ġstri kt . api . expect That Ċ import Ġstri kt . assertions . has Entry Ċ import Ġjava . net . URI Ċ Ċ internal Ġclass ĠApp Login Web Filter Test Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġexchange : ĠServer Web Exchange Ġ= Ġmock k Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġresponse Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġset StatusCode ( any ()) Ġ} Ġreturns Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġheaders Ġ} Ġreturns ĠHttp Headers () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġchain : ĠWeb FilterChain Ġ= Ġmock k Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġfilter ( any ()) Ġ} Ġreturns ĠMono . empty () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġfilter Ġ= ĠApp Login Web Filter ( App Login Properties ( URI . create (" https :// localhost : 8 4 4 3 "))) ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` correct Ġrequest Ġis Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("/ some / path "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġexpect That ( response . headers ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhas Entry (" Location ", ĠlistOf ("/ some / path ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġverify ( exact ly Ġ= Ġ 1 ) Ġ{ Ġresponse . statusCode Ġ= ĠHttpStatus . FOUND Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` redirect Ġto Ġroot Ġis Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("/ "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġexpect That ( response . headers ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhas Entry (" Location ", ĠlistOf ("/ ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġverify ( exact ly Ġ= Ġ 1 ) Ġ{ Ġresponse . statusCode Ġ= ĠHttpStatus . FOUND Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġabsolute Ġpath Ġis Ġnot Ġredirected Ġif Ġdoes Ġnot Ġmatch Ġconfigured Ġorigin `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf (" http :// local / some / path "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġabsolute Ġpath Ġis Ġredirected Ġif Ġmatches Ġconfigured Ġorigin `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf (" https :// localhost : 8 4 4 3 / some / path "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġexpect That ( response . headers ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhas Entry (" Location ", ĠlistOf (" https :// localhost : 8 4 4 3 / some / path ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġverify ( exact ly Ġ= Ġ 1 ) Ġ{ Ġresponse . statusCode Ġ= ĠHttpStatus . FOUND Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` normalized Ġuri Ġis Ġredirected Ġif Ġmatches Ġconfigured Ġorigin `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmap Of ( RE DIRECT _ TO Ġto ĠlistOf (" https :// localhost : 8 4 4 3 / some /../ path ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġexpect That ( response . headers ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhas Entry (" Location ", ĠlistOf (" https :// localhost : 8 4 4 3 / path ")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġverify ( exact ly Ġ= Ġ 1 ) Ġ{ Ġresponse . statusCode Ġ= ĠHttpStatus . FOUND Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` normalized Ġuri Ġnot Ġredirected Ġif Ġdoes Ġnot Ġmatch Ġconfigured Ġorigin `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmap Of ( RE DIRECT _ TO Ġto ĠlistOf (" http :// local / some /../ path ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġincorrect Ġmethod Ġis Ġnot Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . POST ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("/ some / path "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġincorrect Ġpath Ġis Ġnot Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ("/ some / other / path ", Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("/ some / path "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwithout Ġquery Ġis Ġnot Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġdouble Ġslash Ġis Ġnot Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("// double slash "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġback slash Ġis Ġnot Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf ("\\ backslash "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġempty Ġredirect To Ġis Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto ĠlistOf (" "))) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġ` request Ġwith Ġnull Ġredirect To Ġis Ġredirected `() Ġ{ ĊĠĠĠĠĠĠĠ Ġevery Ġ{ Ġexchange . request Ġ} Ġreturns Ġmock k Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġmethod Ġ} Ġreturns ĠHttpMethod . GET ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ Ġpath Ġ} Ġreturns ĠRequest Path . parse ( APP _ LOGIN _ PATH , Ġ"/") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevery Ġ{ ĠqueryParams Ġ} Ġreturns ĠMulti Value Map Adapter ( map Of ( RE DIRECT _ TO Ġto Ġnull )) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfilter . filter ( exchange , Ġchain ). block () ĊĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġexchange . response ĊĠĠĠĠĠĠĠ Ġverify Ġ{ Ġresponse Ġwas Not Ġcalled Ġ} ĊĠĠĠ Ġ} Ċ } Ċ