
    k7i                         S SK r SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJ	r	  S	S
K
Jr  S	SK
Jr  S	SK
Jr  \ R                  " \5      rSr " S S\\5      rg)    N   )	BaseGrant)TokenEndpointMixin)AccessDeniedError)InvalidRequestError)UnauthorizedClientError)hooked   )AuthorizationPendingError)ExpiredTokenError)SlowDownErrorz,urn:ietf:params:oauth:grant-type:device_codec                   R    \ rS rSrSr\r/ SQrS r\	S 5       r
S rS rS rS	 rS
rg)DeviceCodeGrant   a	  This OAuth 2.0 [RFC6749] protocol extension enables OAuth clients to
request user authorization from applications on devices that have
limited input capabilities or lack a suitable browser.  Such devices
include smart TVs, media consoles, picture frames, and printers,
which lack an easy input method or a suitable browser required for
traditional OAuth interactions. Here is the authorization flow::

    +----------+                                +----------------+
    |          |>---(A)-- Client Identifier --->|                |
    |          |                                |                |
    |          |<---(B)-- Device Code,      ---<|                |
    |          |          User Code,            |                |
    |  Device  |          & Verification URI    |                |
    |  Client  |                                |                |
    |          |  [polling]                     |                |
    |          |>---(E)-- Device Code       --->|                |
    |          |          & Client Identifier   |                |
    |          |                                |  Authorization |
    |          |<---(F)-- Access Token      ---<|     Server     |
    +----------+   (& Optional Refresh Token)   |                |
          v                                     |                |
          :                                     |                |
         (C) User Code & Verification URI       |                |
          :                                     |                |
          v                                     |                |
    +----------+                                |                |
    | End User |                                |                |
    |    at    |<---(D)-- End user reviews  --->|                |
    |  Browser |          authorization request |                |
    +----------+                                +----------------+

This DeviceCodeGrant is the implementation of step (E) and (F).

(E) While the end user reviews the client's request (step D), the
    client repeatedly polls the authorization server to find out if
    the user completed the user authorization step.  The client
    includes the device code and its client identifier.

(F) The authorization server validates the device code provided by
    the client and responds with the access token if the client is
    granted access, an error if they are denied access, or an
    indication that the client should continue to poll.
)client_secret_basicclient_secret_postnonec                 8   U R                   R                  R                  R                  S5      nU(       d  [	        S5      eU R                  5       nUR                  U R                  5      (       d  [        SU R                   S35      eU R                  U5      nU(       d  [	        S5      eUR                  5       UR                  5       :w  a
  [        5       eU R                  U5      nX@R                   l        X R                   l        X0R                   l        g)a  After displaying instructions to the user, the client creates an
access token request and sends it to the token endpoint with the
following parameters:

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

device_code
    REQUIRED.  The device verification code, "device_code" from the
    device authorization response.

client_id
    REQUIRED if the client is not authenticating with the
    authorization server as described in Section 3.2.1. of [RFC6749].
    The client identifier as described in Section 2.2 of [RFC6749].

For example, the client makes the following HTTPS request::

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

    grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code
    &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
    &client_id=1406020730
device_codez Missing 'device_code' in payloadz3The client is not authorized to use 'response_type='z Invalid 'device_code' in payloadN)requestpayloaddatagetr   "authenticate_token_endpoint_clientcheck_grant_type
GRANT_TYPEr   query_device_credentialget_client_idvalidate_device_credentialuserclient
credential)selfr   r"   r#   r!   s        \/home/james-whalen/.local/lib/python3.13/site-packages/authlib/oauth2/rfc8628/device_code.pyvalidate_token_request&DeviceCodeGrant.validate_token_requestA   s    8 ll**//33MB%&HII88:&&t77)EdooEVVWX  11+>
%&HII##%)=)=)??)++..z: $",    c                 H   U R                   R                  nU R                   R                  R                  5       nU R	                  U R                   R
                  UUR                  S5      S9n[        R                  SX15        U R                  U5        SX0R                  4$ )zIf the access token request is valid and authorized, the
authorization server issues an access token and optional refresh
token.
refresh_token)r!   scopeinclude_refresh_tokenzIssue token %r to %r   )r   r"   r#   	get_scopegenerate_tokenr!   r   logdebug
save_tokenTOKEN_RESPONSE_HEADER)r$   r"   r+   tokens       r%   create_token_response%DeviceCodeGrant.create_token_responses   s     $$''113##"""("9"9/"J $ 

 			(%8E5555r(   c                 
   UR                  5       (       a
  [        5       eUR                  5       nU R                  U5      nUb  Uu  pEU(       d
  [	        5       eU$ U R                  U5      (       a
  [        5       e[        5       e)N)
is_expiredr   get_user_codequery_user_grantr   should_slow_downr   r   )r$   r#   	user_code
user_grantr!   approveds         r%   r    *DeviceCodeGrant.validate_device_credential   sx      ""#%%,,.	**95
!'ND'))K  ,,/!'))r(   c                     [        5       e)a9  Get device credential from previously savings via ``DeviceAuthorizationEndpoint``.
Developers MUST implement it in subclass::

    def query_device_credential(self, device_code):
        return DeviceCredential.get(device_code)

:param device_code: a string represent the code.
:return: DeviceCredential instance
NotImplementedError)r$   r   s     r%   r   'DeviceCodeGrant.query_device_credential   s     "##r(   c                     [        5       e)a  Get user and grant via the given user code. Developers MUST
implement it in subclass::

    def query_user_grant(self, user_code):
        # e.g. we saved user grant info in redis
        data = redis.get("oauth_user_grant:" + user_code)
        if not data:
            return None

        user_id, allowed = data.split()
        user = User.get(user_id)
        return user, bool(allowed)

Note, user grant information is saved by verification endpoint.
rA   )r$   r<   s     r%   r:    DeviceCodeGrant.query_user_grant   s      "##r(   c                     [        5       e)zThe authorization request is still pending and polling should
continue, but the interval MUST be increased by 5 seconds for this
and all subsequent requests.
rA   )r$   r#   s     r%   r;    DeviceCodeGrant.should_slow_down   s    
 "##r(    N)__name__
__module____qualname____firstlineno____doc__DEVICE_CODE_GRANT_TYPEr   TOKEN_ENDPOINT_AUTH_METHODSr&   r	   r5   r    r   r:   r;   __static_attributes__rH   r(   r%   r   r      sC    *X (J"W0-d 6 6 *$
$$$$r(   r   )loggingrfc6749r   r   rfc6749.errorsr   r   r   rfc6749.hooksr	   errorsr   r   r   	getLoggerrI   r0   rN   r   rH   r(   r%   <module>rW      sJ      ( . 0 4 " - % !!G h$i!3 h$r(   