§
    Ÿv»j"(  ã                  óV  — d Z ddlmZ ddlZddlZddlZddlZddlm	Z	m
Z
mZ ddlmZmZ ddlmZmZmZmZmZ ddlmZ  edd¬	¦  «         G d
„ d¦  «        ¦   «         Z G d„ dej        ¦  «        Z G d„ de¦  «        Z G d„ de¦  «        Z G d„ de¦  «        Z G d„ d¦  «        ZdS )zÕ
Pluggable OAuth Provider Framework for FreeExile.
Pre-architected adapters for Google, Apple (Sign in with Apple), and Facebook.
Supports Staging/Mock mode for automated test suites and production API endpoints.
é    )ÚannotationsN)ÚAnyÚDictÚOptional)Ú	dataclassÚfield)ÚAccountÚAccountStatusÚOAuthIdentityÚOAuthLoginResultÚOAuthProviderType)ÚTokenServiceT)ÚslotsÚfrozenc                  óv   — e Zd ZU dZded<   ded<   ded<   ded<   ded	<   d
Zded<    ee¬¦  «        Zded<   d
S )ÚOAuthUserProfilezKStandardized user profile extracted from external OAuth identity providers.r   ÚproviderÚstrÚprovider_user_idÚemailÚboolÚemail_verifiedÚdisplay_nameNzOptional[str]Ú
avatar_url)Údefault_factoryzDict[str, Any]Ú
raw_claims)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r   r   Údictr   © ó    ú*C:\Projects\FreeExile\server\auth\oauth.pyr   r      s€   € € € € € € àUÐUØÐÐÑØÐÐÑØ€J€J�JØÐÐÑØÐÐÑØ $€JÐ$Ð$Ð$Ñ$Ø!& °tÐ!<Ñ!<Ô!<€JÐ<Ð<Ð<Ñ<Ð<Ð<r$   r   c                  óˆ   — e Zd ZdZeej        dd„¦   «         ¦   «         Zej        dd„¦   «         Zej        dd„¦   «         Z	dS )ÚOAuthProviderzOAbstract adapter interface for third-party OAuth 2.0 / OIDC identity providers.Úreturnr   c                ó   — d S ©Nr#   ©Úselfs    r%   Úprovider_typezOAuthProvider.provider_type(   ó	   € ð 	ˆr$   Ústater   Úredirect_uric                ó   — dS )zBConstruct the provider's OAuth consent authorization redirect URL.Nr#   )r,   r/   r0   s      r%   Úget_authorization_urlz#OAuthProvider.get_authorization_url-   r.   r$   Útoken_or_coder   c                ó   — dS )zDVerify authorization code or ID token and return normalized profile.Nr#   )r,   r3   r0   s      r%   Úverify_token_or_codez"OAuthProvider.verify_token_or_code2   r.   r$   N©r(   r   ©r/   r   r0   r   r(   r   ©r3   r   r0   r   r(   r   )
r   r   r   r    ÚpropertyÚabcÚabstractmethodr-   r2   r5   r#   r$   r%   r'   r'   %   sŽ   € € € € € ØYÐYàØÔðð ð ñ Ôñ „Xðð 	Ôðð ð ñ Ôðð 	Ôðð ð ñ Ôðð ð r$   r'   c                  óB   — e Zd ZdZdd„Zedd	„¦   «         Zdd„Zdd„ZdS )ÚGoogleOAuthProviderz+Google OpenID Connect / OAuth 2.0 Provider.Ú	client_idr   Úclient_secretr(   ÚNonec                ó"   — || _         || _        d S r*   )r>   r?   )r,   r>   r?   s      r%   Ú__init__zGoogleOAuthProvider.__init__;   s   € Ø"ˆŒØ*ˆÔÐÐr$   r   c                ó   — t           j        S r*   )r   ÚGOOGLEr+   s    r%   r-   z!GoogleOAuthProvider.provider_type?   s   € å Ô'Ð'r$   r/   r0   c                ól   — d}| j         |dd|dddœ}|› dt          j                             |¦  «        › �S )Nz,https://accounts.google.com/o/oauth2/v2/authÚcodezopenid email profileÚofflineÚconsent)r>   r0   Úresponse_typeÚscoper/   Úaccess_typeÚpromptú?©r>   ÚurllibÚparseÚ	urlencode©r,   r/   r0   Úbase_urlÚparamss        r%   r2   z)GoogleOAuthProvider.get_authorization_urlC   sP   € ØAˆàœØ(Ø#Ø+ØØ$Øð
ð 
ˆð Ð=Ð=�Vœ\×3Ò3°FÑ;Ô;Ð=Ð=Ð=r$   r3   r   c           
     óâ   — |                      d¦  «        s| j        dk    rA|                     dd¦  «        }t          t          j        d|› �|› d�dd|› �d	|d
œ¬¦  «        S t          d¦  «        ‚)NÚmock_Úsecret_gÚmock_google_token_Ú Úgoogle_uid_z
@gmail.comTÚGoogleUser_zaccounts.google.com©ÚissÚsub©r   r   r   r   r   r   zLLive Google OAuth requires deployment credentials in production environment.)Ú
startswithr?   Úreplacer   r   rD   ÚNotImplementedError©r,   r3   r0   Úuser_suffixs       r%   r5   z(GoogleOAuthProvider.verify_token_or_codeP   s™   € à×#Ò# GÑ,Ô,ð 		°Ô0BÀjÒ0PÐ0PØ'×/Ò/Ð0DÀbÑIÔIˆKÝ#Ý*Ô1Ø!<¨{Ð!<Ð!<Ø$Ð0Ð0Ð0Ø#Ø8¨;Ð8Ð8Ø#8ÀÐMÐMðñ ô ð õ "Ð"pÑqÔqÐqr$   N)r>   r   r?   r   r(   r@   r6   r7   r8   ©	r   r   r   r    rB   r9   r-   r2   r5   r#   r$   r%   r=   r=   8   s|   € € € € € Ø5Ð5ð+ð +ð +ð +ð ð(ð (ð (ñ „Xð(ð>ð >ð >ð >ðrð rð rð rð rð rr$   r=   c                  óD   — e Zd ZdZddd
„Zedd„¦   «         Zdd„Zdd„ZdS )ÚAppleOAuthProviderz#Sign in with Apple (SIWA) Provider.rY   Úteam_idr   r>   Úkey_idÚprivate_keyr(   r@   c                ó>   — || _         || _        || _        || _        d S r*   )rh   r>   ri   rj   )r,   rh   r>   ri   rj   s        r%   rB   zAppleOAuthProvider.__init__e   s%   € ØˆŒØ"ˆŒØˆŒØ&ˆÔÐÐr$   r   c                ó   — t           j        S r*   )r   ÚAPPLEr+   s    r%   r-   z AppleOAuthProvider.provider_typek   s   € å Ô&Ð&r$   r/   r0   c                ój   — d}| j         |ddd|dœ}|› dt          j                             |¦  «        › �S )Nz(https://appleid.apple.com/auth/authorizezcode id_tokenÚ	form_postz
name email)r>   r0   rI   Úresponse_moderJ   r/   rM   rN   rR   s        r%   r2   z(AppleOAuthProvider.get_authorization_urlo   sM   € Ø=ˆàœØ(Ø,Ø(Ø!Øð
ð 
ˆð Ð=Ð=�Vœ\×3Ò3°FÑ;Ô;Ð=Ð=Ð=r$   r3   r   c           
     óâ   — |                      d¦  «        s| j        dk    rA|                     dd¦  «        }t          t          j        d|› �|› d�dd|› �d	|d
œ¬¦  «        S t          d¦  «        ‚)NrV   Ú	KEY_12345Úmock_apple_token_rY   Ú
apple_uid_z@privaterelay.appleid.comTÚAppleWarrior_zhttps://appleid.apple.comr\   r_   zPLive Apple SIWA requires Apple Developer private keys in production environment.)r`   ri   ra   r   r   rm   rb   rc   s       r%   r5   z'AppleOAuthProvider.verify_token_or_code{   s˜   € Ø×#Ò# GÑ,Ô,ð 		°´¸{Ò0JÐ0JØ'×/Ò/Ð0CÀRÑHÔHˆKÝ#Ý*Ô0Ø!;¨kÐ!;Ð!;Ø$Ð?Ð?Ð?Ø#Ø:¨[Ð:Ð:Ø#>À{ÐSÐSðñ ô ð õ "Ð"tÑuÔuÐur$   N)rY   )
rh   r   r>   r   ri   r   rj   r   r(   r@   r6   r7   r8   re   r#   r$   r%   rg   rg   b   s�   € € € € € Ø-Ð-ð'ð 'ð 'ð 'ð 'ð ð'ð 'ð 'ñ „Xð'ð
>ð 
>ð 
>ð 
>ðvð vð vð vð vð vr$   rg   c                  óB   — e Zd ZdZdd„Zedd	„¦   «         Zdd„Zdd„ZdS )ÚFacebookOAuthProviderz)Facebook Graph API / Meta Login Provider.Úapp_idr   Ú
app_secretr(   r@   c                ó"   — || _         || _        d S r*   )rx   ry   )r,   rx   ry   s      r%   rB   zFacebookOAuthProvider.__init__�   s   € ØˆŒØ$ˆŒˆˆr$   r   c                ó   — t           j        S r*   )r   ÚFACEBOOKr+   s    r%   r-   z#FacebookOAuthProvider.provider_type‘   s   € å Ô)Ð)r$   r/   r0   c                óh   — d}| j         ||dddœ}|› dt          j                             |¦  «        › �S )Nz+https://www.facebook.com/v18.0/dialog/oauthzemail,public_profilerF   )r>   r0   r/   rJ   rI   rM   )rx   rO   rP   rQ   rR   s        r%   r2   z+FacebookOAuthProvider.get_authorization_url•   sJ   € Ø@ˆàœØ(ØØ+Ø#ð
ð 
ˆð Ð=Ð=�Vœ\×3Ò3°FÑ;Ô;Ð=Ð=Ð=r$   r3   r   c           	     óà   — |                      d¦  «        s| j        dk    r@|                     dd¦  «        }t          t          j        d|› �|› d�dd|› �d	|i¬
¦  «        S t          d¦  «        ‚)NrV   Úfb_secret_456Úmock_fb_token_rY   Úfb_uid_z@facebook.comTÚFacebookPlayer_r^   r_   zNLive Facebook Graph Login requires App Secret Proof in production environment.)r`   ry   ra   r   r   r|   rb   rc   s       r%   r5   z*FacebookOAuthProvider.verify_token_or_code    s•   € Ø×#Ò# GÑ,Ô,ð 		°´À?Ò0RÐ0RØ'×/Ò/Ð0@À"ÑEÔEˆKÝ#Ý*Ô3Ø!8¨;Ð!8Ð!8Ø$Ð3Ð3Ð3Ø#Ø<¨{Ð<Ð<Ø! ;Ð/ðñ ô ð õ "Ð"rÑsÔsÐsr$   N)rx   r   ry   r   r(   r@   r6   r7   r8   re   r#   r$   r%   rw   rw   Š   s|   € € € € € Ø3Ð3ð%ð %ð %ð %ð ð*ð *ð *ñ „Xð*ð	>ð 	>ð 	>ð 	>ðtð tð tð tð tð tr$   rw   c                  ó2   — e Zd ZdZdd„Zdd„Zdd„Zdd„ZdS )ÚOAuthServicezNManages provider adapters, user authentication, and automatic account binding.Ú
repositoryr   Útoken_servicer   r(   r@   c                ó0   — || _         || _        i | _        d S r*   )r…   r†   Ú
_providers)r,   r…   r†   s      r%   rB   zOAuthService.__init__²   s   € Ø$ˆŒØ*ˆÔØBDˆŒˆˆr$   r   r'   c                ó$   — || j         |j        <   d S r*   )rˆ   r-   )r,   r   s     r%   Úregister_providerzOAuthService.register_provider·   s   € Ø2:ˆŒ˜Ô.Ñ/Ð/Ð/r$   r-   r   úOptional[OAuthProvider]c                ó6   — | j                              |¦  «        S r*   )rˆ   Úget)r,   r-   s     r%   Úget_providerzOAuthService.get_providerº   s   € ØŒ×"Ò" =Ñ1Ô1Ð1r$   Úauth_code_or_tokenr   r0   Ú	client_ipr   c           	     óL  — |                       |¦  «        }|st          dd|j        › d�¬¦  «        S 	 |                     ||¦  «        }n8# t          $ r+}t          ddt          |¦  «        › �¬¦  «        cY d }~S d }~ww xY w| j                             ||j        ¦  «        }d}	|sÞ| j         	                    |j
        ¦  «        }|rRt          ||j        |j
        ¬¦  «        |j        |<   |j        t          j        k    r|j        rt          j        |_        nkd}	| j                             |j
        d|j        |j        rt          j        nt          j        ¬	¦  «        }t          ||j        |j
        ¬¦  «        |j        |<   |j        t          j        k    rt          dd
¬¦  «        S |j        t          j        k    rt          dd¬¦  «        S | j                             |j        |j        |j
        ¬¦  «        }
t          dd|
j        |
j        |j        |j        |	¬¦  «        S )NFzOAuth provider z is not configured or disabled)ÚsuccessÚmessagezOAuth verification failed: )r   r   r   TrY   )r   Úpassword_hashÚusernameÚstatuszAccount is bannedzAccount is suspended)Ú
account_idÚrolesr   zOAuth login successful)r’   r“   Úaccess_tokenÚrefresh_tokenr—   r•   Úis_new_account)rŽ   r   Únamer5   Ú	Exceptionr   r…   Úget_by_oauthr   Úget_by_emailr   r   Úoauth_identitiesr–   r
   ÚPENDING_ACTIVATIONr   ÚACTIVEÚcreate_accountr   ÚBANNEDÚ	SUSPENDEDr†   Úgenerate_token_pairr—   r˜   r™   rš   r•   )r,   r-   r�   r0   r�   r   ÚprofileÚeÚaccountr›   Ú
token_pairs              r%   Úauthenticate_oauthzOAuthService.authenticate_oauth½   s†  € ð ×$Ò$ ]Ñ3Ô3ˆØð 	Ý#ØØ\¨-Ô*<Ð\Ð\Ð\ðñ ô ð ð
	Ø×3Ò3Ð4FÈÑUÔUˆGˆGøÝð 	ð 	ð 	Ý#ØØ>µc¸!±f´fÐ>Ð>ðñ ô ð ð ð ð ð ð øøøøð	øøøð ”/×.Ò.¨}¸gÔ>VÑWÔWˆØˆàð 	à”o×2Ò2°7´=ÑAÔAˆGØð å:GØ*Ø%,Ô%=Ø!œ-ð;ñ ;ô ;�Ô(¨Ñ7ð ”>¥]Ô%EÒEÐEÈ'ÔJ`ÐEÝ%2Ô%9�G”Nøð "&�Øœ/×8Ò8Ø!œ-Ø"$Ø$Ô1Ø3:Ô3IÐo�=Ô/Ð/Í}ÔOoð	 9ñ ô �õ ;HØ*Ø%,Ô%=Ø!œ-ð;ñ ;ô ;�Ô(¨Ñ7ð Œ>�]Ô1Ò1Ð1Ý#¨EÐ;NÐOÑOÔOÐOØŒ>�]Ô4Ò4Ð4Ý#¨EÐ;QÐRÑRÔRÐRàÔ'×;Ò;ØÔ)Ø”-Ø”-ð <ñ 
ô 
ˆ
õ  ØØ,Ø#Ô0Ø$Ô2ØÔ)ØÔ%Ø)ð
ñ 
ô 
ð 	
s   ³A
 Á

A?Á A:Á4A?Á:A?N)r…   r   r†   r   r(   r@   )r   r'   r(   r@   )r-   r   r(   r‹   )
r-   r   r�   r   r0   r   r�   r   r(   r   )r   r   r   r    rB   rŠ   rŽ   r«   r#   r$   r%   r„   r„   ¯   st   € € € € € ØXÐXðEð Eð Eð Eð
;ð ;ð ;ð ;ð2ð 2ð 2ð 2ðI
ð I
ð I
ð I
ð I
ð I
r$   r„   )r    Ú
__future__r   r:   ÚhashlibÚhmacÚurllib.parserO   Útypingr   r   r   Údataclassesr   r   Úserver.auth.modelsr	   r
   r   r   r   Úserver.auth.cryptor   r   ÚABCr'   r=   rg   rw   r„   r#   r$   r%   ú<module>rµ      s  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø 
€
€
€
Ø €€€Ø €€€Ø Ð Ð Ð Ø &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ,Ð +Ð +Ð +Ð +Ð +ð €�˜dÐ#Ñ#Ô#ð=ð =ð =ð =ð =ñ =ô =ñ $Ô#ð=ðð ð ð ð �C”Gñ ô ð ð&'rð 'rð 'rð 'rð 'r˜-ñ 'rô 'rð 'rðT%vð %vð %vð %vð %v˜ñ %vô %vð %vðP"tð "tð "tð "tð "t˜Mñ "tô "tð "tðJW
ð W
ð W
ð W
ð W
ñ W
ô W
ð W
ð W
ð W
r$   