Accessing data passed to External Learning Tool from D2L - desire2learn

When setting up a link to an External Learning Tool, there are checkboxes labelled as 'Security Settings' which allow information (context information, for example) to be passed to the external tool.
How can this information be accessed from the tool?

Per the LTI spec parameters are passed as form post variables.
For example, php code to access the contact email address would be:
//Grab some LTI related parameters
if (isset($_REQUEST['lis_person_contact_email_primary']))
{
$email = $_REQUEST['lis_person_contact_email_primary'];
}
In D2L you can also combine LTI launches with Valence API calls as explained in the LTI and Valence article.
(You should also be validating the LTI oauth signature in order to be confident in your tool the request comes from the D2L Instance that has the key and secret for your tool)

Related

How to secure an API with OIDC/OAuth

I'm trying to better understand how to make use of OIDC/OAuth in securing a restful API, but I keep getting lost in terminology. Also when I research this question most of the answers are for Single Page Apps, so for purposes of this question assume the API will not be used for an SPA.
Assumptions:
Customers will access a restful API to interact with <Service>.
It is expected that customers will create automated scripts, or custom application in their own system to call the API.
Once setup it is not expected that there will be a real person who can provide credentials every time the API is called.
<Service> uses a 3rd party IDP to store and manage users.
3rd part IDP implements OIDC/Oauth and that is how it should be integrated into <Service>
Questions:
What OIDC/OAuth flow should be used in this situation?
What credentials should be provided to the customer? client-id/client-secret or something else?
What tokens can/should be used to communicate information about the "user"? E.g. Who they are/what they can do.
How should those tokens be validated?
Can you point me to any good diagrams/resources that explain this specific use case?
Am I missing anything important in the workflow?
It sounds like these are the requirements, if I am not misunderstanding you. The solution contains not just your own code and is more of a data modelling question than an OAuth one.
R1: Your company provides an API to business partners
R2. Business partners call it from their own applications, which they can develop however they see fit
R3. User authentication will be managed by each business partner, resulting in a unique ID per user
R4. You need to map these user IDs to users + resources in your own system
OAUTH
Partner applications should use the client credentials flow to get an access token to call the API. Each business partner would use a different credential for their set of users.
Using your own IDP to store users does not seem to make sense, since you do not seem to have an authentication relationship with the actual end users.
Access tokens issued to business partners would not be user specific by default. It is possible that a custom claim to identify the user could be included in access tokens - this would have to be developed in a custom manner such as via a custom header, since it is not part of the client credentials flow.
Access tokens would be verified in a standard OAuth manner to identify the partner - and possibly the end user.
DATA
Model users in your own system to have these fields, then store resources (such as orders) mapped against the User ID:
User ID (your generated value)
Partner ID (company the user is from)
External User ID (an ID that is easy for partners to supply)
Typically each partner would also have an entry in one of your database tables that includes a Client ID, name etc.
If you can't include a custom User ID claim in access tokens, partners have to tell you what user they are operating on when they call the API, supplying the external user ID:
POST /users/2569/orders
Your API authorization needs to ensure that calls from Partner A cannot access any resources from Partner B. In the above data you have all the fields you need to enable this.
SUMMARY
So it feels like you need to define the interface for your own APIs, based on how they will be called from the back end of partner apps. Hopefully the above hints help with this.

Is it safe to distribute client_id and client_secret for Google API for an installed application?

Similar questions have been asked before (1,2), but not explicitly answered:
Is it safe to store the client id and client secret credentials obtained for an Installed application -> Other for the Google API with the distributed source code of a command line application which will be distributed? Or will it be possible to access user accounts or data without the access_token granted by user consent?
The Google API docs specifies that..:
.. results in a client ID and, in some cases, a client secret, which you embed in the source code of your application. (In this context, the client secret is obviously not treated as a secret.)
it is apparent from other documentation that this is not best practice: the client_secret should not even be provided by the service, but it is currently required by the oauth2 and googleapiclient libraries (for Python), and probably by the Google service as well.
The application will use oauth2 based on these official examples.
References, good explanation or documentation that confirms whether this is truly safe or not is much appreciated.
Client Id is a publicly visible and it is safe to put it in your website, but it is not safe to put your client secret in js or html code in a website

Using remote plugin to load images in Desire2Learn

I want to insert a link in the image upload page in the D2L LMS which allows the user to upload an image from our Gravatar service. I understand I can do it through the valence content API but just as we can put in links in the insert stuff sidebar, can we also wrap an LTI link into a link on the image upload page?
Thanks!
The Remote Plugin Service builds on LTI to let you integrate with D2L's LMS in more "native user interaction" kinds of ways. The "Insert Stuff" framework is one of these, as you've recognized. While D2L does intend to offer more Remote Plugin configuration types in the future, currently there is no configuration type for integration with the image upload interaction point. This is, however, a good idea; I'd encourage you to suggest it on the Product Ideas Exchange in the D2L Community site, or make a request for this enhancement through your account or partner manager at D2L.
There is sample code for creating a remote plugin that allows you to insert images using the Insert Stuff Framework, which was introduced in the following blog post: http://devs.valence.desire2learn.com/2013/11/11/making-development-easier-with-the-remote-plugins-test-service/. This sample uses LTI and the Valence Learning Framework APIs to insert images.

Desire2Learn invalid oAuth signature with LTI Learning Tool Link

I've created a test LTI Tool Provider and tested it successfully against the IMSGlobal test consumer at http://www.imsglobal.org/developers/LTI/test/v1p1/lms.php.
However, when I use my endpoint in our client's D2L test instance the oAuth signatures don't match. I suspect the signature base string generated by D2L is somehow different than mine. Is there a way to obtain the D2L tool consumer's base string for comparison?
The D2L Tool Consumer implementation has also been tested successfully against the IMS reference implementations. However, registering and configuring an external learning tool in the Learning Environment is a bit of a tricky process.
In the External Learning Tools management tool you can manage the specific list links (which, when embedded, create an LTI launch point in the LMS) as well as the list of tool provider configurations (if, for example, you have one tool provider, but want to embed a number of LTI launch links for that same tool provider). The exact UX in the Learning Environment for getting to manage these two lists of items depends on the version of your LE... in LE's that have early support for LTI, the tool provider list is hidden behind a settings gear on the External Learning Tools management page I think; on later LE's, the list of links and list of tool providers are more equally visible in the management page.
The Tool Provider list allows you to provide a key and secret for the tool provider, and to use that to sign LTI launches rather than the default key/secret configured for the Tool Consumer itself ("use custom tool consumer information instead of default").
The Link list allows you to (a) choose to sign LTI launches from a link, and (b) sign the launch with the tool consumer key/secret or one specific to the LTI link itself. Note that if you use a matching Tool Provider entry for an External Learning Tool link entry, and if that Tool Provider entry has a key/secret that's set to override the default tool consumer information, then it is this Tool Provider override key/secret that get used to sign the launch if in (b) above you choose to sign the launch with the tool consumer key/secret.
Yes, that's confusing.
So -- the launch is either signed or not signed, depending on the setting in the 'Edit Link' page for the link. If the launch is signed, then it can be signed with the 'Link key/secret', provided on the 'Edit Link' page, or it can be signed with the 'Tool Consumer key/secret'. If that last one, then it will first check for a matching tool provider entry override to provide a key/secret and if not finding one, it will use the key/secret set for the entire LE.
Once you have all that set up, from inside the 'Edit Link' page for a link, you can "preview request" to do a test-launch. You can also "preview request details" which will take you to a page that shows you what the LTI POST body form will look like -- from there you can verify if the oauth properties will show up in the launch form -- if they're not in that preview form, then your launches aren't getting signed. If the oauth properties are in the form, then you can see what will be sent and you can do debugging/testing with those values.
Thanks in part to Viktor's suggestion to preview the request, I was able to debug this.
In my Tool Provider, I am checking for certain non-required LTI parameters. When such a parameter did not exist in the consumer's request I was setting it to an empty string rather than throwing an exception.
Using the IMS test consumer I was able to discover that when I set a request parameter to an empty string, while the Tool Consumer omits the field entirely, our signatures will differ even though the two base_strings match. I still don't fully understand this; my understanding of oAuth was that two identical strings signed with the same key and secret will produce the same signature. In any case, better validation of the request parameters now ensures that our strings--and signatures--match.

Can D2L be used as a LTI Tool Provider as well as Tool Consumer

Can I use D2L as a Tool Provider as well as Tool consumer? Basically if I want to access some learning objects from one D2L instance to another D2L instance - is that possible?
Subrata
Not currently, no: D2L cannot act as an LTI Tool Provider. You may be able to achieve what you describe with a service app running in between two D2L instances, using the Valence APIs to read content objects from one LMS, and write to another LMS; however, in this case, you'd need the service to have user credentials for a user in both instances.

Resources