Contents
The Python library provides help with ID/Key authentication.
Installation¶
You can find the source for our Python client library SDK in two locations:
Our own Python client GitHub repository.
On the PyPi package index repository, so you can install it as a package with pip or easy_install.
Dependencies. In order to use the Python client library SDK, you’ll need to first ensure you have a working Python development environment:
Python 3 (the reference environment uses Python 3.3).
The Bottle Python package if you want to use the samples available in conjunction with this client library (not a dependency for the client library itself).
The Requests Python package gets in our our d2lvalence.auth module so that you can use a calling user context object as an authentication helper for Requests.
Authentication API¶
The d2lvalence.auth module provides assistance for the authentication needed
to make Learning Framework API calls. You can use the module’s functions (and
perhaps also classes) to create a calling user context
object that you can then employ in
conjunction with the Requests package as an authentication helper.
In general, there are three kinds of REST API routes:
Those that require an authenticated calling user context (the overwhelming majority) must be decorated by tokens that indicate both the application making the request and the logged-in user context (the user on behalf of which the client application is acting). (Note that because of the way our authentication system works, a calling user context also implies an application context.)
Those that require only an authenticated application context must be decorated by tokens that indicate the application making the request (but not a particular person with a back-end service user account). Typically these routes include only those that can gather general property information about the LMS API itself.
The authentication entry point route that a client application must use to start the process for establishing a user context.
Usage¶
In a typical work-flow using this module, the client application employing the
module should start by creating a new
application context object
with its App ID and
App Key as provided by D2L. Then, use the application context to
Create a URL you can use to initiate the authentication process with the back-end LMS service.
Handle the received URL that the LMS passes back as the result of the user authentication process, and use it to create a
user context object
for that logged-in user.Use the user context object to properly decorate API queries with the authentication tokens that signal the user context to the back-end service.
Walk-through. Here’s an interactive walk-through demonstration, with some inserted comments, to help show intended usage. Here, we use the Requests Python package to cleanly make the URL fetches at the end of the walk-through.
>>> import requests
>>> import d2lvalence.auth as d2lauth
>>>
>>> You will need your own application credentials here, and it's generally
>>> wiser to read them from the environment or a secured file and not put
>>> them directly in your code.
>>> app_creds = { 'app_id': 'G9nUpvbZQyiPrk3um2YAkQ', 'app_key': 'ybZu7fm_JKJTFwKEHfoZ7Q' }
>>>
>>> # We use the App Context factory method to fetch an app context for
>>> # the App ID-key pair
>>> ac = d2lauth.fashion_app_context(app_id=app_creds['app_id'], app_key=app_creds['app_key'])
>>>
>>> # Build an url we can use for user authentication
>>> # -- you can use 'localhost:8080' for the callback as long as you don't have a
>>> # webserver running on that port on your local computer that will answer
>>>
>>> auth_url = ac.create_url_for_authentication('devcop.brightspace.com', 'http://localhost:8080')
>>> auth_url
'https://devcop.brightspace.com/d2l/auth/api/token?x_target=http%3A%2F%2Flocalhost%3A8080&x_b=MvLoaoeGN77jsFnJVvHT3lIe2PKpks6sh69NaqmLg3E&x_a=G9nUpvbZQyiPrk3um2YAkQ'
>>>
>>> # ... We now feed the 'auth_url' to the web browser that will
>>> # handle our user auth ... it will try to redirect back to the 'localhost' URL
>>> # we provided, with the user ID-key pair attached as quoted params --
>>> # your browser should complain there's no handler for this URL, but you
>>> # can then likely copy the 'redirect url' for the next step out of the browser's
>>> # address bar field....
>>>
>>> redirect_url = 'http://localhost:8080?x_a=dC31ncmeHGvtullmp-6xSu&x_b=GPo8Rm7ou1fxZ7D8JHKOu1&x_c=093VuH_tHn1WGlla7pQ7MvGDJUX8lZ5gS5jwOgR8xNE'
>>>
>>> # We use the redirect_url and get the app context object to create us a
>>> # user context.
>>> uc = ac.create_user_context(result_uri=redirect_url, host='devcop.brightspace.com', encrypt_requests=True)
>>>
>>> # When we want to make an API call, we use the user context to build the
>>> # URL to call, given the API route we provide
>>> route = '/d2l/api/versions/'
>>> url = uc.create_authenticated_url(route)
>>> url
'https://devcop.brightspace.com/d2l/api/versions/?x_t=1338916317&x_d=lz2D5RD9LFejpriJTcw7QD8FaBPymmWpK0_mdNt5on0&x_b=dC31ncmeHGvtullmp-6xSu&x_c=pRir1VlN73yhAytcLq6kQ4krBv563YoASnKcJSwdBBY&x_a=G9nUpvbZQyiPrk3um2YAkQ'
>>>
>>> # Note that the created URL is time-sensitive ("x_t" holds the
>>> # timestamp), so we can't wait too long before using this call... we use
>>> # the requests library to cleanly make the API call for us
>>> r = requests.get(url)
>>> r.status_code
200
>>> r.text
'[{"ProductCode":"lp",
"LatestVersion":"1.0",
"SupportedVersions":["1.0"]},
{"ProductCode":"ep",
"LatestVersion":"2.0",
"SupportedVersions":["2.0"]},
{"ProductCode":"le",
"LatestVersion":"1.0",
"SupportedVersions":["1.0"]}]'
>>>
Using the Requests library with a D2LUserContext. You can use a D2LUserContext instance as an authentication helper object for the Requests library. Here’s a re-presentation of the previous example, from the point at which we’ve created a calling user context:
>>>
>>> uc = ac.create_user_context(result_uri=redirect_url, host='devcop.brightspace.com', encrypt_requests=True)
>>> route = '/d2l/api/versions/'
>>> r = requests.get(uc.scheme + '://' + uc.host + route, auth=uc)
>>> r.status_code
200
>>> r.text
'[{"ProductCode":"lp",
"LatestVersion":"1.0",
"SupportedVersions":["1.0"]},
{"ProductCode":"ep",
"LatestVersion":"2.0",
"SupportedVersions":["2.0"]},
{"ProductCode":"le",
"LatestVersion":"1.0",
"SupportedVersions":["1.0"]}]'
>>>
Reference¶
The auth module comprises a several classes that can encapsulate a calling context and help you generate the right authentication parameters for Brightspace API calls.
Factory functions¶
-
fashion_app_context
(app_id, app_key) → client application context object¶ Build a new application context with the default signer implementation.
- Parameters
app_id – Client application’s D2L-provided Application ID string.
app_key – Client application’s D2L-provided Application Key string.
- Returns
Application context
instance.
-
fashion_user_context
(app_id, app_key, d2l_user_context_props_dict) → calling user context object¶ Re-build a new user context using the default signer implementation.
- Parameters
app_id – Client application’s D2L-provided Application ID string.
app_key – Client application’s D2L-provided Application Key string.
d2l_user_context_props_dict – Properties dictionary retrieved from a previous user context instance.
- Returns
User context
instance.
Classes¶
-
class
D2LAppContext
(app_id, app_key[, signer])¶ Application context for a Brightspace API client application.
- Parameters
app_id – Client application’s D2L-provided Application ID string.
app_key – Client application’s D2L-provided Application Key string, which the application should use for signing.
signer – A signer instance that implements
D2LSigner
.
Clients can instantiate an application context on their own, if they wish; to do this, they must be able to provide an appropriate signer instance (one that properly implements
D2LSigner
). It would be simpler in almost all cases to use the built-in signer implementation, and in that case, you need only use the factory methodfashion_app_context()
to build your application context.-
create_url_for_authentication
(host, client_app_url[, connect_type=None[, encrypt_request=True]) → URL string¶ Build a URL that the user’s browser can employ to complete the user authentication process with the back-end LMS.
- Parameters
host – “host:port” string for the back-end LMS service’s API host.
client_app_url – Client application URL the service redirects back to after user-authentication.
connect_type – (Optional, None by default.) Provide mobile to signal client platform is a mobile device.
encrypt_request – (Optional, True by default.) If true, generate an HTTPS URL; otherwise, generate an HTTP URL.
- Returns
URL to complete the ID-Key authentication process.
-
create_anonymous_user_context
(host[, encrypt_request=False]) → anonymous calling user context object¶ Build a new authentication context with no identified user for a Brightspace API client application. You can use an anonymous user context for making some API calls to probe the properties of the API supported by the back-end service (for example, the API versions supported).
- Parameters
host – Host name for the back-end service.
encrypt_requests – (Optional, False by default.) If true, use HTTPS for API requests.
- Returns
User context
instance.
-
create_user_context
([result_uri[, host[, encrypt_request[, d2l_user_context_props_dict]]]]) → calling user context object¶ Build a new authentication LMS-user context for a Brightspace API client application.
- Parameters
result_uri – (Optional, empty string by default.) Entire result URI (including quoted parameters) that the back-end service redirected the user to after user-authentication.
host – (Optional, empty string by default.) Host name for the back-end service.
encrypt_requests – (Optional, False by default.) If true, use HTTPS for API requests.
d2l_user_context_props_dict – (Optional, empty dictionary by default.) Build the user context from a stored context properties dictionary.
- Returns
User context
instance.
You can use this method in two ways:
You can provide the result_uri the service redirects to after successful user_authentication, along with the host to which API calls will get made: the application context will then use the information in the result_uri to build a user context from scratch.
You can re-build a user context from the stored context properties dictionary retrieved from the previous instance of the user context (using
D2LUserContext.get_context_properties()
). If you provide a not-None value for this parameter, the method assumes it can rebuild the user context from the dictionary provided, and will ignore the other method parameters.Note that only an application context with the same App ID and App Key pair as the first one to build the user context can use this methodology. The back-end LMS service couples User ID and User Key pair values to particular application contexts.
-
class
D2LUserContext
(host, user_id, user_key, app_id, app_key[, encrypt_results[, server_skew[, signer]]])¶ Calling user context for a Brightspace API client application.
- Parameters
host – “host:port” string for the back-end LMS service’s API host.
user_id – Logged-in user’s D2L-provided User ID string.
user_key – Logged-in user’s D2L-provided User Key string.
app_id – Client application’s D2L-provided Application ID string.
app_key – Client application’s D2L-provided Application Key string.
encrypt_results – (Optional, False by default.) If true, use HTTPS when building API request URLs.
server_skew – (Optional, 0 by default.) Server time skew from local client clock.
signer – A signer instance that implements
D2LSigner
.
Note that clients should not be building user context instances alone; rather, you should use
D2LAppContext.create_user_context()
on your application context instance to fashion a new user context.-
create_authenticated_url
([api_route[, method]) → URL string¶ Create a properly tokenized URL for a new request through this calling user context.
- Parameters
api_route – (Optional, /d2l/api/versions/ by default.) API route to invoke on the back-end service.
method – (Optional, GET by default.) HTTP method for API call.
- Returns
Tokenized URL for API request.
-
decorate_url_with_authentication
(APIURL[, method]) → URL string¶ Decorate a URL with the proper tokens required for calling through this user context.
- Parameters
- Returns
Tokenized URL for API request.
Use this method to decorate an APIURL (fully formed URL including host, api path, and optional query parameters) so that you can invoke the action with the decorating user context.
-
get_context_properties
() → calling user context properties dictionary¶ Retrieve a dictionary of this calling user context’s current state.
You can provide this dictionary to
D2LAppContext.create_user_context()
orfashion_user_context()
to rebuild this user context at a later time. It will have properties that consist of something like this:>>> uc.get_context_properties() {'user_key': 'TCb8Ezbh1lpw7Q8WUXBh1', 'user_id': 'qP31aurgrUTighzc-6kFh', 'host': 'devcop.brightspace.com', 'encrypt_requests': True, 'server_skew': 0} >>>
-
set_new_skew
(new_skew)¶ Adjust the known time skew between the local client using this user context.
- Parameters
new_skew – New server time-skew value, in milliseconds.
-
class
D2LSigner
¶ Signer class that app and user contexts can employ to create appropriately signed tokens for making Learning Framework API calls.
-
get_hash
(key_string, base_string) → signature string¶ Build a digest value suitable for direct inclusion into an URL’s query parameter as a token.
- Parameters
key_string – App or User Key to use for encoding.
base_string – Base string to encode.
- Returns
Token string for use in an ID-Key API call’s query parameter.
Note that this method returns an URL-safe, base64 encoded result of the signing operation suitable for directly adding as a query parameter value to an API call.
-