3
=^                 @   s   d Z ddlmZ ddlZddl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
 ZG dd de	ZG dd deZG dd deZG dd deZG dd deZG dd deZdS )z+
Provides various authentication policies.
    )unicode_literalsN)authenticateget_user_model)CsrfViewMiddleware)	text_type)ugettext_lazy)HTTP_HEADER_ENCODING
exceptionsc             C   s&   | j jdd}t|tr"|jt}|S )z
    Return request's 'Authorization:' header, as a bytestring.

    Hide some test client ickyness where the header can be unicode.
    ZHTTP_AUTHORIZATION    )METAget
isinstancer   encoder   )requestauth r   L/tmp/pip-build-8app2_gc/djangorestframework/rest_framework/authentication.pyget_authorization_header   s    

r   c               @   s   e Zd Zdd ZdS )	CSRFCheckc             C   s   |S )Nr   )selfr   reasonr   r   r   _reject   s    zCSRFCheck._rejectN)__name__
__module____qualname__r   r   r   r   r   r      s   r   c               @   s    e Zd ZdZdd Zdd ZdS )BaseAuthenticationzF
    All authentication classes should extend BaseAuthentication.
    c             C   s   t ddS )zS
        Authenticate the request and return a two-tuple of (user, token).
        z#.authenticate() must be overridden.N)NotImplementedError)r   r   r   r   r   r   )   s    zBaseAuthentication.authenticatec             C   s   dS )z
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        Nr   )r   r   r   r   r   authenticate_header/   s    z&BaseAuthentication.authenticate_headerN)r   r   r   __doc__r   r   r   r   r   r   r   $   s   r   c               @   s.   e Zd ZdZdZdd Zd
ddZdd	 ZdS )BasicAuthenticationz>
    HTTP Basic authentication against username/password.
    apic             C   s   t |j }| s"|d j dkr&dS t|dkrFtd}tj|nt|dkrdtd}tj|ytj|d j	t
jd}W n. tttjfk
r   td	}tj|Y nX |d |d  }}| j|||S )
z
        Returns a `User` if a correct username and password have been supplied
        using HTTP Basic authentication.  Otherwise returns `None`.
        r   s   basicN   z.Invalid basic header. No credentials provided.   zCInvalid basic header. Credentials string should not contain spaces.:z?Invalid basic header. Credentials not correctly base64 encoded.)r   splitlowerlen_r	   AuthenticationFailedbase64	b64decodedecoder   	partition	TypeErrorUnicodeDecodeErrorbinasciiErrorauthenticate_credentials)r   r   r   msgZ
auth_partsuseridpasswordr   r   r   r   >   s     
z BasicAuthentication.authenticateNc             C   sT   t  j|d|i}tf d|i|}|dkr8tjtd|jsLtjtd|dfS )z
        Authenticate the userid and password against username and password
        with optional request for context.
        r4   r   NzInvalid username/password.zUser inactive or deleted.)r   ZUSERNAME_FIELDr   r	   r(   r'   	is_active)r   r3   r4   r   credentialsuserr   r   r   r1   X   s    z,BasicAuthentication.authenticate_credentialsc             C   s
   d| j  S )NzBasic realm="%s")www_authenticate_realm)r   r   r   r   r   r   k   s    z'BasicAuthentication.authenticate_header)N)r   r   r   r   r8   r   r1   r   r   r   r   r   r   8   s
   
r   c               @   s    e Zd ZdZdd Zdd ZdS )SessionAuthenticationz<
    Use Django's session framework for authentication.
    c             C   s2   t |jdd}| s|j r dS | j| |dfS )z{
        Returns a `User` if the request session currently has a logged in user.
        Otherwise returns `None`.
        r7   N)getattr_requestr5   enforce_csrf)r   r   r7   r   r   r   r   t   s
    
z"SessionAuthentication.authenticatec             C   s6   t  }|j| |j|df i }|r2tjd| dS )zK
        Enforce CSRF validation for session based authentication.
        NzCSRF Failed: %s)r   process_requestZprocess_viewr	   ZPermissionDenied)r   r   checkr   r   r   r   r<      s
    
z"SessionAuthentication.enforce_csrfN)r   r   r   r   r   r<   r   r   r   r   r9   o   s   r9   c               @   s8   e Zd ZdZdZdZdd Zdd Zdd	 Zd
d Z	dS )TokenAuthenticationa  
    Simple token based authentication.

    Clients should authenticate by passing the token key in the "Authorization"
    HTTP header, prepended with the string "Token ".  For example:

        Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a
    TokenNc             C   s    | j d k	r| j S ddlm} |S )Nr   )r@   )modelZrest_framework.authtoken.modelsr@   )r   r@   r   r   r   	get_model   s    
zTokenAuthentication.get_modelc             C   s   t |j }| s,|d j | jj j kr0d S t|dkrPtd}tj|nt|dkrntd}tj|y|d j	 }W n& t
k
r   td}tj|Y nX | j|S )Nr   r!   z.Invalid token header. No credentials provided.r"   z=Invalid token header. Token string should not contain spaces.zIInvalid token header. Token string should not contain invalid characters.)r   r$   r%   keywordr   r&   r'   r	   r(   r+   UnicodeErrorr1   )r   r   r   r2   tokenr   r   r   r      s     
z TokenAuthentication.authenticatec             C   sf   | j  }y|jjdj|d}W n$ |jk
rD   tjtdY nX |jj	s\tjtd|j|fS )Nr7   )keyzInvalid token.zUser inactive or deleted.)
rB   objectsZselect_relatedr   ZDoesNotExistr	   r(   r'   r7   r5   )r   rF   rA   rE   r   r   r   r1      s    z,TokenAuthentication.authenticate_credentialsc             C   s   | j S )N)rC   )r   r   r   r   r   r      s    z'TokenAuthentication.authenticate_header)
r   r   r   r   rC   rA   rB   r   r1   r   r   r   r   r   r?      s   r?   c               @   s   e Zd ZdZdZdd ZdS )RemoteUserAuthenticationa  
    REMOTE_USER authentication.

    To use this, set up your web server to perform authentication, which will
    set the REMOTE_USER environment variable. You will need to have
    'django.contrib.auth.backends.RemoteUserBackend in your
    AUTHENTICATION_BACKENDS setting
    ZREMOTE_USERc             C   s*   t |jj| jd}|r&|jr&|d fS d S )N)Zremote_user)r   r   r   headerr5   )r   r   r7   r   r   r   r      s    
z%RemoteUserAuthentication.authenticateN)r   r   r   r   rI   r   r   r   r   r   rH      s   rH   )r   
__future__r   r)   r/   Zdjango.contrib.authr   r   Zdjango.middleware.csrfr   Zdjango.utils.sixr   Zdjango.utils.translationr   r'   Zrest_frameworkr   r	   r   r   objectr   r   r9   r?   rH   r   r   r   r   <module>   s   7$?