Skip to content

Commit

Permalink
Add device token fetch URI generator
Browse files Browse the repository at this point in the history
In order to perform the full device authorization flow it's necessary
to first generate the device code and get the authorization flow URL.

prepare_request_uri() allows us to do this while providing scopes and
additional parameters.
  • Loading branch information
kellyma2 committed Dec 22, 2021
1 parent 0158e28 commit 24ad1dc
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
26 changes: 26 additions & 0 deletions oauthlib/oauth2/rfc8628/clients/device.py
Expand Up @@ -8,7 +8,10 @@
"""

from oauthlib.oauth2 import BackendApplicationClient, Client
from oauthlib.oauth2.rfc6749.errors import InsecureTransportError
from oauthlib.oauth2.rfc6749.parameters import prepare_token_request
from oauthlib.oauth2.rfc6749.utils import is_secure_transport, list_to_scope
from oauthlib.common import add_params_to_uri


class DeviceClient(Client):
Expand All @@ -27,6 +30,29 @@ class DeviceClient(Client):

grant_type = 'urn:ietf:params:oauth:grant-type:device_code'

def __init__(self, client_id, **kwargs):
super().__init__(client_id, **kwargs)
self.client_secret = kwargs.get('client_secret')

def prepare_request_uri(self, uri, scope=None, **kwargs):
if not is_secure_transport(uri):
raise InsecureTransportError()

scope = self.scope if scope is None else scope
params = [(('client_id', self.client_id)), (('grant_type', self.grant_type))]

if self.client_secret is not None:
params.append(('client_secret', self.client_secret))

if scope:
params.append(('scope', list_to_scope(scope)))

for k in kwargs:
if kwargs[k]:
params.append((str(k), kwargs[k]))

return add_params_to_uri(uri, params)

def prepare_request_body(self, device_code, body='', scope=None,
include_client_id=False, **kwargs):
"""Add device_code to request body
Expand Down
25 changes: 24 additions & 1 deletion tests/oauth2/rfc8628/clients/test_device.py
Expand Up @@ -16,13 +16,23 @@ class DeviceClientTest(TestCase):
"require": "extra arguments"
}

client_secret = "asecret"

device_code = "somedevicecode"

scope = ["profile", "email"]

body = "not=empty"

body_up = "not=empty&grant_type=urn:ietf:params:oauth:grant-type:device_code"
body_code = body_up + "&device_code=somedevicecode"
body_kwargs = body_code + "&some=providers&require=extra+arguments"

device_code = 'somedevicecode'
uri = "https://example.com/path?query=world"
uri_id = uri + "&client_id=" + client_id
uri_grant = uri_id + "&grant_type=urn:ietf:params:oauth:grant-type:device_code"
uri_secret = uri_grant + "&client_secret=asecret"
uri_scope = uri_secret + "&scope=profile+email"

def test_request_body(self):
client = DeviceClient(self.client_id)
Expand All @@ -39,3 +49,16 @@ def test_request_body(self):
body = client.prepare_request_body(
self.device_code, body=self.body, **self.kwargs)
self.assertFormBodyEqual(body, self.body_kwargs)

def test_request_uri(self):
client = DeviceClient(self.client_id)

uri = client.prepare_request_uri(self.uri)
self.assertURLEqual(uri, self.uri_grant)

client = DeviceClient(self.client_id, client_secret=self.client_secret)
uri = client.prepare_request_uri(self.uri)
self.assertURLEqual(uri, self.uri_secret)

uri = client.prepare_request_uri(self.uri, scope=self.scope)
self.assertURLEqual(uri, self.uri_scope)

0 comments on commit 24ad1dc

Please sign in to comment.