Files
boc/iom/quixzoom-auth-service/routes/__pycache__/passwordless.cpython-39.pyc
T

97 lines
8.9 KiB
Plaintext
Raw Normal View History

a
é¤Lj)2ã@sPdZddlZddlZddlZddlZddlmZmZddlmZddl m
Z
m Z m Z m
Z
mZddlmZddlmZmZddlZe
dd gd
Zeje d d ¡ee d
d¡ƒee dd¡ƒddZdZdZdZdZGdddeƒZGdddeƒZGdddeƒZ GdddeƒZ!GdddeƒZ"Gd d!„d!eƒZ#e$d"œd#d$„Z%e$d"œd%d&„Z&e$d"œd'd(„Z'e
e$d)œd*d+„Z(dJe$eee)d-œd.d/„Z*e$e$e$d0œd1d2„Z+e$e$e$d3œd4d5„Z,ej-d6ed7e
ed8œd9d:„ƒZ.ej-d;e!d7e dƒfe
e ee$d<œd=d>„ƒZ/e 0d?¡e
e$e$d@œdAdB„ƒZ1e -dC¡e dƒfe
e#ee$d<œdDdE„ƒZ2e -dF¡e$e$dGœdHdI„ƒZ3dS)KzS
Passwordless authentication routes
Handles cross-device login between app and web
éN)ÚdatetimeÚ timedelta)ÚOptional)Ú APIRouterÚ
HTTPExceptionÚHeaderÚRequestÚDepends)Ú JSONResponse)Ú BaseModelÚFieldz/auth/passwordlessÚ passwordless)ÚprefixZtagsZ
REDIS_HOSTZ localhostZ
REDIS_PORTiëZREDIS_DBT)ÚhostZportZdbZdecode_responsesi„é
éc@sLeZdZUeddZeed<eddZeeed<eddZ ee
ed<dS)ÚInitiateRequestz
web-dashboard)ÚdefaultÚ client_idúhttps://quixzoom.se/dashboardÚ redirect_urlNÚ device_info) Ú__name__Ú
__module__Ú __qualname__r rÚstrÚ__annotations__rrrÚdict©rrúR/home/bernt/.openclaw/workspace/iom/quixzoom-auth-service/./routes/passwordless.pyr$s
rc@s:eZdZUeed<eed<eed<eed<eZeed<dS)ÚInitiateResponseÚ
session_idÚ
request_tokenÚqr_dataÚ
expires_atÚpoll_interval_msN)rrrrrÚPOLL_INTERVAL_MSr%Úintrrrrr *s
r c@s6eZdZUeed<eed<eed<eed<eed<dS)ÚApproveRequestr!r"Z signatureÚ timestampÚapproving_device_idN©rrrrrrrrrr(2s
r(c@s&eZdZUeed<eed<eed<dS)ÚApproveResponseÚstatusr!Ú approved_atNr+rrrrr,:s
r,c@s~eZdZUeed<eed<eed<eed<dZeeed<dZeeed<dZeeed<dZ eeed <dZ
eeed
<dS) ÚStatusResponser-r!r"r$Nr.Ú completed_atÚ access_tokenÚ
refresh_tokenÚ
error_message) rrrrrr.rr0r1r2r3rrrrr/@s
r/c@s&eZdZUeed<eed<eed<dS)Ú
RejectRequestr!r"Ú device_idNr+rrrrr4Ls
r4)ÚreturncCsdt d¡S)zGenerate unique session IDZpls_é©ÚsecretsÚ
token_urlsaferrrrÚgenerate_session_idTsr;cCs
t d¡S)z/Generate cryptographically secure request tokené r8rrrrÚgenerate_request_tokenXsr=cCs
t d¡S)zGenerate nonce for challenger7)r9Z token_hexrrrrÚgenerate_nonce\sr>)Úrequestr6cCs4|j d¡}|r"| d¡d ¡S|jr0|jjSdS)zExtract client IP from requestzX-Forwarded-Forú,rÚunknown)ÚheadersÚgetÚsplitÚstripZclientr)r?Z forwardedrrrÚ
get_client_ip`s rFé<)ÚkeyÚlimitÚwindowr6cCsTt d|¡}|s,t d||d¡dSt|ƒ}||kr@dSt d|¡dS)zCheck if rate limit is exceededz
ratelimit:éTF)Ú redis_clientrCÚsetexr'Zincr)rHrIrJZcurrentÚcountrrrÚcheck_rate_limitgsrO)r!r"r6cCsd|d|S)zCreate QR code data stringzquixzoom://auth?sid=z&token=r©r!r"rrrÚcreate_qr_datausrQ)Ú
user_agentÚipr6cCs |d|}t | ¡¡ ¡S)z!Create hash of device fingerprintú:)ÚhashlibZsha256ÚencodeZ hexdigest)rRrSÚdatarrrÚhash_fingerprintysrXz /initiate)Zresponse_model)r?Úbodyc
Ãt|ƒ}|j dd¡}td|tƒs2tdddtƒ}tƒ}tƒ}t  
d¡}t   ¡t
td}||||d |j|jpvd
||t||ƒt   ¡ ¡| ¡d œ } d |}
tj|
| d
t |
t¡t d|t|¡t||t||ƒ| ¡dtdS)zq
Initiate a new passwordless authentication session.
Returns session details including QR code data.
ú
User-AgentrAzip:i­z*Too many requests. Please try again later.©Z status_codeZdetailr<)ZsecondsÚpendingr) r!r"ÚnonceÚ challenger-rrZweb_ipZweb_user_agentZweb_fingerprintÚ
created_atr$ú
passwordless:©Úmappingzpasswordless_token:ÚZ)r!r"r#r$r%)rFrBrCrOÚRATE_LIMIT_PER_IPrr;r=r>r9r:rÚutcnowrÚSESSION_TTL_SECONDSrrrXÚ isoformatrLÚhsetÚexpirerMr rQr&) r?rYZ client_iprRr!r"r]r^r$Ú session_dataÚ redis_keyrrrÚinitiate_passwordlesssP þ

ô
 ý
ûrlz/approve)r?rYÚ
authorizationc
ÃsZ|r| d¡stddd| dd¡}t|ƒdkr>tdddd|j}t |¡}|sdtd d
d| d ¡|jkr€td d
d| d¡dkr¦tdd| d¡dz:t  
|j  dd¡¡}t   ¡|t
ddkrÞtd ddWnttdddYn0t   ¡}tj|d| ¡|jt|ƒ|j dd¡dœdt |d¡td|j| ¡ddS) zy
Approve a passwordless authentication request from the app.
Requires valid app JWT in Authorization header.
úBearer é‘z Missing or invalid authorizationr[Úrz
Invalid tokenr`zSession not found or expiredr"é“úInvalid request tokenr-r\é™zSession already rcz+00:00r)ZminuteszTimestamp too oldizInvalid timestamp formatÚapprovedrZrA)r-r.r*Z device_ipZdevice_user_agentrai,)r-r!r.)Ú
startswithrÚreplaceÚlenr!rLÚhgetallrCr"rZ
fromisoformatr)rerÚ
ValueErrorrhrgr*rFrBrir,)r?rYrmZ app_tokenrkrjr)r.rrrÚapprove_passwordless¿sH      
  þ  û

ýrzz/status)r?r!r"c
ÃsHd|}t |¡}|s$tddd| d¡|kr>tddd| dd ¡}|||| d
¡d œ}|d kr| d
¡|d
<d}t d¡}t d¡} d|}
tj|
||t ¡  ¡t
|ƒ|j  dd ¡dœdt  |
d¡tj|dt ¡  ¡|dœd| 
dt ¡  ¡d|| dœ¡n&|dkr(d|d<n|dkr:d|d<tfi|¤ŽS)zj
Check the status of a passwordless authentication session.
Called by web client via polling.
r`é”úSession not foundr[r"rqrrr-rAr$)r-r!r"r$rtr.Zuser_from_app_tokenr<z web_session:rZ)Úuser_idr!r_rSrRrai€QZ completed)r-r0Úweb_session_tokenrc)r-r0r1r2ÚrejectedzAuthentication rejected by userr3ZexpiredzSession expired)rLrxrrCr9r:rhrrergrFrBriÚupdater/) r?r!r"rkrjr-Zresponser}r~r2Zweb_session_keyrrrÚ check_statussT

   ü