.NET - OAuth2 Workflow: Part 1 - Authrorize Redirect
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
Recently I was asked to create a custom grading tool based on rubrics, which requires modifying student grade data. I had created a LTI toolkit to run some reports and automate SIS integration workflows, in that scenario I was using a token generated in a service account. But using a service account token to modify grades is not an accepted method. For grading we want to be able to verify a few important details and take advantage of existing functionality within Canvas:
- The user has access to the course (masquerading is technically possible, but prone to errors)
- The user has privileges to modify grades
- Leverage the existing "View Grading History" feature build into Canvas
Canvas documentation on the OAuth2 workflow can be found here: OAuth2 Overview documentation
The example used for this post assumes the application will be launched from within Canvas using LTI integration. If you have not yet worked through OAuth and LTI, these articles can provide an overview of how to get started before you dive into OAuth2:
- .NET LTI Project - Part 1 - Connect to Canvas
- .NET LTI Project - Part 2 - Launch Request
- .NET LTI Project - Part 3 - OAuth
Part 2 and 3 of this example can be found here:
- .NET - OAuth2 Workflow: Part 2 - Access Token & State
- .NET - OAuth2 Workflow: Part 3 - Refresh Token
Before you get started...
To get through this example, you will need to have the following knowledge and tools
- You have successfully integrated at least one custom application that you have written with Canvas using LTI, which also implies the following:
- You have a development environment setup and ready to go (language of your choice)
- Your environment includes a web server
- You have configured your web server with an SSL certificate
- Have access to a database to cache information
- You have administrative access to a test instance of Canvas
- You are familiar with making API calls
- You are familiar with using Git code repositories
If you have experience with web apps, this is not complicated. This walk through should be straight forward.
Source code for this walk through can be found here:
The branch of interest for this walk-through:
- step1-verify-redirect
- git fetch && git checkout step1-verify-redirect
Getting Things Ready in Canavs
The first step towards OAuth2 is completing the LTI install of your application within your Canvas instance. If you have not created an LTI application yet, I suggest completing the three LTI posts mentioned above, I will not cover those steps again here. .NET LTI Project - Part 1 - Connect to Canvas covers steps for registering your application in Canvas.
For the simple application associated with this example, I generated the LTI XML using the tool found here:
Here is the result (substitute your.domain.com with the URL specific to your test environment):
<?xml version="1.0" encoding="UTF-8"?>
<cartridge_basiclti_link xmlns="http://www.imsglobal.org/xsd/imslticc_v1p0"
xmlns:blti = "http://www.imsglobal.org/xsd/imsbasiclti_v1p0"
xmlns:lticm ="http://www.imsglobal.org/xsd/imslticm_v1p0"
xmlns:lticp ="http://www.imsglobal.org/xsd/imslticp_v1p0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.imsglobal.org/xsd/imslticc_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticc_v1p0.xsd
http://www.imsglobal.org/xsd/imsbasiclti_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imsbasiclti_v1p0.xsd
http://www.imsglobal.org/xsd/imslticm_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticm_v1p0.xsd
http://www.imsglobal.org/xsd/imslticp_v1p0 http://www.imsglobal.org/xsd/lti/ltiv1p0/imslticp_v1p0.xsd">
<blti:title>OAuth2 Test</blti:title>
<blti:description>Test app to prove out Canvas OAuth2 worflow</blti:description>
<blti:icon></blti:icon>
<blti:launch_url>https://your.domain.com/home/oauth2Request</blti:launch_url>
<blti:extensions platform="canvas.instructure.com">
<lticm:property name="tool_id">D48C2D1E-C3BC-443E-9BA3-BDF000FDC91B</lticm:property>
<lticm:property name="privacy_level">public</lticm:property>
<lticm:property name="domain">your.domain.com</lticm:property>
<lticm:options name="course_navigation">
<lticm:property name="url">https://your.domain.com/home/oauth2Request</lticm:property>
<lticm:property name="text">OAuth2 Test</lticm:property>
<lticm:property name="visibility">admins</lticm:property>
<lticm:property name="default">enabled</lticm:property>
<lticm:property name="enabled">true</lticm:property>
</lticm:options>
</blti:extensions>
<cartridge_bundle identifierref="BLTI001_Bundle"/>
<cartridge_icon identifierref="BLTI001_Icon"/>
</cartridge_basiclti_link>
Point of interest in the XML:
- https://your.domain.com/home/oauth2Request
- This is the URL that Canvas will call when the user launches your app from the Canvas menu, the first step in initiating the OAuth2 workflow
The XML configuration above should create a Course menu option labeled "Oauth2 Test".
When you install the application in Canvas, make a note of the consumer key and shared secret for reference later.
You will also need to generate a "Developer Key". Follow the steps in this Canvas article:
For the purposes of the exercise, use the following redirect URL (with your domain):
- https://your.domain.com/home/oauth2response
- This is not the same URL defined in the XML
This method call (/home/oauth2response) will line up with the source code associated with this example.
The result of creating the developer key will generate a unique ID for your redirect:
Required Variables
There are three <appSettings> variables that we will use for this first run at the OAuth2 workflow.
- "oauth2ClientId" - this is the value created in the Developer Key (screen shot above)
- "consumerKey" - this is the consuer key you assigned during the LTI install of your application
- "consumerSecret" - this is the shared secret you assigned during the LTI install of your application
Store these three variables in the web.config, see the associated source code for a reference.
Code Walk-thru
Using the sample project as an aide, I'll walk you through the first part of the OAuth2 workflow which is very straight forward. The sample project was created from the default ASP.NET MVC project template, and will use the default HomeController.
Note: The sample project was created with as few steps as possible, it is a simple MVC application with a single controller. This is not a recommended template for a production application, but only an attempt to provide a simple, clean easy to follow example. After following along with this example, I strongly recommend thinking through the steps, and building your own solution.
Home Controller
Using Visual Studio to view the source code you will find a single controller: HomeController.cs
If you browse to the default URL you will see the home page (https://your.domain.com) There is nothing fancy, basically the default home page that was generated by the MVC template with modified content and links. You can use this page to verify your web server is setup properly.
There are two additional methods associated with this example:
The OAauth2 Request Method: oauth2Request()
This is the method defined in the LTI XML above, the method that Canvas will use to execute the launch request. The LTI launch request must be a POST. If you would like to test this method you can use Postman to debug this method manually by making a POST calll to https://your.domain.com/home/oauth2Request
I have included helper classes that will handle LTI parameters received (oauthHelper.cs and ltiLaundhParams.cs), more importantly it will parse the LTI launch parameters and validate the OAuth signature. Step through the code if you would like to learn more about LTI launch parameters. A manual call from Postman will fail validation and return the result.cshtml view with an associated message.
With the debugger running, launch the app from Canvas and confirm that LTI validation is successful. Validation of the OAuth signature depends on the "consuerKey" and "consumerSecret" that you stored in the web.config. Looking at the constructor of oauthHelper.cs you will see where the "consuerSecret" is read from the config file and the OAuth signature is verified. Once the LTI parameters pass validation the response will be a redirect back to Canvas. In the browser you should see a prompt from Canvas asking the user to authorize access on behalf of the user.
By clicking "Authorize" you are prompting Canvas to redirect back to the application server, your web server, at the URL you defined when you created the Developer Key earlier: https://your.domain.com/home/oauth2Response
The OAuth2 Response Method: oauth2Response()
This is the method that Canvas will call if the user clicks the "Authorize" button, shown in the screen shot above. In the source code associated with this example, the web server will return a simple Success!! message to verify that the loop has been closed. Get this much of the application working and you have Step 1 working, and part of Step 2.
Quick Overview
- Create a Developer Key, pointing the redirect URL to your "oauth2Response" method
- Install your application in Canvas, directing the LTI launch URL to the "oauth2Request" method.
- Make sure your web.config has the three required parameters:
- oauth2ClientId
- consumerKey
- consumerSecret
- Launch the app from Canvas, confirm that the OAuth signature passes validation and you receive the "Authorize" option in the browser
- Click "Authorize" and confirm you receive the "Sucess!!" response in the browser
Summary
I felt this was a good place to start, enough to get things working without being too overwhelming. Getting this far you have verified that your dev environment is working properly, and that Canvas is properly configured. Next steps include requesting a user token and caching some values for reuse. If you don't have a database available there are many options:
- SQL Server 2016 Express Edition | Microsoft
- MySQL :: MySQL Community Downloads
- PostgreSQL: Downloads
I have Sql Server in my dev environment and will be using that for examples, but any database will do.
Part 2 will be posted as soon as I can make the time to get it down on "paper".
I am happy to try and answer any questions that come up, and happy to edit this post based on feedback.
Hopefully this will be useful to someone out there.
Part 2 and 3 of this example can be found here:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.