From cf5330d7cf8854eb80ae872e3775bbe3fcac48e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Tue, 7 Mar 2023 00:52:35 +0100 Subject: [PATCH] feat-dev: add U2F iframe for desktop client authentication (#2236) --- ...rowser-npm-7.0.0-93e13e1065-eb8d7e2d92.zip | Bin 19180 -> 0 bytes ...rowser-npm-7.1.0-356ca6f81a-925e266075.zip | Bin 0 -> 18960 bytes packages/snjs/lib/Application/Application.ts | 22 ++-- .../UseCase/UseCaseContainerInterface.ts | 31 ++--- packages/snjs/lib/Domain/index.ts | 16 +++ .../src/Route/Params/AppViewRouteParams.ts | 3 + .../ui-services/src/Route/RootQueryParam.ts | 1 + packages/ui-services/src/Route/RouteParser.ts | 14 +++ .../src/Route/RouteParserInterface.ts | 2 + packages/ui-services/src/Route/RouteType.ts | 1 + packages/web/package.json | 1 + packages/web/src/javascripts/App.tsx | 9 ++ .../javascripts/Application/Application.ts | 8 ++ .../Components/ChallengeModal/U2FPrompt.tsx | 19 ++- .../U2FPromptIframeContainer.tsx | 66 +++++++++++ .../Components/Input/DecoratedInput.tsx | 17 ++- .../Components/Input/DecoratedInputProps.ts | 2 + .../Panes/Security/U2F/U2FAddDeviceView.tsx | 23 +++- .../Security/U2F/U2FView/U2FDescription.tsx | 12 +- .../Security/U2F/U2FView/U2FDevicesList.tsx | 36 +++--- .../Panes/Security/U2F/U2FView/U2FTitle.tsx | 4 +- .../Panes/Security/U2F/U2FView/U2FView.tsx | 27 +++-- .../U2FAuthIframe/U2FAuthIframe.tsx | 109 ++++++++++++++++++ packages/web/src/javascripts/Logging.ts | 2 + yarn.lock | 10 +- 25 files changed, 362 insertions(+), 73 deletions(-) delete mode 100644 .yarn/cache/@simplewebauthn-browser-npm-7.0.0-93e13e1065-eb8d7e2d92.zip create mode 100644 .yarn/cache/@simplewebauthn-browser-npm-7.1.0-356ca6f81a-925e266075.zip create mode 100644 packages/ui-services/src/Route/Params/AppViewRouteParams.ts create mode 100644 packages/web/src/javascripts/Components/ChallengeModal/U2FPromptIframeContainer.tsx create mode 100644 packages/web/src/javascripts/Components/U2FAuthIframe/U2FAuthIframe.tsx diff --git a/.yarn/cache/@simplewebauthn-browser-npm-7.0.0-93e13e1065-eb8d7e2d92.zip b/.yarn/cache/@simplewebauthn-browser-npm-7.0.0-93e13e1065-eb8d7e2d92.zip deleted file mode 100644 index 34e817595ec524436ae380d7e2f0bda735a62804..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19180 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 diff --git a/.yarn/cache/@simplewebauthn-browser-npm-7.1.0-356ca6f81a-925e266075.zip b/.yarn/cache/@simplewebauthn-browser-npm-7.1.0-356ca6f81a-925e266075.zip new file mode 100644 index 0000000000000000000000000000000000000000..9a8da658d280e8916b9ca7130d713f50b35f54b0 GIT binary patch literal 18960 zcmb_^1yo(h(ls6&65QS0HMqN5aJWctx8OlSaEIW5AOV6yaCa_F@ZjzQhw$IbOuo$U z-prfH{D;+W7Ti;Ncb)3)s_JT#WFeu@!MVfz=4Qv9z+jUDaWoB)o0A%gbriZHcwa{dcBEdNN3 zv5T##HQ+aK5MZ#s=+7O$@skBeac$&aVB$X`&eGNt;LZqe;$U>KF=e!|v}Jtm)TMLp zHdpib-rE;?sCL#AalB%+o&clUg`kCDE_H2k`#i9SCmKpxi$(}qm@c*R-rMa`M8zP@ z-KMrF2`gp^yzXXx`M^m^ArrdE4qo8Rrga-k)r6`8uacuO^VyJQpZ3`HqhSSKH)h5z zB_|qE3Fk)m^`%Vff)4ue0iL*3Kkqczyw@EaW$0v_8vzmRkoOLhk^o?-^IGl-`FSm#EEYLbr!&TZKG*8MgP^Be1)6ROteW6=}!^re>{A6nZ- zaQaxu4{E6EisM2_Pb9;_Btj#=mvCdxcxTa$Xd{4Qd_W)1d%}D>MI3`J*P^N-JF&j+ z-lV_qdHDG5tHAyl9V5Ja7ix8*Mi?Us3fHlzG(*Pr^QOgH-b7jv0<~77p6Pw=i#ZBa zokl&_X&+#`KBZ{tW(*7k3JTej>YZGNfrEI}Xd~-JL3i3L=DJO`cpFttiTGQ{;y3A! zW0W~)%;mO7`%;p(EH#@@^;}-ydkI^{+pH;tP(5cX*?7W{bXT|g#RNkcE`9hk&qb?= zeR@qD3DH#SvGN;=X;PJ4mt59q^KJyp9_3XlX>ROIb5(Zr_v=OBVx-fOe)N&=NhUjJ ze3p+i)hEY1p6Mu(IQYOgG7Z>x z6$ar8{B(kT{d^)kJjfZoU9Zd~HnBtKSk3;I z22mQY_*m`o4=Nd>P{t%F10LvTsfI76lO)i`xEP$$Asj7=F-W_u-ze+5f~95n@`1xn z?G6Oei@rxj8D3Du|6nmym{el;aWe%g40+8n!m~MkgMi4OchQM$Ak}!VEOcppz_aw` zD+F0%OgEQ`Nhq7?vo9}1zcec1BLi51ES%zwAQi3=MKFe|BETdp_}-f~$+llF`71zU zph6|mB}ltN+BCDXERm*iJ*sx46(dE?M~RIJh;*{gFUldL;!%60(Y)f)-2NhU`RdXi z;jX&S@CeBswu4ckW%!EUYLogIr=UY~Ei#uHrnh^q=j`+phvaw?f;DOe8i(6N$1k21{W^EMB_IeHrA5Vda|xv?e6OZkBZeo;a@IHEWWDJm{xl89qE zlP`mT8i)z9!d67MTSV}1UAAD9bkjLN0c0)0PbXkyuE%fDDs|L(zQE{=Np&-OWsH-& zR`BH)NRK`uw?;`{8S(a_?uaQ<_t}EU26LOpp`!Mj&v+3^8(iyq&&t1Zw^fEGw74mGSwUBflB#2@Nzs8O8)ZCC^Jje1M`A@u#k; zqze{2zQGS1S^A&qI0*_?2VpRB3#8&bka+-YU9fR2cSu7zz|=f0lY2= zr68W6Hc2mqk=2u%Eg0fKNqr-XLJRfB+|6_XGBn(H{ahG9M$jD=P;YuTT%>jua z-xqB6gU34dagcm4gjp%r82&t|!tU0Jlxy!-M>1V-g-An?bMTEJ`~>S5D}sXy+x?+~ z;u3YcX$QvOth5|AjHUE=zVg3h&B57AggCVBR6CVZvI5tZ$bPGifwRwGO@??~kbq|u zf!*j{rgPJ9w^-J72DY+->;W zJU4Tt3FvRcbfnzDwZgf9`B!e%oiqaaf=U@C7y+#3JTcSjo8IHjqz}7_L*B1_a`$S=v*h-z6`Xf*2K$cQ@u1{cp zQ?&(c7PPJzv%J9>WAB9f7apENH@(k+uzgU^=5Q$=#WcXdOT^k3PUKSVkUnMq;zS;@ zF-vmw(e$}Tk7IDk4epLoZ&%~QQ*yxGXCkv9L0IyYe)Eg!cB`(-Vr`#Z*A7=s|N}262o@aBd<3$ zfS(A+JqzRlOi^0!j^KMmpVfzG`3ZA+T9dL=!O|~5P@|IlXF7;|qOELj&iY$>M0nAAQ~ud?1SOJ9@hXQP$K& z1tafIjr}ngOO)kMcUR6f?uqp!8U|S|!KnNcAs9&s;G7Ht`a7!gFN9&rbkX)5H3~`gCqJ&0n1M>NG!s=YK+vj4lO(zwju_8f!qa5xf79mnL>q zBR+j=4vgB8t9>HGj#qri$vCeuF8xAH-^w8t!W?BGRZ4E7bU!}VxYWnlavM}moi9P5;6h{Q{HVzccNJQaru=7HSjp_Z# zh$ct;rNOMG#m6&m9n*N{7x}y7(Si7kO>NGu=vh}{5DTfmF#E&Ag(h~jDhuj6e5Aa4 z0B*m(wnz#%p-g70X!@5A#5rdSs~Qq3%}W%4d1k&Y1Z$p6cDL*6UCrZgsh;gzhMsN7 zut2a7WqXguOVyk~8_L=FxC8=i(OviPBwRF(A=sbpSxE@ZyG@3}nGk(b4l0r&Do)_^ z8++evErH)^={IZkK@>N;9^wb|u$u%Fb6_xTgoUTY%N%#_wd*|PXh@FP5Ht<|UX z%AfRM16x^Va27g(llZLbT+Rd?axa!y#`x}na^0?Z#`sQiKP}kJ`BI+V(~$?5c=-;8 z9S+`;!ruu_5IEDOP24TCfd3lbeh=j^`V^ps;lRM|Xu!aDem<0Y?zE3%vwi3>mH@${yY z)ej%;;ySbF?01(qO+D*fK!doKq1>$?hJF+0bgtb@rxF7$$7Hlq2rlrV;)Ss#G6q4G zB;EPs``3z}En&(9xZ+in)nXB`V%1Hvuyv0_ngwWO>zT7c;91RM)heJ0sK=iAaky$-m1t&;vG#daquUW%E{P9K*@!uj9^o9L`O*IX62fW zr@fX+NK4i zyM%tU;G2-Z4Zuk`;RgR5-ZT6pdXu0v_QRNbKV>W&ykm&svo0(##&?J!W=|uHpWqaV zY9{1BuD?{b?8{e)cbF2mUi6d{nx>#0fp9khB&3tS3fivi;pfxBqvGGy7SbNeQNb0k zPo_B63S_+VI^OY0J>3(Nqh?xprrZ~x&~81QVMVY`n#V&ZZjp26+nwZm_?hYat8+Ep zVRcl~rXYEf-tFnm!NAv(83D!Clw3eIM%qSIQRwk2HvpUhyhjp-w)hu=NX`LXaXm#X z^--2xG=?Xy_`meZhMvV&!$x$_0v1kaEk}-f>MHVa0qdhHXn0Ob^2bUJp@*;?p9LPP z@)uv5S|$T6q)RO`bx}~BG9}|4Dg#HBEKvnWkH^oO=$aaXMn<29zJ&=Hv=paoEMnG9 z+B4vI{RwrpmFys912nc&GzCymlDBrn)j@ z-InmCU}d!(*Sq# zJHv1dH#k=mi&Jz~Cy#E&clg>i>9Av+%3a9 zh$B5`3YqxGTRRTLN*Z2xEBr*)-*fEkrpW{(aZ*7K2H<7?7d5yd906U94woVvN)9!@ zL+w6EsqC)sL7SZYNhk35-a(SQ`OVP@$Ec`uOt!&H^H`ah9l)-ggAbleaBXs;b+@?Q zI)YG_lu^MOAF4MUHl1EfYswj~c?QDmLoP_ua4KqoS-37SvAWAnhz4+IS56jq36=+0fuonjrEFKCUUZ$8p6a8HaDCBlB+d?%xgQ~> zPH`>f=PUS%T;d!wECIamA`emved1@OrkWTKxI1_-Abna+{jo7!4UeLshXtsm1DVjp zi^pccOx$TM=LTcA@Xo1yB}y5znjXB_E&QwmW$O8CZf9d=fj3yzLZ?i{o&b$pHP`N% zE@?J-xwtZM9IC*u16!t{x(s_LQy_L6t>Sc#F{^Q2*dwBB`lZQfdDFxN_6h!Nbwi^z z5A#(3Io$c_Q0HlIV`qHR;|+$Zok_@3RtvDz0#xQ$W*+lmFoCLGzt~h=OL$8mo>H<4 zNV^xxw`!pt$DhsT>XnwMp*iJgzJv;IRWA^<=H~#}T$l=aqhG?Qzp(b`=DUh@376cV zCGh_6+!3h7vr5B;^uhQvW9W=;5~VBql{(&=8YFFt;w6_H&-dKC@5K90@bRS1al#M< zu%&xPdsHFzy-WEqK2XC?5y=|Ea zJ%zl$2pcz4p|SMj14l5vs}CPjQJY+3&wpYoC>&QatQm5^?7qf3t}IJY0~NubrlR|_ zMiX()S@IneEAh>((OQi6s%E1)X~YJ7q$9TuLs)#3W&t@v-dsda|MJpu;Q4h+hPV46 z3J0*N!Zp_*U4H~#9=%4O+a=iEvs{F#E7*3TJhuW3*h-Yjw^k#{vX+ML1zqD4deEw< z!*1T(4dsCfrN!lyAbUedtZ+>5zQ?8a71s>YKG{v$hD-MzJVdbf(=O*2ouEaZ#FP=s z7sF$3KiQ%erwqpP9+~SSJ&8<6k9p&4F3^Bm&7+xVB)VC}1QdA`V5z{fM$Nlw5sp_rKB)WpO0avx`K1IfXQl_h@SXz2Y#JQQ1SpkI!-eLcwk+?C?zOx>SYJL;kc(wDMf9?&KXzcVw(f(b> zjGfk!9UBV2;q%?H8`0pJ$oDQo*2^wjDD<*ct?F2abVK82HFdRfTP3!Dw3TUlf2el; z`$`0yS*6*kmqt89PN5g$#yam^`OqvQ7_=as(_&qFAyt_X47fi|HKGs`_ZW;jCmp3 z+GQ;#z{hx&=oUV0wuZVw3P@Ev$^Eg>QEy7gCB4S`D}zGW$n5>ev5TnSr68VRVCnX# zgw}k@3)$E7<_l!jd>-0DnzkrSCIZ_c_mht_YdcrB>V}qZSNM09W?kW)p*}Z)#MNlK z*X*zxflbM)ki4sMG~;&jXjC^Cugltr<<+h9if&{kTE{X>i_#O}AuW7eHeAHLP(tT* zce7)3zc_HwaNYTJryW=QhUkx8V(!a)i`SrS6Jcyn`*|<%N3wrN>zUge=M$g94}Kmh zA)%JD+kM-vdBlY~YiVb$Z!SCg4gz;0NF2$tgTOGLN-O|hFVexKU)6K>ncYNVy@7%W z{OEJ~iYjV)GAbw)$UbO9Ei1@EC2GD2T}N~uE1;nGVdia|9kN7TUt)o@$T6<&RN#G>flwT&$4J3OhQkeQEQrPOn*- z!&03_ITjaA9T1H_bC}qKsI;UPtXy4}KXP+}-g>Oa6c}|Mu=VpFtweH32|_S4{(bDxw!`6c8$yLMA{BH)m4qn%s%MkM$V|5 zf|E~Xo^Ot}4YWpf?)GO&Hxji2?78n4z5~D<_kED0S|#U=te2&#`qJD$Zb7j!*)Q^` z8g(k5hunSQ>2-#N0%->KV?mztLKwF5IJ?XvyG(M4OJ~Z{B+96{2(lzGh`f^MMP!o> zGz?PIwEIH*h}N!}nDtllk&!DT)aWFr`QGlc{pZVDp#yYvn4CkYb%-yhSfB5wy}GK< zZmOm=&wnJ+`EEi7mPM1Y_OzkF)1>;S(dTf|Zd;sZg7yXn(;V56Szmgn+|2F$vCmaC zk1NJ*UcXoKlac90xpDL-x=!VruiVDavwggxOAU&uNyWo<-p16VOrSkevV$vLi1Y2y zJh>Fi@9}LC2#eB;x*h#MBbf7Pcim0;Y)LGS5I*c#f~7XPoUyDYvqzggueqL0J{?<> zb}J^P@*J!Y-^xHv8o0Wm$WSyc5A^c;BE~$@TsCTbGvwS5O=cp*(Fj=%P8AdVcAEHe z;B%ydBYP{71ad-2^D)ybjv5Hu0(eD~5*llJ2jGbJP?-j{o+Xl4%5wh z*pfLY@@UMqnj)F1x-eGr*DKgopWhx>#*4l0*>&+viihP0dmM~xoNkQN8uIC~KQqH| zaULpx9+T4Ky{PuQD}LzBz`GW`y67T^yIu^Mm}{)wgxsFC5;YxUj@cvWm}JdpPD5{P zpom^|8#?7jH+wX)NoKua@3ha-T$5CZ0%sKv^wrG~PPN3LUXid5J> zor#AEhB{m0q|0}gy_STtb%4W#<%ZGeiD9iAGl+3Fv&`~zCnu~KTwdmgOy;FlB(h6B zI!XX2cFdT=min~Y=A0`zi+U(G8*=GYbIEz8rF4uzz8Qdk3y`EE_U*libDlj92(54l z5$m&{`m(Z9pF@svJW*Vt<sJBmmnP(G)#(VOx$L#+xItSj3XR09RWy&T{D<5K8CG zNwQTyppUWlr1y-F+*RTb8W`$oSWLhDQRY&q-WbZjGe{Z4wYlyyP1dC71cj@v$g5{tGGwuX(w1_uVz5L=qw>3Ug!G4e z%8%Kz_WS2$B8HOZ3e`3!XDUcKC-Q7vGti9f3PIa8=Nkd(Erz3k00wpO+`35_Rr=N; z@10M_9_Bt=uC_ILp9f*|s2i|xPn2*)ls6bAMPRsZlmjr>dMBieO4x(qnd6783s1qo zT!zTxVe1i~LZX+WB^uF~|laFh16Rj%i!Ie%E*E+K3jUL#_ZE zK3(K?@FVX-A9+J5*6Ybc$AYNzbPMhJb4|CL>e}{!-PjsC)9SNPJt-J}mPT>XFA%J2 z2^I?5l0AaN66;1J&FlQzi+igq1_sUZu;&Qd6!3E6>FOD#I?M1+@9$2|-V;}U?2J=4 z?Ks$ppt1_|3M_J{Rlba+*7bMrf)p=|5kiJ@1fCysaT9TFyuV<5gBp6#@1DF^+4Fw# z$Q#mR&BXS8t0ccvp+eAnXNn;GH8Qe~@wsyR^OR^K<4+EhJ4tHm((~`G^WX|MXkLbJ zuXZvCnAQ(w^YP6&lqmNdxVjncx*G198EUE*ba@Eg7vr$rZy^?bAYk1*a$A?!|6~e-wDoSfnnnWqLtubj9Fx$c-twqd8XU=MeE3bb=wTtHh}@5Nocho)=wmEZ}geu zAzH45ki_{KQ)95b#G#le~{Xl%K?LohW{(9P{;D%1Pk)Zil9pMe86AQKY%9J^_F z=0XwM8#C^5phwwkit`1>o&%CUUv7DkKs)YfFbB}>V`q2PCAE1P$DmEsJDa#vF(f(` z6erKovaY9@SCpOki>1wdBtg2NCDnD=p_Lfo_%=#nik}w(vOjciIiM%!^1b(>UNH?J zb!|px#HHkJjDiEUM8g3EyP>R}jb9I3i;F@VOXXY~W?xdg=!$xhOIZJMv5n?k)ah5Q zd+0xUI@0MfS=r!VV6Py-z_|aer}G@(!SNR+&*>3~TN^ z^Ndk3C_JDope2CNkM;{Wfh=vxeixa3%F6(Id^oKD0qzeKQ!KTcK9izd2@zez+8iHt zDM5C78if>VUvvy`>k4PMm`^~yuk9xhZevyFn)0Y)_F6A49Ca^9DlO5Fdw%z+d0vDxd z%)YhkJe!<%^!;e5Xl>f5_IO7o>6c5RQl9yDG>}VQETB-YYf^4y5|sGt6Ou>eZ{7gv zrOZ||Uno5e7)|E3>&QYND;E1Sz=i!(r{EHqg87EB9BL~dZx?;6s5;*0`Nv_X_v$#vGj`P27BFd+NPzu z>Kc}(CzAMObnMsC2Jj08H_=nYg(hU2O2mT|IKpF+D>w-E_jj97jwwxGe|+tQ7^I|3 z5MW?kP+(wxyFkX?$i&LX8~}RTcD4!eePMVksKJLm@XM|EB08WDuUsA$=qLp%KoKq4 z>!(B80I(8OnPcf_ys_BsN*Sauv`{-MEc&XFKqLVhff2*3|Ms}s!4fJhn>6Bsy0*5r zt6`5FsWZfGokmPUhbn)c227-m?Tg*342av8JEDkwuCqB&JfQ=P;f3n%; zLnb`*S+8C56Hcwr9Jz_;R?J@Dy8{A<)8w$iYA7__`!_{jFtg(O^aN1u`yq^sP*q^Y z)dCu><23l1iO|tx+VT>q{E#WuS?nQoICRUTbQl?CvM(jJHej?F#7vZg`GyG7qUK3_ zK3MOv9akOj7f_#ErDpNU0p=b7$WL$(TNcMxC>sqDC(3J-sXt9yaksA*GrT7CL1Icv zaPhBS--1NjY=8PG-7Rg~2ip|>Yr{hPxH&Uwx2iI-X2k4TWV{5sS1EiR4mxHUW`6Fj z4{uML>%!N(5Afl8Plk`GBr{7+TQTo88V{E6IiXXQyVT?NsOw)C#gUYZ-|10XowH7U z)kN1N7~?i4aF5&+t!!A2N#)2%uV?NsXh)Seb(F^O=OIILZ74{ron(JOt2MgrjQqY9 z!>CNBc-oQQ6aVRhBz#7Zt)dIa`j|l0$Mkn69XV-HaRpUzMjKN-6$86jW>nvceD323 z8D-5g2RllZE}bWmkvOX?2@G-kHfMC^T_u(E377FyaIo_AX`Kq1FfFQJT_4>?!C ziJ=T#!kF_xLtT1X&u?{;v5(}Scl1q@$sdKd+fcslAYdoCoZ{$xly1jF#n(+4yV!=r z*$O%9FYYZ#PiP(kx;#?r##|DVD&0Bwx zZ3;t(la$szw*w&qz8+qK^FRb|h;*`@I|^eKB?o;|5uWBNxBvo}U_@l^VQs;MAvV)H zIfRG{4Co?VFW>9bPH5LUIWn19oN*7`nc~a2niyJkpQDbY59lRlCY#jCm%!vUjmit( zy|i`L#Zk#B&q|?3+`jr}i}2oTh-I}GLD`I@wO3R?u@jP&Wj(gm8O6%QdzMTkUxq9V zy2^DOzvAq%o%}&D7zF)Qub5Vi)aqI6R=6SAO2}#m{ez_t`bwzI4>GUoVe(Swi*(_O z`&fs#Qs@ngUe&2A`)Xm15f>^81-Q}DJSU}lsqpD?O*TcgQg&JuG`Yf|N6vIs zF<_r6-USs`(LRyb6?>T~jj9=jhfspstP3T%)l}H^h{QBtvsWE0nY0;2u)O7u^QWOC zRR=X_$?Syz17rNV7OWyJEGGZWfJ@ZoY$upey)QK78lE`Ul4nav6+BORO|3$~h+-3@ z6ogBaL2gUHSCNi1_rZKmJ`q#vxP9Dg(-WA2letF$m#pC#joU~=BApmMv=k9%lW*S| zaM3)fZ8Wqr!dl~Yhw-|$?ffq5xY?;kn{tlVB|?lsmsVcGUfF~*hyp7+wwOFDSLtbK zuJV=vUyFvj4$hlPn7HHGSj#yml9CI~#QCgr}I0HlEaT=_11C`aY6q{F6jzvhYkzPa7v}ob8C2oGS z(n`LDb=)LXF|}ZWg!uaGD%NVLABWnWHV{H1R`spEo7S2#)z>7@Rf{S&*s}pYs+9J&T(8l`x5aO83tF!;x^RKLWxe* zUL5tr9hH0kst$+8pS6o2Q2<~Km)WA5LC}LK@ty-#TirrANvirz=rx+vb(>r<0Z*vV z$Q0MSB-ap1m_9-fnRZycuABQ~92k|w$AS3PADXPCdB~Vi5g?z4b>px`Vx%=vG1FBE zhnSn5*^?pG;|URXoJZbbtl2uD+LF364+kboz||)@ynq_>vw~$hb3t^p3MxJv=@9X2sg0Ua$$=VQ59R!o-)2 zBz>53%uEI0HfAh6&)L_K&c$>0Jc(-N-HBtvuD>UDJ;O~MUW@F=7;4GlliNUvf+M1o zTWIReO}}zGC>DGZaVR)(k&_#kmozu_!pDGV-JZZz8;hYRqn)pH09yM5<@z^^=C$6) zJ`lf-IneO>k1A&7zdPoBDGqk_u>Z?K=fCav{!W?&z}g<*_`Q7k`}Q*XNyCvCh?^#; zsr>}U?^2D8oB*8c>MC-o&W@J0=4y5#E@ox`M@CadXD8Vb>Ru*VWhrTSpftUVx)j}z zEMwo`u&R^{y#fat9MTCKBTfIHEJ~jnt-P!(!tBnyRbA}u?Hrw*Gy%rK-|EDFVGVHq_B&!zfQhw{BY@b< z#n!~x($1Fnw?goT&rs9w5*ypuSp$r0`QZOJ_qrDO%*cY6%7dCNsQsau{b7mv_d4_c z^5*^o8ARF6%+lKWuXRn^&%~s_0MEz()`u06Psx**Xu1ae>b7by4IfFKF32zEc7AY0 z?M?3OZQ4X9Kc5xj0|%V4({brrDY*iu{VSFKVizF$_@lx65Axsa0>01fj|TI}FZ3A= zHzo#!1}~`aPy@cpQ2IY;zmxVy5Cu_|0yRZY`)S?(Mq6D?g8Nq!|67bvkQ^#uf3faQ z)Uty#^3^K#^t3X?&JeOzIyC5k>%|`*s2RrJ68SZVXFsTE{R_U9rl2s_(#+$VJ%771 zG5Th_;*O4Xzm7@0$a3U%W<;?IpDr8d!homgsKye;M#zO^q}9?6_;BdghtXgN`qm5S znLv3bL*ece#s+dtUqj?@=){hfu9Xq(eNxsp!3P|?(KsAv)+Z9WNA{2&4(G~?0|4h3 zI`af!fE%pSW0MeZ5-xW|4)o`xANsl8mYEmHJoW#A%6Z1Jw8_ozqAI6g8*$W9lo7YW-wmhEx4J3tpKRlH#%Mz9NaK;5qp!^@T&Op|=81T~Uqt8!~`!rFn8 zwNo9WaD0u$qL~++x=qu%DWHJxQRu0qsuF?#glu_^oY5$sO{l12GV z(lD~NG!?V6F#;W1`KF3Lo5}z1Noor_CudtD8vrjc$Xq~6*q_hmP2fQ}av+A^rb4}c z!PMT`$l1)!(dKt!)Xq`bN!ZoM(%Q(_8t@Bw=r$H)KVn3%)&))G9ju9D=K8Ck018eT z2AZzR7l%hy&k1b@5reZ4`xI!iS=^Q1J6r~?#J5cX2@QyYJGq&x>g4EL=HqC|dduYn zf3-CbB0tQpj;v5uE!Zdw45TCz2q7Yo&h8LENO@ zL2HXan7$$R)CiwR@{&MjxNMQRV5se!`w2&J6b714MZsdiPyj*Cdp`uW8sLqKxO_Mv zr5r-u7H?b6Zl=b-D8V0xwv{eZY5X_cgB0`4a{lQ`^asWKepdTcEs?_T?Lvs+7f;1q z)s^O-J#I@6Nbn5UW}j?zHj`4R3UzavO&|_tvxlZ0Th;Bk&Vd|AJB6j{A}wxP)@hCYDq!qe5*d&CmK zX_0R9vgX3|#iN|yGbcl{7K|z1BA_Y@T+Gr&(rHca;vf5O)DzbCZACK!wQnBhKkfhb z@eLZCE+)=Szx0|Tlm*_885QcLaYY8&AS+1g5@r`03u93HfRQ-Vmy1||g*k9n&bW#g zUtg%Jh~0>=!iGPLoJ1E!KfW1sc1^^XqpvMi?QxNhxa|5~BWI^T&VA*<{Hp#Rncu2c zqk4iEw}9HeS(2RXerL~ij>68)MkW@&q@%yhQZA7!pcVOBUyK`s{I}wQ`MbEy9b>&~ zfac(&x9QZ-di6M#96AaV@0SA$XGDzm(gEp%X$E5(m!uX7TXqSmufF6q%q2QjyJhbr zyw-Ew>xtC&vZ5qPeS`cc5lze>tQH2iP z??n)Lvdfi67X|!!q4cY*DQzQ{mmGtBJ37C(?cflCkm#V^{O9WQ?FjJqYyVq$%O88J zB>U%&emfHU{n{6%1Ks|mvi?fcwP7`!2AJ+NBTG6{>ygeLzIX6Wj|1!kpE4T z-|wD16#sBT^9dWIX)O0^f3S->-e) zZu-9|`*)d{zmopVrT%{H3!^jqbLrnbp6@8%$Hl{(-FK8+|L6Y#<*zb$zcPUT1?Za= zALieFFdznPF8r-G^gAtn@8_T7w|?>T9_rv>PVEN+;QxOHphfaWhV3Dfhl#NtOyWRW zg+Hx}zetlkWbiP@^@D*7$i)9Gg9jO}hu{wrRzJY6{{{H}N?$!>@i1%jgT)PKE&N#( zd}s0dXzND`?IDMUxtkvxu2}y$haZ`oUvYj6zK4mDA2?sw{yEO~!S{z`$bTJj57Qn$ za5LC{9`|o0LB6Z{8|1@T{Ezc2fa9N2`5sw+NBKU_K1^l&=y1coK>4%8#zXXn`GOzl z6P!Qa$6wHYZ_oerRX>c?e}~QW&#}Lo*zY6vhrN9mWB)*m1ij#&9l(DbaX;knF!KGu z;RWdA<c~$@+Z;hL-2>u { + get signInWithRecoveryCodes(): SignInWithRecoveryCodes { return this._signInWithRecoveryCodes } - get getRecoveryCodes(): UseCaseInterface { + get getRecoveryCodes(): GetRecoveryCodes { return this._getRecoveryCodes } - get addAuthenticator(): UseCaseInterface { + get addAuthenticator(): AddAuthenticator { return this._addAuthenticator } - get listAuthenticators(): UseCaseInterface> { + get listAuthenticators(): ListAuthenticators { return this._listAuthenticators } - get deleteAuthenticator(): UseCaseInterface { + get deleteAuthenticator(): DeleteAuthenticator { return this._deleteAuthenticator } - get getAuthenticatorAuthenticationResponse(): UseCaseInterface> { + get getAuthenticatorAuthenticationResponse(): GetAuthenticatorAuthenticationResponse { return this._getAuthenticatorAuthenticationResponse } - get listRevisions(): UseCaseInterface> { + get listRevisions(): ListRevisions { return this._listRevisions } - get getRevision(): UseCaseInterface { + get getRevision(): GetRevision { return this._getRevision } - get deleteRevision(): UseCaseInterface { + get deleteRevision(): DeleteRevision { return this._deleteRevision } diff --git a/packages/snjs/lib/Domain/UseCase/UseCaseContainerInterface.ts b/packages/snjs/lib/Domain/UseCase/UseCaseContainerInterface.ts index 4399a41e6..06c72a5a4 100644 --- a/packages/snjs/lib/Domain/UseCase/UseCaseContainerInterface.ts +++ b/packages/snjs/lib/Domain/UseCase/UseCaseContainerInterface.ts @@ -1,16 +1,21 @@ -import { HistoryEntry } from '@standardnotes/models' -import { UseCaseInterface } from '@standardnotes/domain-core' - -import { RevisionMetadata } from '../Revision/RevisionMetadata' +import { AddAuthenticator } from './AddAuthenticator/AddAuthenticator' +import { GetRecoveryCodes } from './GetRecoveryCodes/GetRecoveryCodes' +import { SignInWithRecoveryCodes } from './SignInWithRecoveryCodes/SignInWithRecoveryCodes' +import { ListAuthenticators } from './ListAuthenticators/ListAuthenticators' +import { DeleteAuthenticator } from './DeleteAuthenticator/DeleteAuthenticator' +import { GetAuthenticatorAuthenticationResponse } from './GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponse' +import { ListRevisions } from './ListRevisions/ListRevisions' +import { GetRevision } from './GetRevision/GetRevision' +import { DeleteRevision } from './DeleteRevision/DeleteRevision' export interface UseCaseContainerInterface { - get signInWithRecoveryCodes(): UseCaseInterface - get getRecoveryCodes(): UseCaseInterface - get addAuthenticator(): UseCaseInterface - get listAuthenticators(): UseCaseInterface> - get deleteAuthenticator(): UseCaseInterface - get getAuthenticatorAuthenticationResponse(): UseCaseInterface> - get listRevisions(): UseCaseInterface> - get getRevision(): UseCaseInterface - get deleteRevision(): UseCaseInterface + get signInWithRecoveryCodes(): SignInWithRecoveryCodes + get getRecoveryCodes(): GetRecoveryCodes + get addAuthenticator(): AddAuthenticator + get listAuthenticators(): ListAuthenticators + get deleteAuthenticator(): DeleteAuthenticator + get getAuthenticatorAuthenticationResponse(): GetAuthenticatorAuthenticationResponse + get listRevisions(): ListRevisions + get getRevision(): GetRevision + get deleteRevision(): DeleteRevision } diff --git a/packages/snjs/lib/Domain/index.ts b/packages/snjs/lib/Domain/index.ts index a5ff50e6f..d1fe689aa 100644 --- a/packages/snjs/lib/Domain/index.ts +++ b/packages/snjs/lib/Domain/index.ts @@ -1,2 +1,18 @@ export * from './Revision/Revision' export * from './Revision/RevisionMetadata' +export * from './UseCase/AddAuthenticator/AddAuthenticator' +export * from './UseCase/AddAuthenticator/AddAuthenticatorDTO' +export * from './UseCase/DeleteAuthenticator/DeleteAuthenticator' +export * from './UseCase/DeleteAuthenticator/DeleteAuthenticatorDTO' +export * from './UseCase/DeleteRevision/DeleteRevision' +export * from './UseCase/DeleteRevision/DeleteRevisionDTO' +export * from './UseCase/GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponse' +export * from './UseCase/GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponseDTO' +export * from './UseCase/GetRecoveryCodes/GetRecoveryCodes' +export * from './UseCase/GetRevision/GetRevision' +export * from './UseCase/GetRevision/GetRevisionDTO' +export * from './UseCase/ListAuthenticators/ListAuthenticators' +export * from './UseCase/ListRevisions/ListRevisions' +export * from './UseCase/ListRevisions/ListRevisionsDTO' +export * from './UseCase/SignInWithRecoveryCodes/SignInWithRecoveryCodes' +export * from './UseCase/SignInWithRecoveryCodes/SignInWithRecoveryCodesDTO' diff --git a/packages/ui-services/src/Route/Params/AppViewRouteParams.ts b/packages/ui-services/src/Route/Params/AppViewRouteParams.ts new file mode 100644 index 000000000..b191b1148 --- /dev/null +++ b/packages/ui-services/src/Route/Params/AppViewRouteParams.ts @@ -0,0 +1,3 @@ +export const ValidAppViewRoutes = ['u2f'] as const + +export type AppViewRouteParam = typeof ValidAppViewRoutes[number] diff --git a/packages/ui-services/src/Route/RootQueryParam.ts b/packages/ui-services/src/Route/RootQueryParam.ts index 216029a11..fc0943f53 100644 --- a/packages/ui-services/src/Route/RootQueryParam.ts +++ b/packages/ui-services/src/Route/RootQueryParam.ts @@ -4,4 +4,5 @@ export enum RootQueryParam { DemoToken = 'demo-token', AcceptSubscriptionInvite = 'accept-subscription-invite', UserRequest = 'user-request', + AppViewRoute = 'route', } diff --git a/packages/ui-services/src/Route/RouteParser.ts b/packages/ui-services/src/Route/RouteParser.ts index 83cc4fb78..ade6df172 100644 --- a/packages/ui-services/src/Route/RouteParser.ts +++ b/packages/ui-services/src/Route/RouteParser.ts @@ -1,5 +1,6 @@ import { UserRequestType } from '@standardnotes/common' import { PreferenceId } from './../Preferences/PreferenceId' +import { AppViewRouteParam, ValidAppViewRoutes } from './Params/AppViewRouteParams' import { DemoParams } from './Params/DemoParams' import { OnboardingParams } from './Params/OnboardingParams' import { PurchaseParams } from './Params/PurchaseParams' @@ -78,6 +79,18 @@ export class RouteParser implements RouteParserInterface { } } + get appViewRouteParam(): AppViewRouteParam | undefined { + this.checkForProperRouteType(RouteType.AppViewRoute) + + const appViewRoute = this.searchParams.get(RootQueryParam.AppViewRoute) as AppViewRouteParam + + if (!ValidAppViewRoutes.includes(appViewRoute)) { + return + } + + return this.searchParams.get(RootQueryParam.AppViewRoute) as AppViewRouteParam + } + private checkForProperRouteType(type: RouteType): void { if (this.parsedType !== type) { throw new Error('Accessing invalid params') @@ -99,6 +112,7 @@ export class RouteParser implements RouteParserInterface { [RootQueryParam.DemoToken, RouteType.Demo], [RootQueryParam.AcceptSubscriptionInvite, RouteType.AcceptSubscriptionInvite], [RootQueryParam.UserRequest, RouteType.UserRequest], + [RootQueryParam.AppViewRoute, RouteType.AppViewRoute], ]) for (const rootQueryParam of rootQueryParametersMap.keys()) { diff --git a/packages/ui-services/src/Route/RouteParserInterface.ts b/packages/ui-services/src/Route/RouteParserInterface.ts index ddc01ac81..61bf3e3a8 100644 --- a/packages/ui-services/src/Route/RouteParserInterface.ts +++ b/packages/ui-services/src/Route/RouteParserInterface.ts @@ -1,3 +1,4 @@ +import { AppViewRouteParam } from './Params/AppViewRouteParams' import { DemoParams } from './Params/DemoParams' import { OnboardingParams } from './Params/OnboardingParams' import { PurchaseParams } from './Params/PurchaseParams' @@ -13,5 +14,6 @@ export interface RouteParserInterface { get onboardingParams(): OnboardingParams get subscriptionInviteParams(): SubscriptionInviteParams get userRequestParams(): UserRequestParams + get appViewRouteParam(): AppViewRouteParam | undefined get type(): RouteType } diff --git a/packages/ui-services/src/Route/RouteType.ts b/packages/ui-services/src/Route/RouteType.ts index 5b2fe79a3..e577f14d6 100644 --- a/packages/ui-services/src/Route/RouteType.ts +++ b/packages/ui-services/src/Route/RouteType.ts @@ -5,5 +5,6 @@ export enum RouteType { AcceptSubscriptionInvite = 'accept-subscription-invite', UserRequest = 'user-request', Demo = 'demo', + AppViewRoute = 'route', None = 'none', } diff --git a/packages/web/package.json b/packages/web/package.json index 88e9b8567..cc3df8e6f 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -38,6 +38,7 @@ "@reach/listbox": "^0.18.0", "@reach/tooltip": "^0.18.0", "@reach/visually-hidden": "^0.18.0", + "@simplewebauthn/browser": "^7.1.0", "@standardnotes/authenticator": "^2.3.9", "@standardnotes/autobiography-theme": "^1.2.7", "@standardnotes/bold-editor": "^1.6.4", diff --git a/packages/web/src/javascripts/App.tsx b/packages/web/src/javascripts/App.tsx index 99bd8cd10..6044f82ec 100644 --- a/packages/web/src/javascripts/App.tsx +++ b/packages/web/src/javascripts/App.tsx @@ -36,6 +36,8 @@ import { WebApplication } from './Application/Application' import { createRoot, Root } from 'react-dom/client' import { ElementIds } from './Constants/ElementIDs' import { setDefaultMonospaceFont } from './setDefaultMonospaceFont' +import { RouteParser, RouteType } from '@standardnotes/ui-services' +import U2FAuthIframe from './Components/U2FAuthIframe/U2FAuthIframe' let keyCount = 0 const getKey = () => { @@ -71,6 +73,13 @@ const startApplication: StartApplication = async function startApplication( setDefaultMonospaceFont(device.platform) + const route = new RouteParser(window.location.href) + + if (route.type === RouteType.AppViewRoute && route.appViewRouteParam === 'u2f') { + root.render() + return + } + root.render( | null>(null) const [error, setError] = useState('') + if (!application.isFullU2FClient) { + return ( + { + onValueChange(response, prompt) + }} + /> + ) + } + return (
{error &&
{error}
} @@ -27,18 +40,18 @@ const U2FPrompt = ({ application, onValueChange, prompt, buttonRef, contextData onClick={async () => { if (!contextData || contextData.username === undefined) { setError('No username provided') - return } const authenticatorResponseOrError = await application.getAuthenticatorAuthenticationResponse.execute({ - username: contextData.username, + username: contextData.username as string, }) + if (authenticatorResponseOrError.isFailed()) { setError(authenticatorResponseOrError.getError()) - return } + const authenticatorResponse = authenticatorResponseOrError.getValue() setAuthenticatorResponse(authenticatorResponse) diff --git a/packages/web/src/javascripts/Components/ChallengeModal/U2FPromptIframeContainer.tsx b/packages/web/src/javascripts/Components/ChallengeModal/U2FPromptIframeContainer.tsx new file mode 100644 index 000000000..549dd2534 --- /dev/null +++ b/packages/web/src/javascripts/Components/ChallengeModal/U2FPromptIframeContainer.tsx @@ -0,0 +1,66 @@ +import { log, LoggingDomain } from '@/Logging' +import { isDev } from '@/Utils' +import { useEffect, useRef } from 'react' + +type Props = { + contextData?: Record + onResponse: (response: string) => void + apiHost: string +} + +const U2F_IFRAME_ORIGIN = isDev ? 'http://localhost:3001/?route=u2f' : 'https://app.standardnotes.com/?route=u2f' + +const U2FPromptIframeContainer = ({ contextData, onResponse, apiHost }: Props) => { + const iframeRef = useRef(null) + + useEffect(() => { + const messageHandler = (event: MessageEvent) => { + log(LoggingDomain.U2F, 'Native client received message', event) + const eventDoesNotComeFromU2FIFrame = event.origin !== new URL(U2F_IFRAME_ORIGIN).origin + if (eventDoesNotComeFromU2FIFrame) { + log( + LoggingDomain.U2F, + 'Not sending data to U2F iframe; origin does not match', + event.origin, + new URL(U2F_IFRAME_ORIGIN).origin, + ) + return + } + + if (event.data.mountedAuthView) { + if (iframeRef.current?.contentWindow) { + log(LoggingDomain.U2F, 'Sending contextData to U2F iframe', contextData) + iframeRef.current.contentWindow.postMessage( + { username: (contextData as Record).username, apiHost }, + U2F_IFRAME_ORIGIN, + ) + } + return + } + + if (event.data.assertionResponse) { + log(LoggingDomain.U2F, 'Received assertion response from U2F iframe', event.data.assertionResponse) + onResponse(event.data.assertionResponse) + } + } + + window.addEventListener('message', messageHandler) + + return () => { + window.removeEventListener('message', messageHandler) + } + }, [contextData, onResponse, apiHost]) + + return ( +