External Site Login

cesbrandt
Community Champion


Alright, so let me explain the scenario. I'm looking to make legitimately configured student accounts available to authorized users without needing to provide login credentials for a whole new account or provide masquerade rights.

In and of itself, this isn't a difficult task:

  1. I setup a series of test accounts whose credentials are stored on our system.
  2. Using our own authentication method, validate that a user is authorized access to these accounts.
  3. Find the first set of credentials found to be available (3-hour time limit) and use JavaScript to submit a HTML form with the designated credentials to sign the user into Canvas as that student account.
  4. Log the time the account was signed in to enforce the 3-hour time limit.

There are two primary concerns to this solution:

  1. For browsers that have JavaScript disabled, this won't work due to the form not submitting.
    • Solution: Add a button for the user to submit the form.
  2. For browsers that have JavaScript disabled, the account credentials will be available to the user.
    • Pseudo-Solution: Make all fields hidden.
      • Issue: This only hides the data, visibly, it can still be retrieved by anyone accessing the source or Developer Tools. Though users that would have this opportunity would be authorized access to the accounts, the intent is to avoid supplying credentials to ensure no single user decides to "seize" a particular account and start stepping on toes.

Ideally, JavaScript should be avoided and the credentials of the account they'll be logged into never be passed to the client. This means the solution needs to be through a server-side language. My go-to language is PHP, so that's what I did. My solution works, for non-Canvas.

<?php

  $domain = 'canvas.instructure.com';

  $credentials = array(

    array(

      'user' => 'tstudent1',

      'pass' => 'P@ssw0rd'

    )

  );

  $ch = curl_init('https://' . $domain . '/login/canvas');

  curl_setopt($ch, CURLOPT_POST, 1);

  curl_setopt($ch, CURLOPT_POSTFIELDS, urldecode(http_build_query(array(

    'pseudonym_session' => array(

      'unique_id' => $credentials[0]['user'],

      'password' => $credentials[0]['pass'],

      'remember_me' => 0

    )

  ))));

  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

  curl_setopt($ch, CURLOPT_HEADER, false);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $results = curl_exec($ch);

  curl_close($ch);

?>

Note: The actual code is more complex to accommodate authentication, multiple sets of credentials, and determine which sets are available for use. However, this simplified code has the same issue.

If I point this cURL to a login system on one of my servers, it works, no problem. It submits the credentials to the same target as using a HTML form and when I access the actual site, it's logged me in with the designated credentials.

With Canvas, I get nothing but a 400 Bad Request. I've added the source domain to the list of Trusted HTTP Referers and confirmed the JavaScript-based solution works.

Does anyone have ideas on what I am missing?