Skip navigation
All Places > Canvas Developers > Blog > 2016 > November
2016

I have been encouraged to make the contents of my sandbox more visible, it can be found at https://kth.instructure.com/courses/11  One of my goals has been to be able to use software to interact with Canvas, rather than being limited to cut and paste with RCE. Another of my goals has been to use programs to move content out of various systems that we are currently using and into Canvas. Another goal has been to move content in the other direction to other external systems.

My sandbox contains a lot of examples of things that I have been experimenting with, including computing readability statistics for the page of a course, adding citations to pages (via Zotero) using an RCE buttom to call on an LTI tool provider [a work in progress], and today's exporting of a spreadsheet of all assignments for a course (using Python's Pandas). I'm eager for feedback and opinions on this material.

What is this about?

When I first started learning Canvas, I thought it was very convenient that I could create a new user and Canvas would automatically send an invitation to the new user with a link to the login page.  What a great feature!

 

Once the decision was made to get on board, I started working on integration with the SIS, and quickly learned that when you import new users into Canvas, the SIS import process does NOT send out invitations, and no default passwords are assigned.  So how were we going to notify new users that their account had been created?  We came up with our own automated workflow process to watch for useres who had not yet been created in Canvas, and import those users with a temporary password.

 

At first, we were importing the passwords in clear text.  Canvas later announced that the import would accept an encrypted password, which is a much more secure format, and I began working on adding this functionality to our existing workflow service.

 

I will share a .NET project that includes a class that will encrypt and verify signatures in the format recognized by Canvas.  If you are using .NET and interested in encrypting your passwords, you should be able to implement this class in your projects.  This class is applicable beyond Canvas user passwords to encrypt data in general and may be useful in other ways.

 

Why am I generating passwords anyway?

I am working with an institution that does not have a single-sign-on solution implemented.  We are depending on the built-in Canvas login to gain access to the platform.

 

References

There are a few basics that would help to understand when working with the associated project:

 

What I Learned...

When putting my class together, I used other references and examples, which are documented in the code.

The ComputeHash() method returns an array of 20 bytes, every time.

This is standard in each example I worked through, but it wasn't working for Canvas.

This was created some time ago, but I would like to thank Trevor Fullwood for pointing answering questions at the time and directing me to the Python script.  Working my way through that script helped me identify a step that I was leaving out: converting the 20 byte array to a 40 byte array.

 

In my class clsPasswordGen, you will see two versions of the methods to generate and validate the hashed password:

  • generateSaltedPassword() and complimentary verifySaltedPassword()
  • generateCanvasSaltedPassword() and compliment verifyCanvasSaltedPassword()

You will see an extra step in the Canvas method:  ToHexString(), this is where the 20 byte array is converted to a 40 byte array.

 

Using the test app associated with this post to hash the password "helloWorld", a standard SSHA hash will generate something like this:

  • wdMNf/KsDEWhF4s8NPtiQtb/AvZBaGZ5

Hashing the same password for Canvas compatibility will generate something similar, but of greater length, like this:

  • ZjY4OTg3M2MyOTkxYWQ3YzI1ZmQ0N2U1ZmI1NzhlMGM5OGIzOWMyMXBITE0=

 

The test app will output both versions of the result.

Attached to this post is a sample user import file, "user-password-import-test.csv", with the password listed above (helloWorld).  Import the file to your test environment and login with the password "helloWorld", and it will work.  Then generate your own password, update the import file and try again to validate your generated password hash works.

 

How to use the test app

Download the source code from BitBucket here:  sshaPasswordGen source code

Compile the code and run the executable from the command line.

You will be prompted to select an encryption algorithm (you want option 1 for Canvas: SHA1).

You will be prompted to type in the password to encrypt.

The results will be displayed.

 

 

This is a very simple test app to demonstrate how to implement the encryption class.

You will notice there are several encryption algorithms implemented, I left them in place for demo and testing purposes.

This encryption class can be used for purposes other than Canvas passwords.

What is this about?

If you are a .NET developer and are interested in leveraging the Canvas API to automate tasks at your institution, you might be interested in ths demo project.  I will provide a Visual Studio project that you can download and use as starting point to develop your own tools.

 

References

I can try to guide you to some reference material for those getting started that will hopefully help.

There are a few basics that would help to understand when working with the associated project:

 

How does it work?

The associated source code will create a command line tool that accepts a config file.  The config file contains the following information:

  • "accessToken" - your access token
  • "apiUrl" - the url to your Canvas site, I would you Beta or Test
  • "apiCalls" - array of API calls that you would like to run, including parameters

 

For simplicity and purposes of demo, the access token and API url are in this config file.

 

The format of the API call list is an array of pipe delimited strings in the following format:

  • [method name] | [param1],[value1] | [param2],[value2] | .... | [param(n)],[value(n)]

These strings will be parsed and passed to the API library where they will be converted into actual calls to the Canvas API, at the site defined by the "apiUrl" variable.

 

This sample config includes GET, POST, and PUT calls, to demonstrate each type of verb.

Each verb is implemented in the base class: clsHttpMethods.cs

 

Full response details are logged by NLog.  Grab these responses and inspect them for full details.  If your test produces an error or throws an exception, full details can also be found in the log file.  If you use my default nlog.config, log files will be found in this location:  c:\\logs\canvasApiTest\*.log

 

Comments

The purpose of this project is not to replace tools like Postman, the purpose is to help other developers using .NET to get started with the API.  I tried to keep things as clear as possible.

 

With myapi.config, I have been able to test any API call I have needed to date.  If you follow my code, you will need to add a C# method to handle each additional API call you want to make.  My "long hand" approach to creating matching C# methods could be modified, but hopefully helps to illustrate the concepts.  Share your approaches.

 

There is plenty of room for optimization, optimize to meet your needs and share any enhancements you feel people could benefit from.

 

Project Source Code

Source code can be found on BitBucket here:  Canvas API Implementation

The source published on BitBucket compiles and runs with Visual Studio 2015 and .NET Framework 4.5.2

 

IMPORTANT:  Make sure you edit the myapi.config file with your settings, and modify API variable values to match your environment.

 

All code is provided as-is for demonstration purposes only.

 

2016.12.03 - UPDATE - File Upload via POST

  • I have added a class that walks through the steps of uploading a file.  This code was pulled from another project and put together quickly as a response to a community question, make sure you test failure scenarios in your environment.

The Challenge

This initiative was brought about due to the fact that many of our students, and some of our instructors, have erroneously logged in to Canvas in an incompatible browser. While many receive the notification that Instructure has provided, some are still confused about what a browser is, or which one they should use.

 

Solution

I wanted the solution to provide the user with the following information:

  1. The name and version of the current browser that is being used
  2. Additional information related to that browser
  3. Canvas' list of compatible browsers
  4. Canvas' list of system requirements

 

For this solution, I created a fixed container that is appended to the <body> element use jQuery, and that is displayed on the user dashboard when a user first logs in to Canvas. This container provides the user with basic information related to the current browser in use, and the user can also gain additional information by clicking on links included in the container (addresses solutions points 2-4). Furthermore, to prevent the container from obscuring any containers behind it, I have included a close button that the user can click, which closes the container by sliding it out of view.

 

Demo

 

Repository

If you are interested in applying this to your environment, please feel free to fork or download from my Bitbucket repository, which can be found here. If you previously downloaded this package, please be sure to download the most updated version from the repo to ensure that the code will work as intended.

 

[UPDATE]: With the renewed interest in this repository, I wanted to give you a live demo of it in action. You can find a slightly modified version of it (with comments) on JSFiddle.

 

[UPDATE 2]: Instructure modified the html for their Dashboard page. Previously, in the <title> tag of the page, the text "User Dashboard" was present. Now the text has been updated to "Dashboard." I have modified the file in the repository to match this. I have also updated the JSFiddle to match.