Step 3: Are all the required parameters present?

At this point, step 3, we know that the data passed in the message has come from a trusted source.  This does not, however, mean that all the data that a tool provider relies upon to make their service available to a user is present.  As seen in step 1, the LTI specification has very few required parameters; most are either recommended or just optional (though the 1EdTech certification process does place additional requirements on tool consumers).  This means that it is entirely possible for a valid message to be received which does not contain one or more parameters which a tool provider is needing.

At the outset, it should be said that tool providers are strongly recommended to make as few assumptions about the parameters received as possible; after all it is surely better to provide a customer with lower quality service than no service at all if some data is missing.  Having said that there will almost always be parameters which a tool provider needs before it can deliver a service to the user; for example, the user_id parameter is a common requirement so that you know which user is making the connection.  If this parameter is not included in the launch message it is quite legitimate to refuse (in a user-friendly manner) to accept the request.

Sample PHP Code

This sample code assumes that the tool provider needs to know who the user is (their ID) and whether they are a teacher or a student (their role).  Moreover, the only roles which are recognised are those of Instructor and Learner; in practice tool providers are encouraged to support a wider selection of roles which a tool consumer may support.  Note that this code is based on LTI 1 role names; for LTI 2 the role URIs should be used.

The $ok variable is carried over from Step 1 and should have a value of true at the start of this code segment.  After the code has been executed the variable will have been set to false if the message does not contain all the required parameters.

  // Check for a user ID
  $ok = $ok && !empty($_POST['user_id']);

  // Check for a role
  $ok = $ok && !empty($_POST['roles']);

  if ($ok) {
    // Check that the user is either a Learner or an Instructor
    $roles = parseRoles($_POST['roles']);
    $ok = in_array('urn:lti:role:ims/lis/Learner', $roles) || in_array('urn:lti:role:ims/lis/Instructor', $roles);

parseRoles function

Thus function converts the comma-separated list of roles received in an LTI launch message to an array of fully-qualified role names (Context-level roles are permitted to use a short form of their fully-qualified name).

  function parseRoles($rolesString) {

    $rolesArray = explode(',', $rolesString);
    $roles = array();
    foreach ($rolesArray as $role) {
      $role = trim($role);
      if (!empty($role)) {
        if (substr($role, 0, 4) !== 'urn:') {
          $role = "urn:lti:role:ims/lis/{$role}";
        $roles[] = $role;

    return array_unique($roles);


A Comment on Names of Users

It can be tempting to require a user's name to be passed in an LTI launch message.  However, this is personal data which some customers may be reluctant to provide.  So rather than rejecting a message which does not contain the user's name, an alternative strategy is to generate a name based on their ID.  For example, a user with an ID of abc001 could be assigned a name of User abc001.  If a customer finds these names unhelpful, then they have the option of changing their mind about passing the name across in their launch messages; refusing service would have made it more difficult for a customer to appreciate how this data is used by the tool provider so they can make a more informed decision.

The LTI specification includes three parameters for a user's name:

  • lis_person_name_given
  • lis_person_name_family
  • lis_person_name_full

A user's full name could be derived by concatenating their given and family names; similarly a user's given and family names could be generated by splitting their full name on space characters.  Thus, it should not be necessary to require all three parameters, or depend upon a name being passed in any particular way.  For example, the following function can be used to populate the three parameters with a value even if only some (or none) has been supplied.

    // Ensure all the user's name parameters are populated even if not all are passed
    if (!empty($_POST['lis_person_name_full'])) {
      $name = explode(' ', trim($_POST['lis_person_name_full']));
      if (count($name) < 1) {
        $name[] = 'User';
      if (count($name) < 2) {
        $name[] = $_POST['user_id'];
    } else {
      $name = array('User', $_POST['user_id']);
    if (empty($_POST['lis_person_name_given'])) {
      $_POST['lis_person_name_given'] = $name[0];
    if (empty($_POST['lis_person_name_family'])) {
      $_POST['lis_person_name_family'] = $name[count($name) - 1];
    if (empty($_POST['lis_person_name_full'])) {
      $_POST['lis_person_name_full'] = "{$_POST['lis_person_name_given']} {$_POST['lis_person_name_family']}";


Technical Activity: