o
    b)                     @   st   d dl Z d dlmZ d dlmZ ddlmZmZ ddlmZm	Z	m
Z
 ddlmZ e eZd	ZG d
d deeZdS )    N)jwt)	JoseError   )	BaseGrantTokenEndpointMixin)UnauthorizedClientErrorInvalidRequestErrorInvalidGrantError   sign_jwt_bearer_assertionz+urn:ietf:params:oauth:grant-type:jwt-bearerc                   @   sZ   e Zd ZeZe		d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S )JWTBearerGrantNc                 K   s   t | ||||||fi |S )Nr   )keyZissuerZaudiencesubjectZ	issued_atZ
expires_atclaimskwargs r   `/var/www/secure340b-portal/env/lib/python3.10/site-packages/authlib/oauth2/rfc7523/jwt_bearer.pysign   s   
zJWTBearerGrant.signc                 C   s   ddiddiddiddidS )zCreate a claims_options for verify JWT payload claims. Developers
        MAY overwrite this method to create a more strict options.
        Z	essentialT)ZisssubZaudexpr   )selfr   r   r   create_claims_options   s
   z$JWTBearerGrant.create_claims_optionsc              
   C   sV   t j|| j|  d}z|  W |S  ty* } ztd| t|j	dd}~ww )a#  Extract JWT payload claims from request "assertion", per
        `Section 3.1`_.

        :param assertion: assertion string value in the request
        :return: JWTClaims
        :raise: InvalidGrantError

        .. _`Section 3.1`: https://tools.ietf.org/html/rfc7523#section-3.1
        )Zclaims_optionszAssertion Error: %r)descriptionN)
r   decoderesolve_public_keyr   validater   logdebugr	   r   )r   	assertionr   er   r   r   process_assertion_claims&   s   

z'JWTBearerGrant.process_assertion_claimsc                 C   sp   | j jd}|std| |}| |}td| || j	s&t
 || j _|   | ||| j _dS )a  The client makes a request to the token endpoint by sending the
        following parameters using the "application/x-www-form-urlencoded"
        format per `Section 2.1`_:

        grant_type
             REQUIRED.  Value MUST be set to
             "urn:ietf:params:oauth:grant-type:jwt-bearer".

        assertion
             REQUIRED.  Value MUST contain a single JWT.

        scope
            OPTIONAL.

        The following example demonstrates an access token request with a JWT
        as an authorization grant:

        .. code-block:: http

            POST /token.oauth2 HTTP/1.1
            Host: as.example.com
            Content-Type: application/x-www-form-urlencoded

            grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
            &assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0.
            eyJpc3Mi[...omitted for brevity...].
            J9l-ZhwP[...omitted for brevity...]

        .. _`Section 2.1`: https://tools.ietf.org/html/rfc7523#section-2.1
        r   zMissing "assertion" in requestzValidate token request of %sN)requestformgetr   r!   authenticate_clientr   r   Zcheck_grant_type
GRANT_TYPEr   clientZvalidate_requested_scopeauthenticate_useruser)r   r   r   r'   r   r   r   validate_token_request:   s   

z%JWTBearerGrant.validate_token_requestc                 C   s:   | j | jjdd}td|| jj | | d|| jfS )zZIf valid and authorized, the authorization server issues an access
        token.
        F)scopeZinclude_refresh_tokenzIssue token %r to %r   )Zgenerate_tokenr"   r+   r   r   r'   Z
save_tokenZTOKEN_RESPONSE_HEADER)r   tokenr   r   r   create_token_responseh   s   
z$JWTBearerGrant.create_token_responsec                 C      t  )a  Authenticate user with the given assertion claims. Developers MUST
        implement it in subclass, e.g.::

            def authenticate_user(self, client, claims):
                user = User.get_by_sub(claims['sub'])
                if is_authorized_to_client(user, client):
                    return user

        :param client: OAuth Client instance
        :param claims: assertion payload claims
        :return: User instance
        NotImplementedError)r   r'   r   r   r   r   r(   t   s   z JWTBearerGrant.authenticate_userc                 C   r/   )a4  Authenticate client with the given assertion claims. Developers MUST
        implement it in subclass, e.g.::

            def authenticate_client(self, claims):
                return Client.get_by_iss(claims['iss'])

        :param claims: assertion payload claims
        :return: Client instance
        r0   )r   r   r   r   r   r%      s   
z"JWTBearerGrant.authenticate_clientc                 C   r/   )a  Find public key to verify assertion signature. Developers MUST
        implement it in subclass, e.g.::

            def resolve_public_key(self, headers, payload):
                jwk_set = get_jwk_set_by_iss(payload['iss'])
                return filter_jwk_set(jwk_set, headers['kid'])

        :param headers: JWT headers dict
        :param payload: JWT payload dict
        :return: A public key
        r0   )r   headerspayloadr   r   r   r      s   z!JWTBearerGrant.resolve_public_key)NNNN)__name__
__module____qualname__JWT_BEARER_GRANT_TYPEr&   staticmethodr   r   r!   r*   r.   r(   r%   r   r   r   r   r   r      s    .r   )loggingZauthlib.joser   Zauthlib.jose.errorsr   Zrfc6749r   r   r   r   r	   r   r   	getLoggerr4   r   r7   r   r   r   r   r   <module>   s    
