Cvmcosta / ltijs

Turn your application into a fully integratable LTI 1.3 tool provider.
https://cvmcosta.github.io/ltijs/
Apache License 2.0
303 stars 70 forks source link

Deep Linking - Fails for Blackboard #237

Open tomitrescak opened 1 month ago

tomitrescak commented 1 month ago

This more of a questions. Igot everything working but Deep Linking.

For some reason, when I submit the deep lnked form, it generates "Tool (Invalid Link)" In Balckboard fro me that I cannot click on. Any idea what could be the issue?

{
  iss: "e1a9f302-6c64-4ecd-904b-5eddae93c10f",
  aud: "https://blackboard.com",
  nonce: "2067uke47q5vtlb6x3gzgj40i",
  "https://purl.imsglobal.org/spec/lti/claim/deployment_id": "6c97b9c2-35df-41ca-9ac9-b23xxxx26981",
  "https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingResponse",
  "https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
  "https://purl.imsglobal.org/spec/lti-dl/claim/msg": "Successfully Registered",
  "https://purl.imsglobal.org/spec/lti-dl/claim/data": "_48076_1::_9637154_1::-1::false::false::_1216_1::5eda69725xxxx26a94d29c1453be1a5d::false::false",
  "https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
    {
      type: "ltiResourceLink",
      title: "Ltijs Demo",
      custom: {
        cookoo: "resource2",
      },
    },
  ],
}

This is the jwt token generated by ltijs.

This is in Blckboard:

image

siddrcrelias commented 3 weeks ago

Hello, @tomitrescak is this solved...I was able to implement LTI in my org. and we even have customers using it on Avendoo and Moodle...let me know if you need help with this :)

tomitrescak commented 3 weeks ago

No, the deep linking is evading us. Linking of type “link” works but linking “ltitoollink” always leads to the “invalid link” above. I have no idea how to debug it. It seems like configuration issue or me not sending correct data. But it just does not work.

tomitrescak commented 3 weeks ago

Hello, @tomitrescak is this solved...I was able to implement LTI in my org. and we even have customers using it on Avendoo and Moodle...let me know if you need help with this :)

Are you using any custom parameters? Would you be so kind to show me screeshot of your blackboard config and the code for deep linking route? This is mine:

router.post("/deeplink", async (req, res) => {
  try {
    const resource = req.body;
    const items = [
      {
        type: "ltiResourceLink",
        title: "My Tool Link",
      },
    ];

    const form = await lti.DeepLinking.createDeepLinkingForm(
      res.locals.token,
      items,
      { message: "Successfully Registered" }
    );
    if (form) return res.send(form);
    return res.sendStatus(500);
  } catch (err) {
    console.log(err.message);
    return res.status(500).send(err.message);
  }
});
siddrcrelias commented 2 weeks ago

Hello @tomitrescak Sorry for seeing this message late, let me send you some links https://github.com/siddrc/ltijs-nestjs-server - this is the implementation that I am using at my company, some parts have been skipped but this should give you an idea on how to achieve onboarding various customers , doing deeplinking, assigning different tools to each customer and launching the deep linking UI interface

I also have a medium article on this, so that no one has to break their head on how to implement LTIv1.3 https://medium.com/@debu2in/implementing-ltiv1-3-using-ltijs-1ab38ab87567

I have a discord as well siddharthroyc_97017 , this will notify me on mobile..and I can help sooner...I would ask you to go through the code and the article, if the answer below does not help, or may be reach me out on discord.

Ok, so you are asking if I am using any custom parameters for deep-linking- I think not because the LMS stores the link to the tool provided by me, but when the course is launched by the LMS I get a kind of id from the LMS and I use it to launch the course.

For all my testing purposes I have used Moodle. For custom parameters, what I would do is may be call some endpoint to store those parameters somewhere just before the deeplinking request and retrieve them and use it when the course is launched -- dont know if this helps.. but may I ask why do you need custom parameters.

siddrcrelias commented 2 weeks ago

Here are some screenshots for Deeplinking, On Moodle/LMS what we do is we create a course shell, with minimal data and then link our content to it image

upon clicking Select Content we show a UI which has like checkboxes and shows courses and the submit button

image

image

submitDeeplinkRequest image

On the Server

@Post()
  async deeplink(
    @Req() req: Request,
    @Res() res: Response,
    @Body() deeplinkDto: DeepLinkingDto,
  ) {
    try {
      if (
        Array.isArray(deeplinkDto.courses) &&
        deeplinkDto.courses.length > 0
      ) {
        const token = res.locals.token as Token;
        const deepLinkedCourses = deeplinkDto.courses.map((course) => {
          return {
            type: 'ltiResourceLink',
            title: course.courseName,
            custom: {
              name: course.courseName,
              value: course.courseId,
            },
          };
        });
        const deepLinkingMessage =
          await lti.DeepLinking.createDeepLinkingMessage(
            token,
            deepLinkedCourses,
            { message: 'Successfully Registered' },
          );
        const responseJson = {
          deepLinkingMessage,
          lmsEndpoint:
            token.platformContext.deepLinkingSettings.deep_link_return_url,
        };
        if (deepLinkingMessage) res.send(responseJson);
        else throw new Error('No Deep Linking Message created.');
      } else throw new Error('No Courses selected for deep linking.');
    } catch (err) {
      console.log(`${err.message} - ${err.stack}`);
      res.status(500).send(err.message);
    }
  }

We make a JSON message using lti.DeepLinking.createDeepLinkingMessage and return back to the deep linking ui component. Finally, then my deep linking UI component submits it to the LMS and voila!

image

tomitrescak commented 2 weeks ago

Hello, this is very helpful and amazing article! I have a couple of questions:

Thanks a lot

siddrcrelias commented 2 weeks ago

Custom Parameters I did not use but I think this is something like key value pair seperated with a ; or a & or something - this again might be LMS dependent, because I remember seeing some websites on the internet mentioning this since deep linking request originates from the LMS ( essentially from its LTI deeplinking module ) first then send it out to the deeplinking URL I remember seeing something like KEY1=VALUE&KEY2=VALUE2 , I don't know I am just shooting in the dark there. I presume since it says custom, it should work in a simple intuitive way.

Here is the screenshot of my config for your reference Screenshot 2024-10-24 at 15 22 17

Screenshot 2024-10-24 at 15 17 01

..also thanks for the first point highlight..I will try it out...