- LtiAdvantage is a library to ease the work of creating an LTI Advantage platform or tool.
- LtiAdvantage.IdentityModel has an HttpClient extension method to request a token using JWT client credentials.
- LtiAdvantage.Oidc extends an OpenIddict server with impersonation support (it replaces LtiAdvantage.IdentityServer4).
- LtiAdvantage.AspNetCore contains ASP.NET Core controller implementations to assist in platform development.
- LtiAdvantage.IntegrationTests integration tests.
- LtiAdvantage.UnitTests unit tests.
4.2.0 is binary compatible with 4.1.0: code built against 4.1.0 runs without recompiling. One
case behaves differently: some claim properties moved to a new base class, so reflection that uses
BindingFlags.DeclaredOnly, or that reads PropertyInfo.DeclaringType, sees them on the base.
Those properties are the service claims on the resource link and submission review requests, and
ResourceLink, AttemptNumber and ProctoringSettings on the proctoring messages.
LtiDeepLinkingRequestreads and writes the AGS, NRPS and Course Groups service claims. The AGS specification says the endpoint claim belongs in any LTI message whose context gives the tool access to the services, and a tool often creates line items while handling a deep linking request (#264).- New shared bases:
LtiPlatformLaunchRequestdeclares the service claims once for the resource link, submission review and deep linking requests, andLtiProctoringRequestdeclaresResourceLink,AttemptNumberandProctoringSettingsonce for the three proctoring messages. Code that sets these claims can now work with the base type instead of switching on the message type (#264). - The proctoring messages still carry no service claims: the Proctoring Services specification lists the optional claims for each message, and no service claim is among them (#264).
4.1.0 replaces 4.0.0, which is deprecated on NuGet. It fixes what building the samples against 4.0.0 turned up, and it has breaking changes, so code built against 4.0.0 must be recompiled.
- AGS and NRPS controllers bind the spec's query parameter names (
resource_link_id,resource_id,user_id) and accept the role URI in NRPSrole; the old names still work (#301). - Deep linking content items read and write
width,height,expiresAtand theembedobject by their spec names;DocumentTarget.Embed, andgradesReleased/submissionReviewon a deep-linkedlineItem(#302, #304). Score.ScoreGiven/ScoreMaximumare optional, and AGS models leave unset optional properties out (#303).- The OpenID configuration document has no explicit nulls, and
MvcOptions.MapLtiRoutemoves any of the library's routes, for example away from OpenIddict's discovery endpoint (#305). - Tool helpers:
InMemoryNonceStore, a login-nonce check onLtiTokenValidator, per-registration JWKS, andHttpClientextensions for AGS, NRPS and Course Groups (#306). RsaPemKeysreplacesPemHelper(setskid, no BouncyCastle);AccessTokenUtiltakes anHttpClientand writes a numericiat(#307).ToolPlatform/ToolPlatformInstancereplace the misspelledToolPlatfom*names, andRole.ToUri()/ContextType.ToUri()are public (#308).JwksCacherefetches a JWKS that was empty when first fetched, for example a tool registered before its key was published (#314).
ImageProperty.Width/Heightareint?(#302), andScore.ScoreGiven/ScoreMaximumaredouble?(#303). Use.Valueor?? 0where you read them, and leave the score values null for a progress-only score.CustomPropertySubstitutions.ToolPlatform/ToolPlatformInstanceuse the correctly spelledToolPlatform/ToolPlatformInstancetypes; the misspelled names remain as obsolete aliases (#308).LtiAdvantage.Lti.CourseGroupis renamed toLtiCourseGroup, so it no longer clashes with an app's ownCourseGroup(#320).ForUserClaimValueType.RolesisRole[], like the launch's roles claim, instead ofIList<string>(#321). Convert withRoleExtensions.TryParseandRole.ToUri(). A role the library does not define reads asRole.Unknown.
- Deep linking content items are written with
width,height,expiresAtandembed: {"html": …}instead ofWidth,Height,ExpiresAtand a bareembedstring. Both forms are still read (#302, #304). - AGS line items, results and scores leave unset optional properties out instead of writing
null, and a progress-only score has noscoreGiven/scoreMaximum(#303). - The client assertion's
iatis a number, and it carries thekidwhen you pass a key id (#307). - Roles arrays (the roles claim, NRPS members,
for_user) leaveRole.Unknownout instead of writingnull(#321).
PemHelper(LTIADV001) and theAccessTokenUtil.GetAccessTokenAsyncoverload without anHttpClient(LTIADV002) still work but are obsolete; useRsaPemKeysand the overload that takes anHttpClientand key id (#307). The misspelledToolPlatfom*names are obsolete too (#308).
- LTI Course Groups Service 1.0 —
groupsserviceclaim,GroupsControllerBase+GroupSetsControllerBase, andgroup_enrollmentson the NRPS membership response (?groups=true) - LTI Proctoring Services 1.0 —
LtiStartProctoringRequest,LtiStartAssessmentRequest,LtiEndAssessmentRequest, and the Assessment Control Service (AssessmentControlControllerBase) LtiTokenValidator— validates an ID token's signature against the platform's JWKS (fetched and cached, refreshed on key rotation) plusiss/aud/exp/nonceand the LTI claimsOpenIdConfigurationControllerBasefor platform/.well-known/openid-configuration, andInMemoryJwksKeyStoreas a ready-madeIJwksKeyStore- LTI Submission Review 1.0 (
LtiSubmissionReviewRequest,for_userclaim, AGSsubmissionReviewextension) - JWKS publishing (
JwksControllerBase+IJwksKeyStore) for/.well-known/jwks.json - LTI Dynamic Registration 1.0 — tool-side
HttpClientextensions and platform-sideDynamicRegistrationControllerBase
- Custom-variable substitution:
$Context.id.historyand$ResourceLink.id.historywere mangled by the shorter.idvariable being substituted first, and$Context.sourcedIdwas unreachable because the sourced id was written over$Context.title. - The
…ControllerBaseclasses no longer turn a client disconnect into a 500.
The packages ship XML documentation. To have it copied into your app's output (so Swagger or another OpenAPI generator can show the controller and model docs), set this in your project file:
<PropertyGroup>
<CopyDocumentationFilesFromPackages>true</CopyDocumentationFilesFromPackages>
</PropertyGroup>Two sample applications show the libraries in use:
| Library | Release | Prerelease |
|---|---|---|
| LtiAdvantage | ||
| LtiAdvantage.IdentityModel | ||
| LtiAdvantage.OIDC | ||
| LtiAdvantage.AspNetCore |
| CI | Env | Status |
|---|---|---|
| AppVeyor | Windows | |
| travis-ci | Ubuntu |
There are two sample applications you can reference for ideas: