U
    whT                     @   s6   d dl mZ d dlT ddlmZ G dd dejZdS )    )fields)*   )cmf_auth_openid_pluginc                       s   e Zd Zejjd ZdZdZedd Z	dd Z
 fddZd	d
 Z fddZedddZedd ZeeeedddZdd ZedddZedddZedddZdd  Zed!d" Zed#d$ Zd,eed%d&d'Zd-d(d)Zd*d+ Z  ZS ).CmfAuthOpenIdPlugin)loggerconfigNc                 C   sB   | j s<ddlm} tj}tjr$tj}|j|  dd|d| _ | j S )Nr   )
log_config
   i@KL )ZbackupCountZmaxByteslevel)	_CmfAuthOpenIdPlugin__loggerZcmf.modules.logsr	   ZloggingINFOr   DEBUGZ
get_loggerZget_files_dir)selfr	   r    r   2./cmf/modules/sso/models/cmf_auth_openid_plugin.pyr      s    zCmfAuthOpenIdPlugin.loggerc                 C   s   t dd d| _d S )NT)Zfull_urlzsso/openid-connect)Zapp_base_hrefcallback_urlr   r   r   r   _check_callback_url   s    z'CmfAuthOpenIdPlugin._check_callback_urlc                    s   t   ddddg S )Nr   zplugin.ext_urlservicedesk_supportcreate_new_user)supersave_preload_fieldsr   	__class__r   r   r      s     z'CmfAuthOpenIdPlugin.save_preload_fieldsc                 C   sJ   | j js| jjsd S | jrF| j rFtd| jj d| j j dd d| _d S )Nu   Опция u    несовместима с F)abort)r   
is_changedr   Z	cmf_alertZcaptionr   r   r   r   _check_servicedesk_support    s    z.CmfAuthOpenIdPlugin._check_servicedesk_supportc                    s4   |    | jjrtjdd| _|   t j||S )Nr   )type)r   pluginZis_nullmodelsZ	CmfPluginr   r   save)r   argskwargsr   r   r   r!   )   s
    zCmfAuthOpenIdPlugin.savecodec              	   C   s  dd l }| ddg | jdkrP| jj|dg| jjd}| j|d |d< nF| jd	kr| jj	|| j
jd
| jjdd}d|krtd| | |d |d< nt|d}| jjj|d< | jj|d< t  | jj |d< W 5 Q R X d|d< ddi}|j| jd ||| jjjd}|  | }d|krDtd| dd|d  i}|j| jd || jjjd}|  t |d< |jr| |d< | jd|  |S )Nr   app_typeplugin.*keycloakZauthorization_code)r%   
grant_typeredirect_uriaccess_tokenuserinfo_dataadfs userinfo)scopesr*   Zclaims_challengeerroru>   Сервер авторизации вернул ошибку r$   	client_idr*   client_secretr)   content-type!application/x-www-form-urlencodedtoken_endpointdataheadersverifyZAuthorizationzBearer Zuserinfo_endpoint)r9   r:   u   Получили токен )requestsload_fieldsr&   client_keycloaktokenr   valuer/   client_adfsZ#acquire_token_by_authorization_codescopesplit	Exceptionunpack_tokendictr   ext_client_idcmfutildisable_acl
ext_secretdecryptpostr   
verify_sslraise_for_statusjsongetcontentr   info)r   r%   r;   r>   paramsr9   resZuserinfo_responser   r   r   	get_token1   sJ    





zCmfAuthOpenIdPlugin.get_tokenc                 C   sH   dd l }| jr| jS |jtj| jjjd| jj	jd
 | _| jS d S )Nr   z .well-known/openid-configurationr:   )r;   _CmfAuthOpenIdPlugin__configrO   ospathjoinr   ext_urlr?   rL   rN   )r   r;   r   r   r   r   X   s    zCmfAuthOpenIdPlugin.config)r>   jwksreturnc                    s(  dd l }dd l}dd l}ddlm} ddlm} ddlm} ddl	m
} ddlm}	 || }
|
d |
d}td	|
  t fd
d|D d }|d kr|r|D ]^}d|kr||d d }|| }||dd}||kr|}td  qq|d kr,td  d| td|  d|krz||d d }||| }| }td ndd|krd|krt||d d}t||d d}|	||| }td ntd|j|jj |j!j"d}td|   |j| ||ddgddidS ) Nr   )base64url_decode)x509)default_backend)serialization)rsakidx5tu!   Заголовок токена: c                 3   s    | ]}| d  kr|V  qdS )rb   N)rO   ).0keyrb   r   r   	<genexpr>s   s      z4CmfAuthOpenIdPlugin._decode_token.<locals>.<genexpr>Zx5czutf-8=u,   Найден JWK по отпечатку x5tu$   JWK не найден ни по kid=u   , ни по x5t=u   Используемый JWK: u5   Публичный ключ извлечён из x5cnebigu4   Публичный ключ создан из n и eu,   JWK не содержит ни x5c, ни n/e)encodingformatu   PEM-ключ:
ZalgZRS256
verify_audF)re   
algorithmsoptions)#jwtbase64hashlibZ	jwt.utilsr]   Zcryptographyr^   Zcryptography.hazmat.backendsr_   Zcryptography.hazmat.primitivesr`   Z)cryptography.hazmat.primitives.asymmetricra   Zget_unverified_headerrO   gdebugnextZ	b64decodeZsha1ZdigestZurlsafe_b64encodedecoderstrip
ValueErrorZload_der_x509_certificate
public_keyint
from_bytesZRSAPublicNumbersZpublic_bytesZEncodingZPEMZPublicFormatZSubjectPublicKeyInfo)r>   r[   rq   rr   rs   r]   r^   r_   r`   ra   headerrc   Zjwkre   ZderZ
thumbprintZ	thumb_b64Zcert_derZcertrz   ri   rj   Zpem_keyr   rf   r   _decode_tokenb   s`    





z!CmfAuthOpenIdPlugin._decode_tokenc                 C   s6   dd l }| jdkr(|jj|| jjjS | |S d S )Nr   r-   )	msalr&   Z	oauth2cliZoidcZdecode_id_tokenr   rF   r?   rD   )r   r>   r   r   r   r   unpack_id_token   s    
z#CmfAuthOpenIdPlugin.unpack_id_token)r>   c                 C   s|   dd l }dd l}| jdkr*| j d }nF| jdkrN|j|ddgdddd	S |j| jd
 | jj	j
d d }| ||S )Nr   r(   keysr-    ZRSA256F)Zverify_signaturern   )ro   rp   Zjwks_urirU   )r;   rq   r&   r=   Zcertsrw   rO   r   r   rL   r?   rN   r~   )r   r>   r;   rq   Zjwkeysr   r   r   rD      s    

"z CmfAuthOpenIdPlugin.unpack_token)rq   c           	      C   s  |d  | jj}|s,| jd|  d S |D ]}d| d}| jd|  ddg}tjj ddd| dg|d	}|stjj d
d|g|d	}|s| jsq0| jd|  tj||| d}|j	s||_	||j	kr|j	 | |_	||j
kr0| jd| d|  |j
| |  q0tjjdd|jggdd| gg|d	D ]f}d}|D ]$}d| d|j	krNd} qtqN|sB| jd| d|  |j
| |  qBd S )Nr,   uM   Группы по ключу group не обнаружены в токене z::u-   Обрабатываем группу ext_id=
rg_membersext_idZLIKE%filterr   name==u0   Не нашли группу, создадим: )r   r   auth_pluginu(   Добавим пользователя u    в группу INr   FTu&   Уберем пользователя u    из группы )rO   Zgroups_claimr?   r   ZwarningrQ   r    CmfPersonGroupZcreate_new_groupsr   r   appendr!   listidremove)	r   personrq   groupsZgroup_idr   _fieldsgroupmemberr   r   r   _process_groups   sH    




z#CmfAuthOpenIdPlugin._process_groupsc              
   C   s  dd l }z| |d }W n*   | jd|d  d t }Y nX | |d }| jd| d| d|  |d	 | jj	}|s|| jj	}|s|| jj	}|st
d
| j d|d	  d|kr|}n| d| j }dddddg}tjj||d}|stjj||d}|s.tjj||d}|d	 d}	|d	 d}
|d	 d}|d	 d}|d	 d}|s|	rtjjdd|	g|d}|s | jrtjdtj g|||	|
||d}|  |r ||}|jdkr ||j ntd||_| jrN|
|_|	|_||_||_|rN||}|jdkrN||j |jr^|  | j||d tj|| d }|j   |j!   |j"|_#|	|_$|j%|_&|d!|_'|d"|_(|d#}|s|d#}||_)|d$ |_*t+j,rt+j,d |_-|  |S )%Nr   r+   u8   Неудалось дешифровать access_token ''id_tokenu2   Создаем сессию по access_token JWT=z, access_token=z, id_token=r,   uY   Логин не может быть пустым, проверьте настройки, u    нет в @	ext_loginr   
first_name	last_nameemail)loginr   )r   r   )r   r   Z
given_nameZfamily_nameZpicturer   r   r   T)Z
user_localZrg_member_ofr   r   r   r   r   r      u1   Пользователя нет в системе)r   rq   )rq   r   refresh_tokenrefresh_expires_inrA   
expires_in).r;   rD   r   	exceptionrE   r   rQ   rO   Zusername_claimr?   AssertionErrordomainr    Z	CmfPersonr   r   Z
user_groupr!   Zstatus_codeZ
set_avatarrP   rC   r   Zupdate_userr   r   r   r   r   r   Z
CmfSessionZ	auth_dateset_nowreauth_dater   
user_loginZ
user_emailr   Zuser_idr   lifetimerA   access_token_expires_inrequestZaccess_routeZ	client_ip)r   rq   r;   Zpayloadr   r   Z	cmf_loginr   r   r   r   r   r   Zpicture_urlrS   sessionrA   r   r   r   get_session   s     
    






zCmfAuthOpenIdPlugin.get_sessionc                 C   s  dd l }t  d zz| jd|jj  | dddg | j	rNt
| jdkrj| j|jj}nXt|jjd| jjj| jj d}d	d
i}|j| jd ||| jjjd}|  | }|r(| jd|j d|  |j  |dr|d|_|dr|d|_|d |_nd|_W n t
k
rh   | jd| j d|j  d|_Y nV |j j!k
r } z2| jd|j d|jj d|j"j#  d|_W 5 d }~X Y nX W 5 |  |  W  5 Q R  S X  W 5 Q R X d S )Nr   u    Обновляем сессию disabledr&   r'   r(   r   )r   r)   r2   r3   r4   r5   r6   r7   u    Для пользователя u(    получили новый токен r   r   Tu8   SSO интеграция была выключена id=u;   , отключаем сессию пользователя u5   Ошибка обновления сессии login=u    по токену z res=)$r;   rG   rH   r!   r   rQ   r   r?   r<   r   r   r&   r=   r   rE   r   rF   rI   rJ   rK   r   rL   rM   rN   r   r   r   rO   r   r   Zexpiredr   
exceptionsZ	HTTPErrorZresponsetext)r   r   r;   rq   rR   r9   rS   errr   r   r   r   2  sH    






(z!CmfAuthOpenIdPlugin.refresh_tokenc              
   C   sj   ddl m} | dg t @ || jjj| jjj| jj	j| jj
 | jjjdW  5 Q R  S Q R X d S )Nr   )KeycloakOpenIDr'   )Z
server_urlr2   Z
realm_nameZclient_secret_keyr:   )r(   r   r<   rG   rH   r   rZ   r?   rF   Zext_realm_namerI   rJ   rL   )r   r   r   r   r   r=   Y  s    


z#CmfAuthOpenIdPlugin.client_keycloakc              
   C   sf   |  dg ddlm} t < || jjj| jjj| jj	
 | jjjdgdW  5 Q R  S Q R X d S )Nr'   r   )ConfidentialClientApplicationZoffline_access)r2   Z	authorityZclient_credentialr:   Zexclude_scopes)r<   r   r   rG   rH   r   rF   r?   rZ   rI   rJ   rL   )r   r   r   r   r   r@   c  s    

zCmfAuthOpenIdPlugin.client_adfs)next_urlr\   c                 C   s  ddl m}m} | ddg |s,|tj}t|| jj	d}z| j
dkrh| jj| jj	| jj	|d}n| j
dkr| jj| jj	d	| jj	|d
}nXt }| jjj	|d< | jj	|d< d|d< | jj	|d< ||d< ||}| jd  d| }W n   | jd d }Y nX |S )Nr   )	urlencodequoter   r'   )r   r   r(   )r*   rA   stater-   r.   )r0   r*   r   r2   r*   r%   Zresponse_typerA   r   Zauthorization_endpoint?u-   Неудалось получить login_url)urllib.parser   r   r<   r   urlrN   dumpsr   r?   r&   r=   Zauth_urlr   rA   r@   Zget_authorization_request_urlrB   rE   r   rF   r   r   r   )r   r   r   r   Zstate_params	login_urlrR   qsr   r   r   get_redirect_urlp  s:    

 

z$CmfAuthOpenIdPlugin.get_redirect_urlc                 C   s   dd l }| ddg tjdrFtjdd }|dd  }ntj}|sft	dtj  d S |
|}| dg d}| jjD ]}||krd	} qq|st	| d
| jj  d S | j|d}|r| jd|  t|S d S )Nr   r   r'   zX-Forwarded-For,uV   Не удалось определить ext_ip по X-Forwarded-For: request.headers=zplugin.ext_networksFTuE    не входит в список разрешенных сетей )r   u\   Редиректим пользователя на страницу авторизации: )	ipaddressr<   r   r9   ZgetlistrB   stripZremote_addrrt   ru   IPv4Addressr   Zext_networksr   r   rQ   redirect)r   r   r   ipsZext_ipZacceptednetworkr   r   r   r   login_redirect  s.    
z"CmfAuthOpenIdPlugin.login_redirectc                 C   s   ddl m} | jdkr&| j|jjS | jdr|t	
i d}d|jkrZ|jd |d< | jd  d|| }td	tjj d
|  t|S d S )Nr   )r   r(   Zend_session_endpoint)Zpost_logout_redirect_urir   r   Zid_token_hintr   zlogin=z logout redirect=)r   r   r&   r=   logoutr   r?   r   rO   rN   r   rq   rt   ru   Zcurrent_userr   r   )r   r   Z
logout_urlr   rR   Zredirect_urlr   r   r   r     s    

zCmfAuthOpenIdPlugin.logout)N)N) __name__
__module____qualname__r   r   Zui_meta_skipr   rV   propertyr   r   r   r   r!   strrT   r   staticmethodr   rE   r~   r   rD   r   r   r   r=   r@   r   r   r   __classcell__r   r   r   r   r      s4   
		'
	C
(S'
	

r   N)Zcmfr   Zcmf.includer   r   r   r   r   r   <module>   s   