LTI 1.3 + OIDC with Anthology: End-to-End SSO Integration Guide

Introduction

This article explains a real example of the SSO flow from Anthology Blackboard to a Custom Learning Tool (BonuspointLearningTool.sg). The SSO flow follows OpenID Connect using JWT. The same pattern can be applied to any Custom Learning Tool that is SSO-integrated with Blackboard.

For security, sensitive encoded strings and key values are masked while preserving original length.


0) Entry and callback URLs in this flow

  • BonuspointLearningTool OIDC login entry:
  • https://api.learningtool.bonuspoint.info/lti/oidc/login
  • BonuspointLearningTool frontend callback:
  • https://learningtool.bonuspoint.info/sso-callback?token=<BonuspointLearningToolSessionToken>

These two are in different stages:
/lti/oidc/login is LMS-to-tool OIDC initiation
/sso-callback?token=... is tool backend redirect to frontend after launch verification


1) Token structure and cryptography clarification

Original point kept: “token has 3 parts separated by dot (.)” — correct.

For a JWT:
– Part 1: header
– Part 2: payload
– Part 3: signature

Important correction:
– These parts are Base64URL encoded (not standard Base64 wording in strict JWT terms).
– Signature segment is also Base64URL text of signature bytes.

Example session token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImRvbmd6aGkueWFuZ0Bib251c3BvaW50LmluZm8iLCJyb2xlIjoiYWRtaW4iLCJpZCI6IjY5NTdiOGY5NTRmOGQ0MDA0NjhlYmU1OSIsInNjaG9vbElkIjoiNjkyZDk0YzllYmEyZDgwMDE5YmY0NjliIiwiY291cnNlSWQiOiI2OTU3YjA1M2E0MWVkZjAwNDc4MjQ1NzciLCJjb3Vyc2VOYW1lIjoiTklFX1RFU1RfQVBQTE******************************************************************************************************************************

Decoded header:
{"alg":"HS256","typ":"JWT"}

Decoded payload:
{"email":"dongzhi.yang@bonuspoint.info","role":"admin","id":"6957b8f954f8d400468ebe59","schoolId":"692d94c9eba2d80019bf469b","courseId":"6957b053a41edf0047824577","courseName":"NIE_TEST_APPLETREE","time":1772912607514,"iat":1772912607,"exp":1773344607}

Signature math

For HS256 token signing:

signature = HMACSHA256(base64url(header) + "." + base64url(payload), secret)

Then JWT stores base64url(signature) as segment 3.


2) Two JWT contexts in this integration

A) Platform launch id_token (Blackboard/Anthology -> BonuspointLearningTool)

  • Verified by BonuspointLearningTool backend using platform JWKS public keys
  • RS256 verification flow in code path
  • Validation includes issuer, audience, nonce, expiry, etc.

B) BonuspointLearningTool app session token (BonuspointLearningTool backend -> frontend/API)

  • Generated by BonuspointLearningTool backend using session secret (helpers/jwt.js)
  • Verified by BonuspointLearningTool backend on API requests (middlewares/authentication.js)
  • This is issuer-and-verifier both BonuspointLearningTool (shared secret model)

Original point kept and corrected:
– This is different from RS256/ES256 asymmetric verification.
– Verification is signature checking, not decryption.


3) Credential mapping

  • LTI_CLIENT_ID = Application ID
  • ANTHOLOGY_APPLICATION_KEY = Application Key
  • ANTHOLOGY_APPLICATION_SECRET = LTI_CLIENT_SECRET = Application Secret

Values currently listed in original source:
– Application ID: 68c75d43-9477-4060-8750-3***********
– Application Key: 691c7d94-09a2-4714-9329-6***********
– Secret: EOU9tV95HjgBZkMWwUubeH**********

Security note:
– Keep these in secret storage/env vars; avoid public publication.


4) End-to-End SSO Sequence

Step 1 — User clicks tool in Blackboard

  • Browser opens Blackboard tool link (launch link / placement page context)
  • Blackboard prepares LTI launch context

Step 2 — Blackboard calls BonuspointLearningTool OIDC login endpoint

  • Request to:
  • https://api.learningtool.bonuspoint.info/lti/oidc/login
  • Blackboard provides parameters such as:
  • iss
  • client_id
  • login_hint
  • lti_message_hint
  • target_link_uri
  • lti_deployment_id

Step 3 — BonuspointLearningTool backend validates and creates temporary launch session

  • Validates issuer and client id against configured values
  • Generates:
  • state
  • nonce
  • Stores state/nonce in temporary LTI session storage

Step 4 — BonuspointLearningTool redirects browser to Anthology OIDC auth endpoint

  • 302 redirect to:
  • https://developer.anthology.com/api/v1/gateway/oidcauth
  • Includes:
  • response_type=id_token
  • scope=openid
  • response_mode=form_post
  • client_id
  • redirect_uri=https://api.learningtool.bonuspoint.info/lti/oidc/launch
  • state
  • nonce
  • prompt=none
  • forwarded login_hint
  • forwarded lti_message_hint (if present)

Step 5 — Anthology/Blackboard returns launch result to BonuspointLearningTool

  • Browser receives an auto-submitting form (response_mode=form_post)
  • POST to:
  • https://api.learningtool.bonuspoint.info/lti/oidc/launch
  • Form fields include:
  • id_token
  • state

Step 6 — BonuspointLearningTool verifies platform id_token

  • Decodes token header, reads kid
  • Gets platform keys from JWKS endpoint:
  • https://developer.anthology.com/.well-known/jwks.json
  • Selects matching key by kid
  • Verifies RS256 signature and validates claims (iss, aud, nonce, expiry)

Step 7 — BonuspointLearningTool user/course processing and sync

  • Finds/creates user
  • Updates LTI context
  • Finds/creates class/course mapping
  • If needed, calls Blackboard token endpoint for API-based membership sync:
  • https://ntulearntst.ntu.edu.sg/learn/api/public/v1/oauth2/token
  • Uses application key + secret for that server-to-server API token

Step 8 — BonuspointLearningTool generates BonuspointLearningTool session token

  • Uses backend session secret (helpers/jwt.js)
  • Sets cookie and redirects user to frontend callback:
  • https://learningtool.bonuspoint.info/sso-callback?token=<BonuspointLearningToolSessionToken>

Step 9 — Frontend callback and API authentication

  • Frontend decodes token payload for context routing
  • Frontend stores auth context/token and sends GraphQL/API requests with bearer token
  • Backend verifies bearer token in middleware
  • Frontend navigates user to role-appropriate page (home, admin-dashboard, school-dashboard, etc.)

5) Query/Form Parameter Purpose Table

  • iss: identifies trusted platform issuer
  • client_id: identifies BonuspointLearningTool tool registration in LMS
  • login_hint: opaque LMS-provided hint for launch/user continuity
  • lti_message_hint: opaque LMS launch context hint
  • target_link_uri: intended tool launch target URL
  • lti_deployment_id: specific LMS deployment identifier for this tool install
  • state: anti-CSRF + transaction correlation
  • nonce: replay protection for id_token
  • id_token: signed platform assertion containing launch/user/role/context claims
  • kid: key id in JWT header used to choose proper verification key from JWKS

6) Original conversational summary

  • Browser/User -> Blackboard: user wants to open BonuspointLearningTool tool
  • Blackboard -> BonuspointLearningTool: sends OIDC launch initiation with known client id and hints
  • BonuspointLearningTool -> Blackboard/Browser: returns redirect to Anthology OIDC with generated state/nonce
  • Browser -> Anthology: continues authentication launch
  • Anthology + Blackboard runtime prepare signed id_token
  • Browser -> BonuspointLearningTool launch callback: submits id_token + state
  • BonuspointLearningTool -> Anthology runtime: fetches JWKS public keys and verifies signature
  • BonuspointLearningTool -> Browser: after validation, returns BonuspointLearningTool app session token and redirects to frontend
  • BonuspointLearningTool frontend -> Browser: initializes authenticated experience

Corrections applied to original wording:
– Not “decryption” of JWT signature; this is signature verification
– JWKS keys are platform-published rotating keys, not per-user “dynamic session key” semantics
– BonuspointLearningTool app session token is issued by BonuspointLearningTool backend and then used for BonuspointLearningTool API authorization


7) Mermaid sequence

Full SSO sequence chart


8) Additional implementation notes from code

  • Backend sets httpOnly cookie for token during redirect flow.
  • Frontend callback also processes token from query and stores token/context for app usage.
  • Membership sync logic can use Blackboard REST API and token endpoint credentials.

9) Final concise takeaway

  • Platform launch token validation (LTI/OIDC): asymmetric verification via JWKS (RS256 path)
  • BonuspointLearningTool app token validation: shared-secret signing/verification within BonuspointLearningTool
  • Security of this flow depends on strict validation of state, nonce, issuer, audience, signature key id (kid), and expiry.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *