Reputation: 829
We are struggling to send LtiDeepLinkingResponse using .NET core. Getting Error as {"errors":{"jwt":[{"attribute":"jwt","type":"JWT format is invalid","message":"JWT format is invalid"}]}}
We are referring the solution provided here https://github.com/LtiLibrary/LtiAdvantage
In Code forming a response as
var Token = handler.ReadJwtToken(idToken);
LtiDeepLinkRequest = new LtiDeepLinkingRequest(Token.Payload);
var response = new LtiDeepLinkingResponse
{
Data = LtiDeepLinkRequest.DeepLinkingSettings.Data,
DeploymentId = LtiDeepLinkRequest.DeploymentId
};
var contentItems = new List<ContentItem>();
var customParameters = LtiDeepLinkRequest.Custom;
var platformId = "1000000101";
List<UseCase> selectedUsecases = new List<UseCase>();
selectedUsecases.Add(new UseCase
{
WebGLUrl = "our_web_page.html",
Module = "ModuleName",
Description = "Module Description",
Topics = "Module Topics"
});
foreach (var useCase in selectedUsecases)
{
var url = Url.Page("/Index", null, new { platformId = platformId }, Request.Scheme);
var contentItem = new LtiLinkItem
{
Title = useCase.Module,
Text = useCase.Description,
Url = url,
Custom = new Dictionary<string, string>
{
{ "activity_id", useCase.Id.ToString() }
}
};
if (customParameters != null)
{
foreach (var keyValue in LtiDeepLinkRequest.Custom)
{
contentItem.Custom.TryAdd(keyValue.Key, keyValue.Value);
}
}
contentItems.Add(contentItem);
}
response.ContentItems = contentItems.ToArray();
response.AddClaim(new Claim(JwtRegisteredClaimNames.Iss, LtiDeepLinkRequest.Aud[0]));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Aud, LtiDeepLinkRequest.Iss));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Sub, LtiDeepLinkRequest.Sub));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Nbf, EpochTime.GetIntDate(DateTime.UtcNow.AddSeconds(-5)).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Exp, EpochTime.GetIntDate(DateTime.UtcNow.AddMinutes(5)).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Nonce, IdentityModel.CryptoRandom.CreateUniqueId(8)));
RsaSecurityKey key = new RsaSecurityKey(RSA.Create());
key.KeyId = "ourjwkskeyid";
var credentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
var header = new JwtHeader(credentials);
var jwt = handler.WriteToken(new JwtSecurityToken(header, response));
return Post("JWT", jwt, LtiDeepLinkRequest.DeepLinkingSettings.DeepLinkReturnUrl);
Other required methods are-
private static ContentResult Post(string name, string value, string url)
{
return new ContentResult
{
Content = "<html><head><title></title></head><body onload=\"document.contentitems.submit()\">"
+ $"<form name=\"contentitems\" method=\"post\" action=\"{url}\">"
+ $"<input type=\"hidden\" name=\"{name}\" value=\"{value}\" /></body></html>",
ContentType = "text/html",
StatusCode = StatusCodes.Status200OK
};
}
We have confirmed that the payload is getting formatted correctly. Payload is
{
"https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingResponse",
"https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
"iss": "1000000101",
"aud": "https://canvas.instructure.com",
"exp": "1674104792",
"iat": "1674104492",
"nonce": "gdT446jJTgc",
"azp": "0omiNPx2v5Q",
"https://purl.imsglobal.org/spec/lti/claim/deployment_id": "11767:105256654",
"https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
{
"custom": {
"activity_id": "0"
},
"text": "Module Description",
"title": "ModuleName",
"type": "ltiResourceLink",
"url": "our_web_page.html"
}
]
}
Could you please guide what could be missing in this? Or any .NET Core libraries reference from where we can explore how can we send LtiDeepLinkingResponse
Upvotes: 1
Views: 374
Reputation: 1
You're missing the claim/data
The https://purl.imsglobal.org/spec/lti-dl/claim/data value must match the value of the data property of the https://purl.imsglobal.org/spec/lti-dl/claim/deep_linking_settings claim from the LtiDeepLinkinkingRequest message. This claim is required if present in LtiDeepLinkingRequest message.
https://www.imsglobal.org/spec/lti-dl/v2p0#data
With the LtiAdvantage Lib for C#, you can obtain the Data in the LtiDeepLinkingRequest with LtiDeepLinkingRequest.DeepLinkingSettings.Data
And if you generate the keys this way:
RsaSecurityKey key = new RsaSecurityKey(RSA.Create());
You wont have them saved anywhere, the Platform will make a request to your Tool JWKS URL to obtain the Public Key and verify the signature.
Check the PemHelper class in your reference to know where to start.
Upvotes: 0