/// <summary> /// Handle the LTI request to launch deep linking. The token was validated by the Tool page. /// </summary> /// <returns></returns> public IActionResult OnPost() { if (string.IsNullOrEmpty(IdToken)) { Error = $"{nameof(IdToken)} is missing or empty"; return(Page()); } var handler = new JwtSecurityTokenHandler(); Token = handler.ReadJwtToken(IdToken); LtiRequest = new LtiDeepLinkingRequest(Token.Payload); // Fill the catalog with choices if (LtiRequest.Context == null) { Activities = new List <Activity> { new Activity { Id = 1, Title = "Reports", Description = "Reporting tool for admins.", Selected = false } }; } else { Activities = GenerateActivities(12); } return(Page()); }
/// <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)); }
/// <summary> /// Returns the LTI claims for an LtiDeepLinkingRequest. /// </summary> /// <param name="tool">The deep linking tool.</param> /// <param name="person">The person being authorized.</param> /// <param name="course">The course (can be null).</param> /// <param name="platform">The platform.</param> /// <returns></returns> private List <Claim> GetDeepLinkingRequestClaims( Tool tool, Person person, Course course, Platform platform) { var httpRequest = _httpContextAccessor.HttpContext.Request; var request = new LtiDeepLinkingRequest { DeploymentId = tool.DeploymentId, FamilyName = person.LastName, GivenName = person.FirstName, LaunchPresentation = new LaunchPresentationClaimValueType { DocumentTarget = DocumentTarget.Window, Locale = CultureInfo.CurrentUICulture.Name }, Lis = new LisClaimValueType { PersonSourcedId = person.SisId, CourseSectionSourcedId = course?.SisId }, Lti11LegacyUserId = person.Id.ToString(), Platform = new PlatformClaimValueType { ContactEmail = platform.ContactEmail, Description = platform.Description, Guid = platform.Id.ToString(), Name = platform.Name, ProductFamilyCode = platform.ProductFamilyCode, Url = platform.Url, Version = platform.Version }, Roles = PeopleModel.ParsePersonRoles(person.Roles), TargetLinkUri = tool.DeepLinkingLaunchUrl }; // Add the context if the launch is from a course. if (course == null) { // Remove context roles request.Roles = request.Roles.Where(r => !r.ToString().StartsWith("Context")).ToArray(); } else { request.Context = new ContextClaimValueType { Id = course.Id.ToString(), Title = course.Name, Type = new[] { ContextType.CourseSection } }; } // Add the deep linking settings request.DeepLinkingSettings = new DeepLinkingSettingsClaimValueType { AcceptPresentationDocumentTargets = new [] { DocumentTarget.Window }, AcceptMultiple = true, AcceptTypes = new [] { Constants.ContentItemTypes.LtiLink }, AutoCreate = true, DeepLinkReturnUrl = _linkGenerator.GetUriByPage( "/DeepLinks", handler: null, values: new { platformId = platform.Id, courseId = course?.Id }, scheme: httpRequest.Scheme, host: httpRequest.Host) }; // Collect custom properties if (tool.CustomProperties.TryConvertToDictionary(out var custom)) { // Prepare for custom property substitutions var substitutions = new CustomPropertySubstitutions { LtiUser = new LtiUser { Username = person.Username } }; request.Custom = substitutions.ReplaceCustomPropertyValues(custom); } return(new List <Claim>(request.Claims)); }