Invalid Authorization Header in grade passback using LTI 1.0

Jump to solution
Community Member

Hello all,

I'm trying to passback a grade using my tool into canvasLMS using LTI 1.0, but I'm getting "401 Unauthorized" "Invalid authorization header".

The grade passback is working correctly in moodle and blackboard, but not in canvasLMS and I can't figure out why. It's very frustrating.

Here's my nodejs code:


const consumerKey = 'contains_consumer_key';
const secretKey = 'contains_secret_key';
const requestURL = 'contains_request_url';
const bodyXML = `xml_with_the_imsx_POXEnvelopeRequest_format`;

var timestamp = Math.round( / 1000);
var params = {
  oauth_consumer_key: consumerKey,
  oauth_nonce: btoa(timestamp),
  oauth_signature_method: 'HMAC-SHA1',
  oauth_timestamp: timestamp,
  oauth_version: '1.0'
params.oauth_body_hash = crypto.createHash('sha1').update(bodyXML).digest('base64');
params.body_hash = encodeURIComponent(params.oauth_body_hash);
const signature = oauth.hmacsign('POST', requestURL, params, secretKey);
params.oauth_signature = encodeURIComponent(signature);
const authorization = `OAuth oauth_consumer_key="${params.oauth_consumer_key}",oauth_signature_method="${params.oauth_signature_method}",oauth_timestamp="${params.oauth_timestamp}",oauth_nonce="${params.oauth_nonce}",oauth_version="${params.oauth_version}",oauth_signature="${params.oauth_signature}",oauth_body_hash="${params.body_hash}"`;

const options = {
  timeout: 20000,
  uri: requestURL,
  method: 'POST',
  headers: {
    'Authorization': authorization,
    'Content-Type': 'application/octet-stream;charset=UTF-8',
    'Content-Length': Buffer.byteLength(bodyXML)
  body: bodyXML


I know there's a similar question here, but I didn't manage to make it work yet.

Hope somebody can help me,



Labels (2)
1 Solution
Community Member

Hello all,

I ended up finding that there were many things that were not accurate in my code, while reading the ims-lti code that deals with grade passback.

- the oauth_nonce formula "btoa(timestamp)" can add non-letter characters, so I ended up changing it to something random that only has letters and numbers;
- moved the URIencoding of the oauth_body_hash to after the signature generation;
- the consumer_key and oauth_nonce could need URIencoding, so I added it;
- the "Content-Type" header has to be set to "application/xml".


Everything seems to be working now. I hope this will help anybody.



View solution in original post