/// <summary> /// Build and send the deep linking response. /// </summary> /// <returns></returns> public async Task <IActionResult> OnPostAssignActivities() { var handler = new JwtSecurityTokenHandler(); Token = handler.ReadJwtToken(IdToken); LtiRequest = new LtiDeepLinkingRequest(Token.Payload); var response = new LtiDeepLinkingResponse { Data = LtiRequest.DeepLinkingSettings.Data, DeploymentId = LtiRequest.DeploymentId }; var contentItems = new List <ContentItem>(); var customParameters = LtiRequest.Custom; foreach (var activity in Activities) { if (activity.Selected) { var contentItem = new LtiLinkItem { Title = activity.Title, Text = activity.Description, Url = Url.Page("./Tool", null, null, Request.Scheme), Custom = new Dictionary <string, string> { { "activity_id", activity.Id.ToString() } } }; if (customParameters != null) { foreach (var keyValue in LtiRequest.Custom) { contentItem.Custom.TryAdd(keyValue.Key, keyValue.Value); } } contentItems.Add(contentItem); } } response.ContentItems = contentItems.ToArray(); response.AddClaim(new Claim(JwtRegisteredClaimNames.Iss, LtiRequest.Aud[0])); response.AddClaim(new Claim(JwtRegisteredClaimNames.Aud, LtiRequest.Iss)); response.AddClaim(new Claim(JwtRegisteredClaimNames.Sub, LtiRequest.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.CreateRandomKeyString(8))); var platform = await _context.GetPlatformByIssuerAsync(LtiRequest.Iss); var credentials = PemHelper.SigningCredentialsFromPemString(platform.PrivateKey); var jwt = handler.WriteToken(new JwtSecurityToken(new JwtHeader(credentials), response)); return(Post("id_token", jwt, LtiRequest.DeepLinkingSettings.DeepLinkReturnUrl)); }
public async Task <IActionResult> OnPost(int platformId, int?courseId = null) { if (IdToken.IsMissing()) { return(BadRequest(new ProblemDetails { Title = "Missing data", Detail = $"{nameof(IdToken)} is missing." })); } if (!await ValidateToken(IdToken)) { return(Unauthorized()); } var handler = new JwtSecurityTokenHandler(); var token = handler.ReadJwtToken(IdToken); var messageType = token.Claims.SingleOrDefault(c => c.Type == Constants.LtiClaims.MessageType)?.Value; if (messageType != Constants.Lti.LtiDeepLinkingResponseMessageType) { return(BadRequest(new ProblemDetails { Title = "Incorrect message format", Detail = $"Expecting {Constants.Lti.LtiDeepLinkingResponseMessageType}, but found {messageType}." })); } var client = await _identityContext.Clients.SingleOrDefaultAsync(c => c.ClientId == token.Issuer); var tool = await _context.Tools.SingleOrDefaultAsync(t => t.IdentityServerClientId == client.Id); var platform = await _context.GetPlatformAsync(platformId); var course = courseId.HasValue ? await _context.GetCourseAsync(courseId.Value) : null; var ltiRequest = new LtiDeepLinkingResponse(token.Payload); var contentItems = ltiRequest.ContentItems; if (contentItems != null) { foreach (var contentItem in contentItems) { // Can only handle LTI Links if (contentItem.Type != Constants.ContentItemTypes.LtiLink) { continue; } var ltiLink = (ILtiLinkItem)contentItem; var resourceLink = new ResourceLink { CustomProperties = ltiLink.Custom.ToDatabaseString(), Description = ltiLink.Text, Title = ltiLink.Title, Tool = tool }; if (course == null) { platform.ResourceLinks.Add(resourceLink); } else { course.ResourceLinks.Add(resourceLink); course.GradebookColumns.Add(new GradebookColumn { Label = ltiLink.LineItem?.Label ?? resourceLink.Title, ResourceId = ltiLink.LineItem?.ResourceId, ResourceLink = resourceLink, ScoreMaximum = ltiLink.LineItem?.ScoreMaximum ?? 100, Tag = ltiLink.LineItem?.Tag.IfMissingThen("Deep Link") }); } } await _context.SaveChangesAsync(); } return(Page()); }