@lti-tool/core 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/interfaces/index.d.ts +1 -0
  3. package/dist/interfaces/index.d.ts.map +1 -1
  4. package/dist/interfaces/ltiConfig.d.ts +23 -0
  5. package/dist/interfaces/ltiConfig.d.ts.map +1 -1
  6. package/dist/interfaces/ltiDynamicRegistrationSession.d.ts +14 -0
  7. package/dist/interfaces/ltiDynamicRegistrationSession.d.ts.map +1 -0
  8. package/dist/interfaces/ltiDynamicRegistrationSession.js +1 -0
  9. package/dist/interfaces/ltiStorage.d.ts +22 -0
  10. package/dist/interfaces/ltiStorage.d.ts.map +1 -1
  11. package/dist/ltiTool.d.ts +64 -1
  12. package/dist/ltiTool.d.ts.map +1 -1
  13. package/dist/ltiTool.js +87 -1
  14. package/dist/schemas/index.d.ts +5 -0
  15. package/dist/schemas/index.d.ts.map +1 -1
  16. package/dist/schemas/index.js +4 -0
  17. package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.d.ts +34 -0
  18. package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.d.ts.map +1 -0
  19. package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.js +28 -0
  20. package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.d.ts +101 -0
  21. package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.d.ts.map +1 -0
  22. package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.js +51 -0
  23. package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.d.ts +59 -0
  24. package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.d.ts.map +1 -0
  25. package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.js +53 -0
  26. package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.d.ts +7 -0
  27. package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.d.ts.map +1 -0
  28. package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.js +5 -0
  29. package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.d.ts +73 -0
  30. package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.d.ts.map +1 -0
  31. package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.js +61 -0
  32. package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.d.ts +103 -0
  33. package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.d.ts.map +1 -0
  34. package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.js +49 -0
  35. package/dist/services/dynamicRegistration.service.d.ts +121 -0
  36. package/dist/services/dynamicRegistration.service.d.ts.map +1 -0
  37. package/dist/services/dynamicRegistration.service.js +312 -0
  38. package/dist/services/dynamicRegistrationHandlers/moodle.d.ts +48 -0
  39. package/dist/services/dynamicRegistrationHandlers/moodle.d.ts.map +1 -0
  40. package/dist/services/dynamicRegistrationHandlers/moodle.js +152 -0
  41. package/dist/utils/ltiPlatformCapabilities.d.ts +65 -0
  42. package/dist/utils/ltiPlatformCapabilities.d.ts.map +1 -0
  43. package/dist/utils/ltiPlatformCapabilities.js +73 -0
  44. package/package.json +3 -3
  45. package/src/interfaces/index.ts +1 -0
  46. package/src/interfaces/ltiConfig.ts +25 -0
  47. package/src/interfaces/ltiDynamicRegistrationSession.ts +14 -0
  48. package/src/interfaces/ltiStorage.ts +32 -0
  49. package/src/ltiTool.ts +122 -1
  50. package/src/schemas/index.ts +17 -0
  51. package/src/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.ts +31 -0
  52. package/src/schemas/lti13/dynamicRegistration/ltiMessages.schema.ts +59 -0
  53. package/src/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.ts +60 -0
  54. package/src/schemas/lti13/dynamicRegistration/registrationRequest.schema.ts +8 -0
  55. package/src/schemas/lti13/dynamicRegistration/registrationResponse.schema.ts +67 -0
  56. package/src/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.ts +55 -0
  57. package/src/services/dynamicRegistration.service.ts +406 -0
  58. package/src/services/dynamicRegistrationHandlers/moodle.ts +184 -0
  59. package/src/utils/ltiPlatformCapabilities.ts +86 -0
@@ -0,0 +1,59 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for LTI platform-specific configuration within OpenID Connect Discovery.
4
+ * Contains LTI-specific metadata about the platform's capabilities and supported features.
5
+ *
6
+ * @property product_family_code - Platform identifier (e.g., 'moodle', 'canvas', 'sakai')
7
+ * @property version - Platform version string
8
+ * @property messages_supported - Array of LTI message types the platform supports
9
+ * @property variables - Optional array of custom variable names the platform supports
10
+ */
11
+ export declare const ltiPlatformConfigurationSchema: z.ZodObject<{
12
+ product_family_code: z.ZodString;
13
+ version: z.ZodString;
14
+ messages_supported: z.ZodArray<z.ZodObject<{
15
+ type: z.ZodString;
16
+ placements: z.ZodOptional<z.ZodArray<z.ZodString>>;
17
+ }, z.core.$loose>>;
18
+ variables: z.ZodOptional<z.ZodArray<z.ZodString>>;
19
+ }, z.core.$strip>;
20
+ /**
21
+ * Zod schema for validating OpenID Connect Discovery configuration from LTI 1.3 platforms.
22
+ * This configuration is fetched during dynamic registration to discover platform endpoints,
23
+ * supported features, and security requirements. Used to validate the response from the
24
+ * platform's /.well-known/openid_configuration endpoint.
25
+ *
26
+ * @property issuer - Platform's issuer URL (must match hostname of configuration endpoint)
27
+ * @property authorization_endpoint - OAuth 2.0 authorization endpoint for LTI launches
28
+ * @property registration_endpoint - Dynamic registration endpoint for tool registration
29
+ * @property jwks_uri - JSON Web Key Set endpoint for signature verification
30
+ * @property token_endpoint - OAuth 2.0 token endpoint for service access tokens
31
+ * @property scopes_supported - Array of OAuth scopes the platform supports (AGS, NRPS, etc.)
32
+ * @property https://purl.imsglobal.org/spec/lti-platform-configuration - LTI-specific platform metadata
33
+ */
34
+ export declare const openIDConfigurationSchema: z.ZodObject<{
35
+ issuer: z.ZodURL;
36
+ authorization_endpoint: z.ZodURL;
37
+ registration_endpoint: z.ZodURL;
38
+ jwks_uri: z.ZodURL;
39
+ token_endpoint: z.ZodURL;
40
+ token_endpoint_auth_methods_supported: z.ZodArray<z.ZodString>;
41
+ token_endpoint_auth_signing_alg_values_supported: z.ZodArray<z.ZodString>;
42
+ scopes_supported: z.ZodArray<z.ZodString>;
43
+ response_types_supported: z.ZodArray<z.ZodString>;
44
+ id_token_signing_alg_values_supported: z.ZodArray<z.ZodString>;
45
+ claims_supported: z.ZodArray<z.ZodString>;
46
+ subject_types_supported: z.ZodArray<z.ZodString>;
47
+ authorization_server: z.ZodOptional<z.ZodString>;
48
+ 'https://purl.imsglobal.org/spec/lti-platform-configuration': z.ZodObject<{
49
+ product_family_code: z.ZodString;
50
+ version: z.ZodString;
51
+ messages_supported: z.ZodArray<z.ZodObject<{
52
+ type: z.ZodString;
53
+ placements: z.ZodOptional<z.ZodArray<z.ZodString>>;
54
+ }, z.core.$loose>>;
55
+ variables: z.ZodOptional<z.ZodArray<z.ZodString>>;
56
+ }, z.core.$strip>;
57
+ }, z.core.$loose>;
58
+ export type OpenIDConfiguration = z.infer<typeof openIDConfigurationSchema>;
59
+ //# sourceMappingURL=openIDConfiguration.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openIDConfiguration.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;iBAYzC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;iBAkB5B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for LTI platform-specific configuration within OpenID Connect Discovery.
4
+ * Contains LTI-specific metadata about the platform's capabilities and supported features.
5
+ *
6
+ * @property product_family_code - Platform identifier (e.g., 'moodle', 'canvas', 'sakai')
7
+ * @property version - Platform version string
8
+ * @property messages_supported - Array of LTI message types the platform supports
9
+ * @property variables - Optional array of custom variable names the platform supports
10
+ */
11
+ export const ltiPlatformConfigurationSchema = z.object({
12
+ product_family_code: z.string(),
13
+ version: z.string(),
14
+ messages_supported: z.array(z
15
+ .object({
16
+ type: z.string(),
17
+ placements: z.array(z.string()).optional(),
18
+ })
19
+ .loose()),
20
+ variables: z.array(z.string()).optional(),
21
+ });
22
+ /**
23
+ * Zod schema for validating OpenID Connect Discovery configuration from LTI 1.3 platforms.
24
+ * This configuration is fetched during dynamic registration to discover platform endpoints,
25
+ * supported features, and security requirements. Used to validate the response from the
26
+ * platform's /.well-known/openid_configuration endpoint.
27
+ *
28
+ * @property issuer - Platform's issuer URL (must match hostname of configuration endpoint)
29
+ * @property authorization_endpoint - OAuth 2.0 authorization endpoint for LTI launches
30
+ * @property registration_endpoint - Dynamic registration endpoint for tool registration
31
+ * @property jwks_uri - JSON Web Key Set endpoint for signature verification
32
+ * @property token_endpoint - OAuth 2.0 token endpoint for service access tokens
33
+ * @property scopes_supported - Array of OAuth scopes the platform supports (AGS, NRPS, etc.)
34
+ * @property https://purl.imsglobal.org/spec/lti-platform-configuration - LTI-specific platform metadata
35
+ */
36
+ export const openIDConfigurationSchema = z
37
+ .object({
38
+ issuer: z.url(),
39
+ authorization_endpoint: z.url(),
40
+ registration_endpoint: z.url(),
41
+ jwks_uri: z.url(),
42
+ token_endpoint: z.url(),
43
+ token_endpoint_auth_methods_supported: z.array(z.string()),
44
+ token_endpoint_auth_signing_alg_values_supported: z.array(z.string()),
45
+ scopes_supported: z.array(z.string()),
46
+ response_types_supported: z.array(z.string()),
47
+ id_token_signing_alg_values_supported: z.array(z.string()),
48
+ claims_supported: z.array(z.string()),
49
+ subject_types_supported: z.array(z.string()),
50
+ authorization_server: z.string().optional(),
51
+ 'https://purl.imsglobal.org/spec/lti-platform-configuration': ltiPlatformConfigurationSchema,
52
+ })
53
+ .loose();
@@ -0,0 +1,7 @@
1
+ import * as z from 'zod';
2
+ export declare const RegistrationRequestSchema: z.ZodObject<{
3
+ openid_configuration: z.ZodURL;
4
+ registration_token: z.ZodOptional<z.ZodString>;
5
+ }, z.core.$strip>;
6
+ export type RegistrationRequest = z.infer<typeof RegistrationRequestSchema>;
7
+ //# sourceMappingURL=registrationRequest.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registrationRequest.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/registrationRequest.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,eAAO,MAAM,yBAAyB;;;iBAGpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import * as z from 'zod';
2
+ export const RegistrationRequestSchema = z.object({
3
+ openid_configuration: z.url(),
4
+ registration_token: z.string().optional(),
5
+ });
@@ -0,0 +1,73 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for validating LTI 1.3 dynamic registration response from platforms.
4
+ * This response is returned after successfully registering a tool with an LTI platform.
5
+ * Contains the registered client credentials and configuration that the tool needs to store.
6
+ *
7
+ * @property client_id - Unique client identifier assigned by the platform
8
+ * @property registration_client_uri - Optional URI for managing this registration
9
+ * @property registration_access_token - Optional token for registration management
10
+ * @property application_type - Always 'web' for LTI tools
11
+ * @property response_types - OAuth response types, always ['id_token'] for LTI
12
+ * @property grant_types - OAuth grant types supported ('implicit', 'client_credentials')
13
+ * @property initiate_login_uri - Tool's login initiation endpoint
14
+ * @property redirect_uris - Array of valid redirect URIs for the tool
15
+ * @property client_name - Human-readable name of the registered tool
16
+ * @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
17
+ * @property logo_uri - Optional URL to the tool's logo image
18
+ * @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3
19
+ * @property contacts - Optional array of contact email addresses
20
+ * @property scope - Optional OAuth scopes granted to the tool
21
+ * @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
22
+ */
23
+ export declare const RegistrationResponseSchema: z.ZodObject<{
24
+ client_id: z.ZodString;
25
+ registration_client_uri: z.ZodOptional<z.ZodURL>;
26
+ registration_access_token: z.ZodOptional<z.ZodString>;
27
+ application_type: z.ZodLiteral<"web">;
28
+ response_types: z.ZodArray<z.ZodLiteral<"id_token">>;
29
+ grant_types: z.ZodArray<z.ZodEnum<{
30
+ implicit: "implicit";
31
+ client_credentials: "client_credentials";
32
+ }>>;
33
+ initiate_login_uri: z.ZodURL;
34
+ redirect_uris: z.ZodArray<z.ZodURL>;
35
+ client_name: z.ZodString;
36
+ jwks_uri: z.ZodURL;
37
+ logo_uri: z.ZodUnion<[z.ZodOptional<z.ZodURL>, z.ZodLiteral<"">]>;
38
+ token_endpoint_auth_method: z.ZodLiteral<"private_key_jwt">;
39
+ contacts: z.ZodOptional<z.ZodArray<z.ZodEmail>>;
40
+ scope: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
41
+ 'https://purl.imsglobal.org/spec/lti-tool-configuration': z.ZodObject<{
42
+ domain: z.ZodString;
43
+ target_link_uri: z.ZodOptional<z.ZodURL>;
44
+ custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
45
+ claims: z.ZodArray<z.ZodString>;
46
+ messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
47
+ type: z.ZodLiteral<"LtiResourceLinkRequest">;
48
+ }, z.core.$strip>, z.ZodObject<{
49
+ type: z.ZodLiteral<"LtiDeepLinkingRequest">;
50
+ target_link_uri: z.ZodOptional<z.ZodURL>;
51
+ label: z.ZodOptional<z.ZodString>;
52
+ placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
53
+ ContentArea: "ContentArea";
54
+ RichTextEditor: "RichTextEditor";
55
+ CourseNavigation: "CourseNavigation";
56
+ }>>>;
57
+ supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
58
+ file: "file";
59
+ ltiResourceLink: "ltiResourceLink";
60
+ html: "html";
61
+ link: "link";
62
+ image: "image";
63
+ }>>>;
64
+ supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
65
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
66
+ custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
67
+ }, z.core.$strip>], "type">>;
68
+ version: z.ZodOptional<z.ZodString>;
69
+ deployment_id: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$strip>;
71
+ }, z.core.$strip>;
72
+ export type RegistrationResponse = z.infer<typeof RegistrationResponseSchema>;
73
+ //# sourceMappingURL=registrationResponse.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registrationResponse.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/registrationResponse.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AA0BzB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBrC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1,61 @@
1
+ import * as z from 'zod';
2
+ import { LTIMessagesArraySchema } from './ltiMessages.schema';
3
+ /**
4
+ * Zod schema for LTI tool configuration within dynamic registration response.
5
+ * Contains tool-specific metadata returned by the platform after successful registration.
6
+ *
7
+ * @property domain - Tool's domain name for security validation
8
+ * @property target_link_uri - Optional default launch URL for the tool
9
+ * @property custom_parameters - Optional custom parameters passed to the tool
10
+ * @property claims - Array of JWT claims the tool requires (e.g., 'iss', 'sub', 'name', 'email')
11
+ * @property messages - Array of LTI message types the tool supports
12
+ * @property version - Optional tool version string
13
+ * @property deployment_id - Optional deployment identifier assigned by the platform
14
+ */
15
+ const LTIToolConfigurationResponseSchema = z.object({
16
+ domain: z.string(),
17
+ target_link_uri: z.url().optional(),
18
+ custom_parameters: z.record(z.string(), z.string()).optional(),
19
+ claims: z.array(z.string()),
20
+ messages: LTIMessagesArraySchema,
21
+ version: z.string().optional(),
22
+ deployment_id: z.string().optional(),
23
+ });
24
+ /**
25
+ * Zod schema for validating LTI 1.3 dynamic registration response from platforms.
26
+ * This response is returned after successfully registering a tool with an LTI platform.
27
+ * Contains the registered client credentials and configuration that the tool needs to store.
28
+ *
29
+ * @property client_id - Unique client identifier assigned by the platform
30
+ * @property registration_client_uri - Optional URI for managing this registration
31
+ * @property registration_access_token - Optional token for registration management
32
+ * @property application_type - Always 'web' for LTI tools
33
+ * @property response_types - OAuth response types, always ['id_token'] for LTI
34
+ * @property grant_types - OAuth grant types supported ('implicit', 'client_credentials')
35
+ * @property initiate_login_uri - Tool's login initiation endpoint
36
+ * @property redirect_uris - Array of valid redirect URIs for the tool
37
+ * @property client_name - Human-readable name of the registered tool
38
+ * @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
39
+ * @property logo_uri - Optional URL to the tool's logo image
40
+ * @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3
41
+ * @property contacts - Optional array of contact email addresses
42
+ * @property scope - Optional OAuth scopes granted to the tool
43
+ * @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
44
+ */
45
+ export const RegistrationResponseSchema = z.object({
46
+ client_id: z.string(),
47
+ registration_client_uri: z.url().optional(),
48
+ registration_access_token: z.string().optional(),
49
+ application_type: z.literal('web'),
50
+ response_types: z.array(z.literal('id_token')),
51
+ grant_types: z.array(z.enum(['implicit', 'client_credentials'])), // Note: "implicit" not "implict"
52
+ initiate_login_uri: z.url(),
53
+ redirect_uris: z.array(z.url()),
54
+ client_name: z.string(),
55
+ jwks_uri: z.url(),
56
+ logo_uri: z.url().optional().or(z.literal('')),
57
+ token_endpoint_auth_method: z.literal('private_key_jwt'),
58
+ contacts: z.array(z.email()).optional(),
59
+ scope: z.string().optional().or(z.literal('')),
60
+ 'https://purl.imsglobal.org/spec/lti-tool-configuration': LTIToolConfigurationResponseSchema,
61
+ });
@@ -0,0 +1,103 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Zod schema for LTI tool configuration section within tool registration payload.
4
+ * Contains LTI-specific metadata about the tool being registered with the platform.
5
+ *
6
+ * @property domain - Tool's domain name for security validation and CORS policies
7
+ * @property description - Optional human-readable description of the tool's purpose
8
+ * @property target_link_uri - Default launch URL where the platform should send LTI requests
9
+ * @property claims - Array of JWT claims the tool requires from launch requests (e.g., 'iss', 'sub', 'name', 'email')
10
+ * @property messages - Array of LTI message types the tool supports (ResourceLink, DeepLinking, etc.)
11
+ */
12
+ declare const LTIToolConfigurationSchema: z.ZodObject<{
13
+ domain: z.ZodString;
14
+ description: z.ZodOptional<z.ZodString>;
15
+ target_link_uri: z.ZodURL;
16
+ claims: z.ZodArray<z.ZodString>;
17
+ messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
18
+ type: z.ZodLiteral<"LtiResourceLinkRequest">;
19
+ }, z.core.$strip>, z.ZodObject<{
20
+ type: z.ZodLiteral<"LtiDeepLinkingRequest">;
21
+ target_link_uri: z.ZodOptional<z.ZodURL>;
22
+ label: z.ZodOptional<z.ZodString>;
23
+ placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
24
+ ContentArea: "ContentArea";
25
+ RichTextEditor: "RichTextEditor";
26
+ CourseNavigation: "CourseNavigation";
27
+ }>>>;
28
+ supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
29
+ file: "file";
30
+ ltiResourceLink: "ltiResourceLink";
31
+ html: "html";
32
+ link: "link";
33
+ image: "image";
34
+ }>>>;
35
+ supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
36
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
38
+ }, z.core.$strip>], "type">>;
39
+ }, z.core.$strip>;
40
+ /**
41
+ * Zod schema for validating LTI 1.3 dynamic registration payload sent to platforms.
42
+ * This payload is constructed by the tool and sent to the platform's registration endpoint
43
+ * to register the tool and request specific OAuth scopes and LTI services.
44
+ *
45
+ * @property application_type - Always 'web' for LTI tools
46
+ * @property response_types - OAuth response types, always ['id_token'] for LTI 1.3
47
+ * @property grant_types - OAuth grant types requested ('implicit' for launches, 'client_credentials' for services)
48
+ * @property initiate_login_uri - Tool's login initiation endpoint for OIDC flow
49
+ * @property redirect_uris - Array of valid redirect URIs where the platform can send responses
50
+ * @property client_name - Human-readable name of the tool being registered
51
+ * @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
52
+ * @property logo_uri - Optional URL to the tool's logo image
53
+ * @property scope - Optional OAuth scopes being requested (AGS, NRPS, etc.)
54
+ * @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3 security
55
+ * @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
56
+ */
57
+ export declare const ToolRegistrationPayloadSchema: z.ZodObject<{
58
+ application_type: z.ZodLiteral<"web">;
59
+ response_types: z.ZodArray<z.ZodLiteral<"id_token">>;
60
+ grant_types: z.ZodArray<z.ZodEnum<{
61
+ implicit: "implicit";
62
+ client_credentials: "client_credentials";
63
+ }>>;
64
+ initiate_login_uri: z.ZodURL;
65
+ redirect_uris: z.ZodArray<z.ZodURL>;
66
+ client_name: z.ZodString;
67
+ jwks_uri: z.ZodURL;
68
+ logo_uri: z.ZodOptional<z.ZodURL>;
69
+ scope: z.ZodOptional<z.ZodString>;
70
+ token_endpoint_auth_method: z.ZodLiteral<"private_key_jwt">;
71
+ 'https://purl.imsglobal.org/spec/lti-tool-configuration': z.ZodObject<{
72
+ domain: z.ZodString;
73
+ description: z.ZodOptional<z.ZodString>;
74
+ target_link_uri: z.ZodURL;
75
+ claims: z.ZodArray<z.ZodString>;
76
+ messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
77
+ type: z.ZodLiteral<"LtiResourceLinkRequest">;
78
+ }, z.core.$strip>, z.ZodObject<{
79
+ type: z.ZodLiteral<"LtiDeepLinkingRequest">;
80
+ target_link_uri: z.ZodOptional<z.ZodURL>;
81
+ label: z.ZodOptional<z.ZodString>;
82
+ placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
83
+ ContentArea: "ContentArea";
84
+ RichTextEditor: "RichTextEditor";
85
+ CourseNavigation: "CourseNavigation";
86
+ }>>>;
87
+ supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
88
+ file: "file";
89
+ ltiResourceLink: "ltiResourceLink";
90
+ html: "html";
91
+ link: "link";
92
+ image: "image";
93
+ }>>>;
94
+ supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
95
+ roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
96
+ custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
97
+ }, z.core.$strip>], "type">>;
98
+ }, z.core.$strip>;
99
+ }, z.core.$strip>;
100
+ export type ToolRegistrationPayload = z.infer<typeof ToolRegistrationPayloadSchema>;
101
+ export type LTIToolConfiguration = z.infer<typeof LTIToolConfigurationSchema>;
102
+ export {};
103
+ //# sourceMappingURL=toolRegistrationPayload.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolRegistrationPayload.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB;;;;;;;;;GASG;AACH,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM9B,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1,49 @@
1
+ import * as z from 'zod';
2
+ import { LTIMessagesArraySchema } from './ltiMessages.schema';
3
+ /**
4
+ * Zod schema for LTI tool configuration section within tool registration payload.
5
+ * Contains LTI-specific metadata about the tool being registered with the platform.
6
+ *
7
+ * @property domain - Tool's domain name for security validation and CORS policies
8
+ * @property description - Optional human-readable description of the tool's purpose
9
+ * @property target_link_uri - Default launch URL where the platform should send LTI requests
10
+ * @property claims - Array of JWT claims the tool requires from launch requests (e.g., 'iss', 'sub', 'name', 'email')
11
+ * @property messages - Array of LTI message types the tool supports (ResourceLink, DeepLinking, etc.)
12
+ */
13
+ const LTIToolConfigurationSchema = z.object({
14
+ domain: z.string(),
15
+ description: z.string().optional(),
16
+ target_link_uri: z.url(),
17
+ claims: z.array(z.string()),
18
+ messages: LTIMessagesArraySchema,
19
+ });
20
+ /**
21
+ * Zod schema for validating LTI 1.3 dynamic registration payload sent to platforms.
22
+ * This payload is constructed by the tool and sent to the platform's registration endpoint
23
+ * to register the tool and request specific OAuth scopes and LTI services.
24
+ *
25
+ * @property application_type - Always 'web' for LTI tools
26
+ * @property response_types - OAuth response types, always ['id_token'] for LTI 1.3
27
+ * @property grant_types - OAuth grant types requested ('implicit' for launches, 'client_credentials' for services)
28
+ * @property initiate_login_uri - Tool's login initiation endpoint for OIDC flow
29
+ * @property redirect_uris - Array of valid redirect URIs where the platform can send responses
30
+ * @property client_name - Human-readable name of the tool being registered
31
+ * @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
32
+ * @property logo_uri - Optional URL to the tool's logo image
33
+ * @property scope - Optional OAuth scopes being requested (AGS, NRPS, etc.)
34
+ * @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3 security
35
+ * @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
36
+ */
37
+ export const ToolRegistrationPayloadSchema = z.object({
38
+ application_type: z.literal('web'),
39
+ response_types: z.array(z.literal('id_token')),
40
+ grant_types: z.array(z.enum(['implicit', 'client_credentials'])),
41
+ initiate_login_uri: z.url(),
42
+ redirect_uris: z.array(z.url()),
43
+ client_name: z.string(),
44
+ jwks_uri: z.url(),
45
+ logo_uri: z.url().optional(),
46
+ scope: z.string().optional(),
47
+ token_endpoint_auth_method: z.literal('private_key_jwt'),
48
+ 'https://purl.imsglobal.org/spec/lti-tool-configuration': LTIToolConfigurationSchema,
49
+ });
@@ -0,0 +1,121 @@
1
+ import type { BaseLogger } from 'pino';
2
+ import type { DynamicRegistrationConfig } from '../interfaces/ltiConfig.js';
3
+ import type { LTIDynamicRegistrationSession } from '../interfaces/ltiDynamicRegistrationSession.js';
4
+ import type { LTIStorage } from '../interfaces/ltiStorage.js';
5
+ import type { DynamicRegistrationForm } from '../schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.js';
6
+ import { type OpenIDConfiguration } from '../schemas/lti13/dynamicRegistration/openIDConfiguration.schema.js';
7
+ import type { RegistrationRequest } from '../schemas/lti13/dynamicRegistration/registrationRequest.schema.js';
8
+ /**
9
+ * Service for handling LTI 1.3 dynamic registration workflows.
10
+ *
11
+ * Provides a complete implementation of the LTI 1.3 Dynamic Registration specification,
12
+ * enabling tools to automatically register with LTI platforms without manual configuration.
13
+ * Handles the full registration lifecycle from initiation to completion with security validation.
14
+ *
15
+ * ## Key Features
16
+ * - **Platform Discovery**: Fetches and validates OpenID Connect configuration from LTI platforms
17
+ * - **Security Validation**: Enforces hostname matching and session-based CSRF protection
18
+ * - **Vendor Support**: Provides platform-specific registration forms (Moodle, with extensibility for Canvas, Sakai, etc.)
19
+ * - **Service Selection**: Allows administrators to choose which LTI Advantage services to enable (AGS, NRPS, Deep Linking)
20
+ * - **Automatic Storage**: Persists client and deployment configurations for future launches
21
+ *
22
+ * ## Registration Flow
23
+ * 1. **Initiation**: Platform redirects to tool with registration request
24
+ * 2. **Discovery**: Tool fetches platform's OpenID Connect configuration
25
+ * 3. **Form Generation**: Tool presents service selection form to administrator
26
+ * 4. **Registration**: Tool submits registration payload to platform
27
+ * 5. **Storage**: Tool stores received client credentials and deployment information
28
+ *
29
+ * ## Security Features
30
+ * - Session-based registration with 15-minute expiration
31
+ * - CSRF protection via secure session tokens
32
+ * - Hostname validation between OIDC endpoint and issuer
33
+ * - One-time session consumption to prevent replay attacks
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const service = new DynamicRegistrationService(
38
+ * storage,
39
+ * dynamicRegistrationConfig,
40
+ * logger
41
+ * );
42
+ *
43
+ * // Initiate registration
44
+ * const formHtml = await service.initiateDynamicRegistration(request, '/lti/register');
45
+ *
46
+ * // Complete registration
47
+ * const successHtml = await service.completeDynamicRegistration(formData);
48
+ * ```
49
+ *
50
+ * @see https://www.imsglobal.org/spec/lti-dr/v1p0 LTI 1.3 Dynamic Registration specification
51
+ */
52
+ export declare class DynamicRegistrationService {
53
+ private storage;
54
+ private dynamicRegistrationConfig;
55
+ private logger;
56
+ constructor(storage: LTIStorage, dynamicRegistrationConfig: DynamicRegistrationConfig, logger: BaseLogger);
57
+ /**
58
+ * Fetches and validates the OpenID Connect configuration from an LTI platform during dynamic registration.
59
+ * Validates that the OIDC endpoint and issuer have matching hostnames for security.
60
+ *
61
+ * @param registrationRequest - Registration request containing openid_configuration URL and optional registration_token
62
+ * @returns Validated OpenID configuration with platform endpoints and supported features
63
+ * @throws {Error} When the configuration fetch fails, validation fails, or hostname mismatch detected
64
+ */
65
+ fetchPlatformConfiguration(registrationRequest: RegistrationRequest): Promise<OpenIDConfiguration>;
66
+ /**
67
+ * Initiates LTI 1.3 dynamic registration by fetching platform configuration and generating registration form.
68
+ * Creates a temporary session and returns vendor-specific HTML form for service selection.
69
+ *
70
+ * @param registrationRequest - Registration request containing openid_configuration URL and optional registration_token
71
+ * @param requestPath - Current request path used to build form action URLs
72
+ * @returns HTML form for service selection and registration completion
73
+ * @throws {Error} When platform configuration fetch fails or session creation fails
74
+ */
75
+ initiateDynamicRegistration(registrationRequest: RegistrationRequest, requestPath: string): Promise<string>;
76
+ /**
77
+ * Completes LTI 1.3 dynamic registration by processing form submission and storing client configuration.
78
+ * Validates session, registers with platform, stores client/deployment data, and returns success page.
79
+ *
80
+ * @param dynamicRegistrationForm - Validated form data containing selected services and session token
81
+ * @returns HTML success page with registration details and close button
82
+ * @throws {Error} When session is invalid, registration fails, or storage operations fail
83
+ */
84
+ completeDynamicRegistration(dynamicRegistrationForm: DynamicRegistrationForm): Promise<string>;
85
+ /**
86
+ * Verifies and consumes a registration session token for security validation.
87
+ * Retrieves the session data and immediately deletes it to prevent replay attacks.
88
+ *
89
+ * @param sessionToken - UUID session token from the registration form
90
+ * @returns Session data if valid and not expired, undefined otherwise
91
+ */
92
+ verifyRegistrationSession(sessionToken: string): Promise<LTIDynamicRegistrationSession | undefined>;
93
+ /**
94
+ * Builds array of LTI message types based on selected services during registration.
95
+ * Always includes ResourceLinkRequest, conditionally adds DeepLinkingRequest.
96
+ *
97
+ * @param selectedServices - Array of service names selected by administrator
98
+ * @param deepLinkingUri - URI where deep linking requests should be sent
99
+ * @returns Array of LTI message configurations for the registration payload
100
+ */
101
+ private buildMessages;
102
+ /**
103
+ * Builds array of OAuth scopes based on selected LTI services during registration.
104
+ * Maps service selections to their corresponding LTI Advantage scope URIs.
105
+ *
106
+ * @param selectedServices - Array of service names selected by administrator ('ags', 'nrps', etc.)
107
+ * @returns Array of OAuth scope URIs to request from the platform
108
+ */
109
+ private buildScopes;
110
+ /**
111
+ * Constructs the complete tool registration payload for platform submission.
112
+ * Combines tool configuration, selected services, and OAuth parameters into LTI 1.3 registration format.
113
+ *
114
+ * @param selectedServices - Array of service names selected by administrator
115
+ * @returns Complete registration payload ready for platform submission
116
+ */
117
+ private buildRegistrationPayload;
118
+ private validateDynamicRegistrationResponse;
119
+ private getRegistrationSuccessHtml;
120
+ }
121
+ //# sourceMappingURL=dynamicRegistration.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamicRegistration.service.d.ts","sourceRoot":"","sources":["../../src/services/dynamicRegistration.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,gDAAgD,CAAC;AACpG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uEAAuE,CAAC;AAErH,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,oEAAoE,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oEAAoE,CAAC;AAS9G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAAa,0BAA0B;IAEnC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,yBAAyB;IACjC,OAAO,CAAC,MAAM;gBAFN,OAAO,EAAE,UAAU,EACnB,yBAAyB,EAAE,yBAAyB,EACpD,MAAM,EAAE,UAAU;IAG5B;;;;;;;OAOG;IACG,0BAA0B,CAC9B,mBAAmB,EAAE,mBAAmB,GACvC,OAAO,CAAC,mBAAmB,CAAC;IAkC/B;;;;;;;;OAQG;IACG,2BAA2B,CAC/B,mBAAmB,EAAE,mBAAmB,EACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAsClB;;;;;;;OAOG;IACG,2BAA2B,CAC/B,uBAAuB,EAAE,uBAAuB,GAC/C,OAAO,CAAC,MAAM,CAAC;IAoDlB;;;;;;OAMG;IACG,yBAAyB,CAC7B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,6BAA6B,GAAG,SAAS,CAAC;IAQrD;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAoBnB;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;YAkClB,mCAAmC;IAgBjD,OAAO,CAAC,0BAA0B;CAiDnC"}