o
    RDiE                     @   s  d dl Z d dlmZ d dlmZ d dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ ddlmZ ddlm Z m!Z!m"Z"m#Z#m$Z$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5m6Z6m7Z7 e- Z8eeddG dd de7eZ9eeddG dd de7eZ:eeddeeddG dd  d e7e5eZ;d!d" Z<d#d$ Z=eeddG d%d& d&e6eZ>dS )'    N)urlparse)logout)AnonymousUser)HttpResponseJsonResponse)reverse)method_decorator)csrf_exempt)FormViewView)jwt)JWException)InvalidJWSObject)
JWTExpired)add_params_to_uri   )login_not_required)ClientIdMissmatchInvalidIDTokenErrorInvalidOIDCClientErrorInvalidOIDCRedirectURIErrorLogoutDenied	OIDCError)ConfirmLogoutForm)OAuth2ResponseRedirect)AbstractGrantget_access_token_modelget_application_modelget_id_token_modelget_refresh_token_model)oauth2_settings)jwk_from_pem   )OAuthLibMixinOIDCLogoutOnlyMixinOIDCOnlyMixindispatch)namec                   @      e Zd ZdZdd ZdS )ConnectDiscoveryInfoViewz
    View used to show oidc provider configuration information per
    `OpenID Provider Metadata <https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata>`_
    c                 O   s  t j}|s4t |}|td}|td}t jp!|td}|td}t jr3|td}	n;tt j}
|
jd |
j	 }d
|td}d
|td}t jp[d
|td}d
|td}t jrod
|td}	tjg}t jr|tjtjg}t j}| }tt||}t j}| }dd	 | D }||||||t jt j|t jd
d	 tjD |d}t jr|	|d< t|}d|d< |S )Nzoauth2_provider:authorizezoauth2_provider:tokenzoauth2_provider:user-infozoauth2_provider:jwks-infoz#oauth2_provider:rp-initiated-logoutz://z{}{}c                 S   s   g | ]}|qS  r*   ).0scoper*   r*   S/var/www/Datamplify/venv/lib/python3.10/site-packages/oauth2_provider/views/oidc.py
<listcomp>V   s    z0ConnectDiscoveryInfoView.get.<locals>.<listcomp>c                 S   s   g | ]\}}|qS r*   r*   )r+   key_r*   r*   r-   r.   e   s    )issuerauthorization_endpointtoken_endpointuserinfo_endpointjwks_uriscopes_supportedresponse_types_supportedsubject_types_supported%id_token_signing_alg_values_supported%token_endpoint_auth_methods_supported code_challenge_methods_supportedclaims_supportedend_session_endpoint*Access-Control-Allow-Origin)r    OIDC_ISS_ENDPOINToidc_issuerbuild_absolute_urir   OIDC_USERINFO_ENDPOINT OIDC_RP_INITIATED_LOGOUT_ENABLEDr   schemenetlocformatApplicationHS256_ALGORITHMOIDC_RSA_PRIVATE_KEYRS256_ALGORITHMOAUTH2_VALIDATOR_CLASSlistsetget_discovery_claimsSCOPES_BACKEND_CLASSget_available_scopesOIDC_RESPONSE_TYPES_SUPPORTEDOIDC_SUBJECT_TYPES_SUPPORTED*OIDC_TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTEDr   CODE_CHALLENGE_METHODSr   )selfrequestargskwargs
issuer_urlr2   r3   r4   r5   r=   
parsed_urlhostsigning_algorithmsvalidator_class	validatoroidc_claimsscopes_classscopesr6   dataresponser*   r*   r-   get2   sf   



zConnectDiscoveryInfoView.getN__name__
__module____qualname____doc__re   r*   r*   r*   r-   r)   +   s    r)   c                   @   r(   )JwksInfoViewz:
    View used to show oidc json web key set document
    c           	      O   s   g }t jr*t jgt jD ]}t|}dd| d}|t|  |	| qt
d|i}d|d< ddt j d	 d
t j d	 dt j  |d< |S )NRS256sig)algusekidkeysr>   r?   zCache-Control: public, zmax-age=z, zstale-while-revalidate=zstale-if-error=zCache-Control)r    rJ   OIDC_RSA_PRIVATE_KEYS_INACTIVEr!   
thumbprintupdatejsonloadsexport_publicappendr   OIDC_JWKS_MAX_AGE_SECONDS)	rV   rW   rX   rY   rq   pemr/   rc   rd   r*   r*   r-   re   u   s*   
zJwksInfoView.getNrf   r*   r*   r*   r-   rk   o   s    rk   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	UserInfoViewzC
    View used to show Claims about the authenticated End-User
    c                 O   
   |  |S N_create_userinfo_responserV   rW   rX   rY   r*   r*   r-   re         
zUserInfoView.getc                 O   r|   r}   r~   r   r*   r*   r-   post   r   zUserInfoView.postc           	      C   s@   |  |\}}}}t|pd|d}| D ]\}}|||< q|S )N )contentstatus)create_userinfo_responser   items)	rV   rW   urlheadersbodyr   rd   kvr*   r*   r-   r      s
   
z&UserInfoView._create_userinfo_responseN)rg   rh   ri   rj   re   r   r   r*   r*   r*   r-   r{      s
    r{   c              
   C   s   t  }t }z|| }W n
 ty   Y dS w |sdS z"tjr$i }nd}tj|| |d}t	|j
}|jj|d d|fW S  tt|jfyM   Y dS w )z
    Loads an IDToken given its string representation for use with RP-Initiated Logout.
    A tuple (IDToken, claims) is returned. Depending on the configuration expired tokens may be loaded.
    If loading failed (None, None) is returned.
    )NNN)r/   r   check_claimsjti)r   )r   r    rL   _get_key_for_tokenr   .OIDC_RP_INITIATED_LOGOUT_ACCEPT_EXPIRED_TOKENSr   JWTru   rv   claimsobjectsre   r   r   DoesNotExist)tokenIDTokenr_   r/   r   	jwt_tokenr   r*   r*   r-   _load_id_token   s&   r   c                 C   s*   t  }d|vs|d || krdS dS )zS
    Validates the claims of an IDToken for use with OIDC RP-Initiated Logout.
    issFT)r    rL   get_oidc_issuer_endpoint)rW   r   r_   r*   r*   r-   _validate_claims   s   r   c                       s   e Zd ZdZeZejejgZ	ej
ejejejejgZdd Z fddZdd Zdd	 Zd
d Zdd Zdd Zdd Zdd ZdddZdd Z  ZS )RPInitiatedLogoutViewz#oauth2_provider/logout_confirm.htmlc              	   C   sN   | j dd | j dd | j dd | j dd | j dd | j dd dS )Nid_token_hintlogout_hint	client_idpost_logout_redirect_uristate
ui_locales)r   r   r   r   r   r   )	oidc_datare   )rV   r*   r*   r-   get_initial   s   z!RPInitiatedLogoutView.get_initialc                    s    i | _ t j|g|R i |S r}   )r   superr&   r   	__class__r*   r-   r&      s   zRPInitiatedLogoutView.dispatchc              
   O   s   |j d}|j d}|j d}|j d}z| j|||d\}}	W n ty; }
 z| |
W  Y d }
~
S d }
~
ww | |	sI| ||||	S ||||d| _| | 	 }||d< |rb||d< | 
| jd	i |S )
Nr   r   r   r   r   r   r   )r   r   r   r   formapplicationr*   )GETre   validate_logout_requestr   error_responsemust_prompt	do_logoutr   get_formget_form_classrender_to_responseget_context_data)rV   rW   rX   rY   r   r   r   r   r   
token_usererrorr   r*   r*   r-   re      s4   
zRPInitiatedLogoutView.getc           	   
   C   s   |j d}|j d}|j d}|j d}z!| j|||d\}}| |r.|j dr7| ||||W S t  tyP } z| |W  Y d }~S d }~ww )Nr   r   r   r   r   allow)cleaned_datare   r   r   r   r   r   r   )	rV   r   r   r   r   r   r   r   r   r*   r*   r-   
form_valid  s"   
z RPInitiatedLogoutView.form_validc                 C   s|   |sdS |s	t  t|d }|stdtjr%|dkr%|jdkr%td|| vr3td| d||s<td	dS )
zb
        Validate the OIDC RP-Initiated Logout Request post_logout_redirect_uri parameter
        Nr   z*A Scheme is required for the redirect URI.httpconfidentialz/http is only allowed with confidential clients.zRedirect to scheme "z" is not permitted.z7This client does not have this redirect uri registered.)r   r   r   r    -OIDC_RP_INITIATED_LOGOUT_STRICT_REDIRECT_URISclient_typeget_allowed_schemes post_logout_redirect_uri_allowed)rV   r   r   rE   r*   r*   r-   !validate_post_logout_redirect_uri.  s   
z7RPInitiatedLogoutView.validate_post_logout_redirect_uric                 C   sD   |sdS t |\}}|rt| j|st |r |jj|kr t |S )zG
        Validate the an OIDC RP-Initiated Logout Request user
        N)r   r   rW   r   r   r   r   )rV   r   r   id_tokenr   r*   r*   r-   validate_logout_request_userD  s   z2RPInitiatedLogoutView.validate_logout_request_userc                 C   s"   |r
t  jj|dS |r|jS d S )N)r   )r   r   re   r   )rV   r   r   r*   r*   r-   get_request_applicationY  s
   z-RPInitiatedLogoutView.get_request_applicationc                 C   s8   |  ||}| ||}| || ||r|jfS dfS )a  
        Validate an OIDC RP-Initiated Logout Request.
        `(application, token_user)` is returned.

        If it is set, `application` is the Application that is requesting the logout.
        `token_user` is the id_token user, which will used to revoke the tokens if found.

        The `id_token_hint` will be validated if given. If both `client_id` and `id_token_hint` are given they
        will be validated against each other.
        N)r   r   r   user)rV   r   r   r   r   r   r*   r*   r-   r   _  s   z-RPInitiatedLogoutView.validate_logout_requestc                 C   s   t jp|du p|| jjkS )aR  Indicate whether the logout has to be confirmed by the user. This happens if the
        specifications force a confirmation, or it is enabled by `OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT`.

        A logout without user interaction (i.e. no prompt) is only allowed
        if an ID Token is provided that matches the current user.
        N)r    &OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPTrW   r   )rV   r   r*   r*   r-   r   q  s
   
z!RPInitiatedLogoutView.must_promptNc                 C   s   |p| j j}tjrBt|tsBt }t }|jj	|| j
| jd}t|jj	|d}	|D ]}
|
jr4|
j  |
  q*|	D ]}|  q;t| j  |r_|rXtt|d|fg| S t|| S t| j dtjS )N)r   application__client_type__in)application__authorization_grant_type__in)access_token__inr   /)rW   r   r    &OIDC_RP_INITIATED_LOGOUT_DELETE_TOKENS
isinstancer   r   r   r   filtertoken_deletion_client_typestoken_deletion_grant_typesrM   r   revoker   r   r   r   rB   ALLOWED_REDIRECT_URI_SCHEMES)rV   r   r   r   r   r   AccessTokenRefreshTokenaccess_tokens_to_deleterefresh_tokens_to_deleter   refresh_tokenr*   r*   r-   r   ~  s<   




zRPInitiatedLogoutView.do_logoutc                 C   s   d|i}| j ||jdS )Nr   )r   )r   status_code)rV   r   r   r*   r*   r-   r     s   z$RPInitiatedLogoutView.error_response)NNNN)rg   rh   ri   template_namer   
form_classrH   CLIENT_PUBLICCLIENT_CONFIDENTIALr   GRANT_AUTHORIZATION_CODEGRANT_IMPLICITGRANT_PASSWORDGRANT_CLIENT_CREDENTIALSGRANT_OPENID_HYBRIDr   r   r&   re   r   r   r   r   r   r   r   r   __classcell__r*   r*   r   r-   r      s.    

)r   )?ru   urllib.parser   django.contrib.authr   django.contrib.auth.modelsr   django.httpr   r   django.urlsr   django.utils.decoratorsr   django.views.decorators.csrfr	   django.views.genericr
   r   jwcryptor   jwcrypto.commonr   jwcrypto.jwsr   jwcrypto.jwtr   oauthlib.commonr   compatr   
exceptionsr   r   r   r   r   r   formsr   r   r   modelsr   r   r   r   r   settingsr    utilsr!   mixinsr#   r$   r%   rH   r)   rk   r{   r   r   r   r*   r*   r*   r-   <module>   sD     

C

+
