ColdFusion and Oauth Signature validation

989 views
Skip to first unread message

s8loud

unread,
Oct 23, 2013, 3:33:01 AM10/23/13
to canvas-l...@googlegroups.com
I'm trying to wrap my head around what needs to happen to validate the Oauth signature during the Oauth handshake process surrounding my application launch from within Canvas, however it appears as though I'm just not "getting it."  I've gone up to Lesson 3 on LTI Activity 2: Signature Verification and it's not exactly clear on how to actually generate the signature; the most it says is that I should have found a library to do it for me.  I've found the ColdFusion Oauth library on Riaforge, though I'm not sure how to apply it to my purposes here with Canvas.

Any pseudo-code or examples would be appreciated.

Thanks in advance.

- Gerald

Chris Herdt

unread,
Oct 23, 2013, 9:42:02 AM10/23/13
to canvas-l...@googlegroups.com
Gerald, I've struggled with this too. I think for the app I am working on, all I really need is signature validation but I haven't gotten it to work yet using ColdFusion (although it works fine in PHP).

One of the better OAuth resources I found was from Twitter:
https://dev.twitter.com/docs/auth/creating-signature

Definitely interested in hearing more about your progress. I'll see if I can pull together some of the resources I have so far to share with you & the list.




--
 
---
You received this message because you are subscribed to the Google Groups "Canvas LMS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to canvas-lms-use...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Chris Herdt
Web Applications Developer
267-603-1066 (home)
734-754-3585 (cell)
http://osric.com/chris/

Christopher Bennell

unread,
Oct 25, 2013, 10:59:38 AM10/25/13
to canvas-l...@googlegroups.com
Here's an example of verifying the signature in PHP. You might have to dig into the Zend Framework classes to see the actual implementation, but it may help illustrate the process. 

Gerald Harper, Jr.

unread,
Nov 1, 2013, 2:07:08 AM11/1/13
to canvas-l...@googlegroups.com
Thanks, Chris.  That link was helpful.  I've also referenced

http://www.delbridge.org/post.cfm/tackling-twitter-s-oauth-with-coldfusion

to get me going and I seem to have a functional process for calculating the signature.  However, what I am stuck on is getting my signature calculation to match what Canvas is POSTing to my launch URL (e.g., the oauth_signature parameter).  I have verified that my code is performing the calculation correctly (using this and this), so I believe the issue to be in the parameters I am passing to my signature calculation method, particularly the signature base string.

Is there a way I can confirm I am using the correct signature base string?

Also, isn't the signing message just "[shared_secret]&[empty string]" (no quotes/brackets)?

Thanks.

- Gerald

Gerald Harper, Jr.

unread,
Nov 1, 2013, 2:19:43 AM11/1/13
to canvas-l...@googlegroups.com
Thanks, Christopher.

I know almost nothing about PHP, but after creating my own process I now see that what I've done is very similar to what you posted, so thanks for the validation.
--

Steve

unread,
Nov 16, 2013, 1:21:48 AM11/16/13
to canvas-l...@googlegroups.com
Gerald,
I wanted to jump in here and note that I've spent about two work days now trying to get a calculation of the signature to match what Canvas creates and puts in its parameters list when it calls my external tool. I've sent a note over to one of the Instructure contacts to ask how they build their signature base string (verifying no use of tokens, verifying version 1.0, verifying whether my url is modified at all). Just for background, I created the external tool link in Canvas, and supplied the URL that it calls out to, as well as the consumer key and secret. There are no tokens involved because this is a "one-way" event. I'm not passing anything back into Canvas but I do want to verify the authenticity of the page call from within my website. 

I am looking at the parameters passed into my page from Canvas, including the nonce value, timestamp, oauth_version (1.0), and oauth_signature_method (HMAC-SHA1). I've set up a page to help me quickly permutate through various combinations of what Canvas may or may not be supplying for the base string, to no avail.  I should be able to recreate the matching string from a combination of what's supplied by Canvas in the call (nonce, timestamp, oauth_version, oauth_signature_method) and the url that the page is at.  I've used two different sources of vb.net code, as well as two third party sites such as http://oauth.googlecode.com/svn/code/javascript/example/signature.html which allow you to type in the parameters. I'm assuming that the url that they feed into the string is the exact url to my site that I supply when I create the external tool from within Canvas. I'm also assuming that according to the LTI spec that it's a POST although I've tried everything else in various combinations.

Is anyone out there who can supply me with a reverse-engineered list of how Canvas builds its base string when creating a signature for an external tool when there's no tokens involved? Also Gerald, according to what I've read of the specification, the signing message would be "[shared secret]&" if there is no token secret being used, so I agree with that. I've also tried no ampersand as well. The specification asks that the parameters be ordered alphabetically. Done that. Normalization of url and parameters: done that. HTML encoding: done. 
Thanks in advance to anyone who can provide that algorithm that Canvas uses to generate the base string. I tried to find it on github but couldn't find it easily.
Steve

Brad Humphrey

unread,
Nov 18, 2013, 1:12:17 PM11/18/13
to canvas-l...@googlegroups.com
I just sent a message about this on another thread (https://groups.google.com/forum/?fromgroups#!topic/canvas-lms-users/2V3kDfpOaNw), but I figured it would be worth it to mention here too.

The short version of the message is that there is a beta tool for testing signatures that can be installed using this config XML: https://lti-tool-provider.herokuapp.com/tool_config.xml?signature_proxy_test=1.  The source code for this tool is here: https://github.com/instructure/lti_tool_provider_example.  Let me know if you notice any problems with it.





       

Steve Brown

unread,
Nov 18, 2013, 1:47:39 PM11/18/13
to canvas-l...@googlegroups.com
Hi Brad,
Thanks for posting the link. I'm coding your ordering of parameters for the base string now, and will let you know if I can't match the signature with my code. It looks like Canvas is rolling pretty much all the page parameters into the basestring, which is fine - I just need to know what they are and what order.  I was spinning my wheels without this template, as I couldn't match signatures via a standard oauth template with about 4 parameters, and didn't match the LTI template because of mainly the presence of the custom_canvas_... etc. parameters. Thanks for not adding the button code like the LTI v1p0 spec did. That was a strange addition.
Steve


--
 
---
You received this message because you are subscribed to a topic in the Google Groups "Canvas LMS Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/canvas-lms-users/iLdnrBiYuEE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to canvas-lms-use...@googlegroups.com.

Steve Brown

unread,
Nov 18, 2013, 5:00:36 PM11/18/13
to canvas-l...@googlegroups.com
Brad:
Check your encoding for the user_image parameter. The URL is getting an extra "25". Look near https://canvas.instructure.com just after the avatar string. You'll see:
https%25253A%25252F%25252Fcanvas.instructure.com%25252Fimages%25252Fmessages%25252Favatar-50.png
Steve

Steve Brown

unread,
Nov 18, 2013, 5:10:16 PM11/18/13
to canvas-l...@googlegroups.com
Supplemental: I see that the parameter string for the user_image has pre-encoded characters:

......https%3A%2F%2Fcanvas.instructure.com%2Fimages%2Fmessages%2Favatar-50.png

Wouldn't you replace the percent rather than changing %3A to %25253A?
Steve

Steve Brown

unread,
Nov 18, 2013, 9:02:31 PM11/18/13
to canvas-l...@googlegroups.com
Brad, 
Success!
I was able to match your template and generate the matching oAuth signature. The solution (after matching up your template) was to do a Uri.EscapeDataString() on each parameter (I'm doing this in .NET) making up the base string excluding the initial url, then apply the same function again. This way, the "&" between the parameters in the basestring is only escaped once.

Thanks for supplying the URL for the test tool. It would have been very difficult to figure this out without it, and impossible without the parameter ordering template which it also provides. 
Steve

Brad Humphrey

unread,
Nov 20, 2013, 11:40:27 AM11/20/13
to canvas-l...@googlegroups.com
I am glad it was helpful.  After going though the troubleshooting process, did you find that there was anything we need to change about it?


       


Steve Brown

unread,
Nov 20, 2013, 12:32:57 PM11/20/13
to canvas-l...@googlegroups.com
Hi Brad,
The tool helped me and was indispensable, as it provided the actual basestring. Nothing to change with it, but the steps to make an external tool call successful would be augmented by these notes:
1. Make the diagnostic page URL findable, particularly in your external tools info page. 
2. Add a note that ampersands between the parameters are single-escaped, and the parameters themselves are double-escaped, making a space become %2520, and pre-escaped characters are triple-escaped, as would happen with the URL appearing in the user_image parameter (making https:// become https%25253A%25252F%25252F)
3. This is not your responsibility but it helped me to use MS Word's document compare feature. There are so many parameters being used in creating the basestring that this helps the debugging a lot.
Steve 

Steve Brown

unread,
Nov 21, 2013, 8:53:32 PM11/21/13
to canvas-l...@googlegroups.com
Hi Brad,
I'm not getting an oAuth signature match when I invoke the external tool in some circumstances. In using your analysis page, I see that the basestring doesn't double-encode all the non-alphanumeric characters like it recently did, and to which I tuned my logic. For example:
I now see:
launch_presentation_height%3D400 
whereas I had seen:
launch_presentation_height%253D400.

I'll try to post as soon as I can get a fix on what the general circumstances are, but I noticed it when I logged in as a student, and also as an admin who isn't a teacher of a course that has the external tool link.
Steve

Steve Brown

unread,
Nov 23, 2013, 2:04:31 PM11/23/13
to canvas-l...@googlegroups.com
HI Brad,
Following up with the non-match: I was able to reproduce the issue and found that your LTI signature verifier reproduced my signature (from my oAuth functions) but not yours (sent as a parameter to my external tool page) under the reproducible circumstance. 

This authenticates: Install a tool as a course level external tool for learners, while I'm logged in as administrator, and call the tool while still logged in as administrator.

This fails: Log in as a learner and call the tool from the course. There is either a.) a discrepancy with Canvas' signature generation when a learner calls the tool, or b.) the same discrepancy both in my logic and your LTI siguature verifier, because they both agree on what the signature should be.

I've compared the parameters sent to my external tool page. One thing I notice when I'm a learner is that there is an additional parameter passed in:
lis_person_sourcedid: 123456
This parameter does not appear for the admnistrator, nor does it appear in the LTI signature verifier. If I have more time today, I'll add that as a parameter to my code, and see if it matches your signature. If you can't reproduce this issue, then email me privately and I'll provide you with the location of the site page and a login.

tnx
Steve


Steve Brown

unread,
Nov 23, 2013, 2:25:56 PM11/23/13
to canvas-l...@googlegroups.com
Update: I just added the parameter lis_person_sourcedid to the basestring (in the appropriate alphabetical order) and got a successful signature match. So my suggestion b.) above appears to be the issue: The list_person_sourcedid parameter needs to be added to the basestring if it exists, and your LTI signature verifier needs to include this as an option, and account for the lack of that parameter (ie, don't add it) when it generates a basestring. It's possible that the LTI verifier tool already would display this parameter if it exists, but I haven't tested it being called by a learner. 

Brad Humphrey

unread,
Nov 25, 2013, 5:03:15 PM11/25/13
to canvas-l...@googlegroups.com
Steve, 

I am unable to reproduce the signature mismatch, but I can comment on the lis_person_sourcedid parameter.  The lis_person_sourcedid maps to the sis user id for the current user.  This can be found by going to /accounts/self/users/:user_id and looking at the login(s) for that user.  The reason it was showing up for a learner but not an admin in your case is probably just because one had an assigned sis id and the other did not.  That being said, when I launched the verifier for a user without an sis id, the field was not included, and when I launched it for a user with an sis id the field was included, as I would expect.  Do you have any ideas what else I might need to do to reproduce the problem?




       


Steve Brown

unread,
Nov 25, 2013, 5:10:03 PM11/25/13
to canvas-l...@googlegroups.com
Hi Brad,
I think we're saying the same thing coming from different starting points and I'm adapting my code. 
What I labeled as a reproducible problem (the lis_person_sourcedid not appearing as a parameter) is according to Canvas' signature generation logic not a problem because it's not a parameter to begin with for some users. I had assumed that your LTI test page was static in the field count that it generates, rather than dynamic, based on user type. Since I was testing my signature generator as a non-student, I never saw that other parameter. 
Steve

Rich V

unread,
Jan 8, 2014, 4:31:10 PM1/8/14
to canvas-l...@googlegroups.com, cogn...@gmail.com, dled...@wiley.com
Hi Steve-

First off, thanks to everybody who contributed to this forum; it has been a very helpful read.

My dev team has encountered the last issue exactly: we implemented the Uri.EscapeDataString() solution but then began having problems dynamically discovering parameters and calculating the oauth_signature when "unexpected" parameters were included in an LTI launch.

Would it be possible to share the final solution encompassing the Uri.EscapeDataString() implementation + support for dynamic discovery and counting of the parameters/fields just-in-time?

Any insights you can lend would be hugely appreciated!

Best regards,

Rich Virginia

Michelle Lawrence

unread,
Mar 6, 2014, 12:39:21 PM3/6/14
to canvas-l...@googlegroups.com, cogn...@gmail.com, dled...@wiley.com
Hi guys,

So I'm still really new to coding and am having a lot of trouble working through the LTI Activity 2: Signature Verification module. Could anyone give me a super dumbed-down version of how to use an OAuth library for signature verification?

Thanks much,

Michelle Lawrence

Becky Kinney

unread,
Mar 6, 2014, 12:57:50 PM3/6/14
to canvas-l...@googlegroups.com
Michelle,
What library are you using? If you are working in php, I can help.

Becky Kinney
Academic Technology Services

Michelle Lawrence

unread,
Mar 6, 2014, 1:04:10 PM3/6/14
to canvas-l...@googlegroups.com
Right now I'm pretty language-agnostic. :P I was trying to implement one in Ruby but PHP is great!

Becky Kinney

unread,
Mar 6, 2014, 1:32:20 PM3/6/14
to canvas-l...@googlegroups.com
Ok, then, here we go. The first thing is to grab the library. I actually had a hard time finding it at github, but here is a direct link to the zip http://ims-dev.googlecode.com/svn/trunk/basiclti/php-simple/dist.zip

There is way more than just the library in there, so spend some time looking it over. Dr. Chuck has done a nice job making this as easy as possible.

Once you know your way around, pretty much all you have to do is mount the entire contents of the zip on a secure server, and then point your LTI link at the tool.php page. The tool.php assumes an LTI secret of 'secret' so you will have to edit it to make sure that your secrets match. Dr. Chuck takes care of almost everything else. The only gotcha is the nonce, which this library pretty much ignores. You will have to come up with a way to be sure nonce's are not being reused. The spot you will need to modify is in the file named TrivialOAuthDataStore.php. 

Write back when/if you get stuck.

Becky Kinney
Academic Technology Services


Michelle Lawrence

unread,
Mar 18, 2014, 12:32:28 PM3/18/14
to canvas-l...@googlegroups.com
Thanks Becky. 

Obviously *very* new to all this. How do I "mount" the files on a secure server?

Thanks,

Michelle

Becky Kinney

unread,
Mar 18, 2014, 1:26:41 PM3/18/14
to canvas-l...@googlegroups.com
Michelle,
You may need more help than I can offer. A secure server is a web hosting location with an https:// url. That means anything that leaves or enters the server is encrypted so that hackers can't see it. When you make an online purchase using a credit card, your card info could be stolen if the server you are sending the number to isn't secure.

So, if you have access to a secure server, and you know how to ftp the files onto the server, that is a start. If you don't have access to a secure server, or you don't know what ftp is, I think you have bitten off more than you can hope to chew.
Becky

Becky Kinney
Academic Technology Services


For more options, visit https://groups.google.com/d/optout.

Michelle Lawrence

unread,
Apr 8, 2014, 1:29:38 PM4/8/14
to canvas-l...@googlegroups.com
Hi Becky,

Thanks for the advice. I got some help from a closer source and am back with a more informed perspective.  

When you say to edit tool.php to make sure the secrets match, are you just replacing "secret" in the following line:

$context = new BLTI("secret", false, false);

with whatever secret Canvas gives us, or do we edit in another place. I just keep getting a "could not establish context" when running through Canvas even after replacing the secret.

Thanks,

Michelle

Becky Kinney

unread,
Apr 8, 2014, 9:44:46 PM4/8/14
to canvas-l...@googlegroups.com
Michelle,

The secret in that line of code has to match the secret in the app configuration you see in Canvas Settings>App Center>New App.

Becky
For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to the Google Groups "Canvas LMS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to canvas-lms-use...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

Michelle Lawrence

unread,
Apr 10, 2014, 1:18:31 PM4/10/14
to canvas-l...@googlegroups.com
Thanks! 

I created a new tool in the app center and got tool.php running properly within the course context, but I'm still a little confused on how it all connects/fits into the LTI learning modules. Are they self contained or do they relate to our created course and the tools that are connected to it somehow?

Really appreciate all the help. :)

-Michelle
To unsubscribe from this group and stop receiving emails from it, send an email to canvas-lms-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Becky Kinney

unread,
Apr 11, 2014, 10:59:35 AM4/11/14
to canvas-l...@googlegroups.com
Where are you creating your learning modules? You can use an LTI assignment as a page within a Canvas module, or you can create entire modules outside of Canvas, and deploy them as LTI assignments. Which one are you interested in doing?

Becky Kinney
Academic Technology Services


To unsubscribe from this group and stop receiving emails from it, send an email to canvas-lms-use...@googlegroups.com.

Adam Blomeke

unread,
Aug 3, 2015, 4:09:28 PM8/3/15
to Canvas LMS Users, geraldh...@gmail.com
Gerald,

I am curious if you ever resolved this.  I'm working on Integrating an app in Canvas, and need to do the same thing, namely to validate a post request from Canvas before I log someone into my ColdFusion app.  If you have would you be wiling to post the code for it?

Thanks,
Adam Blomeke
Reply all
Reply to author
Forward
0 new messages