/- coki /+ naive, ethereum, sr=sortug, cokil=coki, server |_ [=sessions:coki =bowl:gall] +* cokilib ~(. cokil [sessions bowl]) ++ serve-metamask-challenge |= eyre-id=@ta :: special-case MetaMask auth handling =/ new-challenge (sham [now eny]:bowl) =/ jon (enjs-challenge new-challenge) %+ weld (send-self-poke:cokilib [%meta new-challenge]) %+ give-simple-payload:app:server eyre-id (json-response:gen:server jon) :: :: Modified from ~rabsef-bicrym's %mask by ~hanfel-dovned. ++ process-metamask-auth |= [order-id=@t octs=(unit octs) redirect-path=@t base-slug=@t] ^- (each (list card:agent:gall) [@ud @t]) =/ challenges challenges.sessions |^ ?~ octs [%.n 403 %empty-auth-request] :: ?. =('auth' (cut 3 [0 4] q.u.octs)) :: *(list card:agent:gall) =/ jon (de:json:html q.u.octs) ?~ jon [%.n 403 %empty-auth-json] =/ body=json u.jon =/ axn (dejs-action body) =/ is-valid (validate who.axn challenge.axn adr.axn sig.axn) ~& >> signature-valid=[is-valid who.axn challenge.axn adr.axn sig.axn] ?. is-valid [%.n 403 %bad-metamask-signature] =/ coki-hash session-hash:cokilib =/ coki (session-cookie-string:cokilib coki-hash who.axn base-slug) :- %.y %+ weld (send-self-poke:cokilib [%coki who.axn coki-hash challenge.axn]) %+ give-simple-payload:app:server order-id ^- simple-payload:http :- :- 303 :~ ['set-cookie' coki] ['location' redirect-path] == =/ obj=json %- pairs:enjs:format :~([%login-ok [%b .y]]) `(as-octs:mimes:html (en:json:html obj)) ++ validate |= [who=@p =challenge:coki address=tape hancock=tape] ^- ? =/ addy (from-tape address) =/ cock (from-tape hancock) =/ owner (get-owner who) ?~ owner ~& "no owner" %.n ?. =(addy u.owner) ~& "wrong owner" %.n ?. (~(has in challenges) challenge) ~& "bad challenge" %.n =/ note=@uvI =+ octs=(as-octs:mimes:html (scot %uv challenge)) %- keccak-256:keccak:crypto %- as-octs:mimes:html ;: (cury cat 3) '\19Ethereum Signed Message:\0a' (crip (a-co:co p.octs)) q.octs == ?. &(=(20 (met 3 addy)) =(65 (met 3 cock))) ~& "addy != cock" %.n =/ r (cut 3 [33 32] cock) =/ s (cut 3 [1 32] cock) =/ v=@ =+ v=(cut 3 [0 1] cock) ?+ v 99 %0 0 %1 1 %27 0 %28 1 == ?. |(=(0 v) =(1 v)) ~& "wrong v" %.n =/ xy (ecdsa-raw-recover:secp256k1:secp:crypto note v r s) =/ pub :((cury cat 3) y.xy x.xy 0x4) =/ add (address-from-pub:key:ethereum pub) =(addy add) :: ++ from-tape |=(h=tape ^-(@ux (scan h ;~(pfix (jest '0x') hex)))) :: ++ get-owner |= who=@p ^- (unit @ux) =- ?~ pin=`(unit point:naive)`- ~ ?. |(?=(%l1 dominion.u.pin) ?=(%l2 dominion.u.pin)) ~ `address.owner.own.u.pin .^ (unit point:naive) %gx %+ en-beam [our.bowl %azimuth [%da now.bowl]] /point/(scot %p who)/noun == ++ dejs-action |= jon=json ^- authorization:cokilib =, dejs:format %. jon %- ot :: :~ [%who (se %p)] :~ [%who ni] [%challenge (se %uv)] [%address sa] [%signature sa] == -- ++ enjs-challenge =, enjs:format |= chal=@ ^- json %- pairs :~ [%challenge [%s (scot %uv chal)]] == --