Communication with the remote Application
Accessing the application
The extension system for Applications in itslearning uses its own system for providing SSO between itslearning and the remote web application.
Whenever a user creates a new application's instance in the course, itslearning passes data as a regular HTTP URI query string. The request is made to the add instance page, which URL is specified during registration of the application. The request can look as follows:
GET https://myitslearningextension.net/Add.aspx?Accessibility=False&allowedhtmlcodelevel=Everything&ApiSessionId=n0hsmdawswebjt2fqtap4n55&ContextRole=Administrator&CustomerId=14&email=testing%40hotmail.com&Encoding=utf8&FirstName=Admin&Language=en-GB&LastName=Admin&LearningObjectId=100947&LearningObjectInstanceId=110989&Locale=en-GB&mobile=%2b4798884148&OlsonTimeZoneId=Europe%2fOslo&Permissions=Read%2c+Participate%2c+Modify&ReadOnly=False&Role=Staff&synckey=adminSyncKey&Use12HTimeFormat=False&UserId=9&WindowsTimeZoneId=Central+European+Standard+Time&Timestamp=2014-01-16T15%3a18%3a07&Signature=ed57b0d15f35f81e6eef82b792685b41 HTTP/1.1
Likewise, when we open once created application's instance, there's another request sent, this time to the view page of the application. The query string is similar to the previous one:
GET https://myitslearningextension.net/View.aspx?Accessibility=False&allowedhtmlcodelevel=Everything&ApiSessionId=n0hsmdawswebjt2fqtap4n55&ContextRole=Administrator&CustomerId=14&email=testing%40hotmail.com&Encoding=utf8&FirstName=Admin&Language=en-GB&LastName=Admin&LearningObjectId=100947&LearningObjectInstanceId=110989&Locale=en-GB&mobile=%2b4798884148&OlsonTimeZoneId=Europe%2fOslo&Permissions=Read%2c+Participate%2c+Modify&ReadOnly=False&Role=Staff&synckey=adminSyncKey&Use12HTimeFormat=False&UserId=9&WindowsTimeZoneId=Central+European+Standard+Time&Timestamp=2014-01-16T15:20:11&Signature=0051e5d979c5100b0c5333b766c32e18 HTTP/1.1
Query string parameters passed from itslearning to the application:
Parameter name |
Sample value |
Explanation |
ApiSessionId |
fjaklsajj23rfaaallcvj |
Session id that must be used for communicating with itslearning rest api (used as part of Authorization header) |
LearningObjectId |
14345521 |
Numeric unique id of the learning object |
LearningObjectInstanceId |
15677744 |
numeric learning object instance id, identifies a unique use of the learning object (e.g. in a course) |
UserId |
556660 |
Numeric unique id for current user. No relation to PersonId from Plugins. |
WindowsTimeZoneId |
GMT Standard Time |
Id of timezone that can be used in .net framework: TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(windowsTimeZoneId) |
OlsonTimeZoneId |
Europe/London |
Id of timezone on Olson format |
FirstName |
Bent Audun |
First name of current user |
LastName |
Hesvik |
Last name of current user |
Locale |
en-GB |
Culture name that specifies e.g. date time format. RFC 1766 standard in the format "<languagecode2>-<country/regioncode2>") like used by Microsoft.NET Framework, seehttp://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo(vs.71).aspx |
Language |
en-GB |
Culture name for current user's language. RFC 1766 standard in the format "<languagecode2>-<country/regioncode2>") like used by Microsoft.NET Framework, see http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo(vs.71).aspx |
Use12hTimeFormat |
False |
True/False. True if user expects 12 hour format for times (7:00 PM) or False when user expects 24 hour time format (19:00). |
Accessibility |
False |
True/False, if user has checked the accessibility setting in itslearning |
Permissions |
Read, Participate, Evaluate, Modify, ModifyInstance |
Permissions user has to this particular learning object instance. Comma separated string. |
ContextRole |
Admin |
The role of the user in the current context (course). One of Admin, Instructor, Member, Learner |
CustomerId |
353 |
The customer the user request is coming from. Integer. |
Role |
Learner |
The role that the user has in itslearning. Can be one of Staff, Learner, Guest. This parameter should not be used as a permission system, but rather to for example prevent Learner's from seeing parts of the application that you'd only like Staff users to see. |
TimeStamp |
2009 - 06 -20T21: 30 : 22 |
Time stamp in UTC |
allowedhtmlcodelevel |
The level of HTML the user is allowed to use. HighlyRestricted (Only some basic tags are allowed) Restricted (More tags are restricted) LessRestricted (Some tags are restricted) Everything (Everything is allowed) |
|
ReadOnly |
False |
True/False. Can be send in specific cases to indicate a readonly state should be used e.g. preview option. |
iscommonaddpageused |
True |
If "True" itslearning's common AddPage used. If "False" itslearning's common AddPage wasn't used. If application can't use itslearning's common AddPage, parameter won't be present. |
Signature |
A signature created from all of the above parameters and shared secret. The signature is calculated by alphabetically ordering the query string parameters by their name [a-z] and creating an MD5 hash of it. The parameter values are URL encoded before signing (using the C# .NET method HttpUtility.UrlEncode(parameter.Value, Encoding.UTF8. ). A parameter called "SharedSecret" is included which holds the shared secret (Only for computing the signature. It is not sent in the query string.) Example code to validate signature: /// <summary> /// Checks if the request signature is valid and the request is not expired. /// </summary> /// <param name="queryString"></param> /// <param name="sharedSecret"></param> /// <param name="requestLifetimeInMinutes"></param> /// <param name="parameters"></param> internal static void ValidateQueryString( string queryString, string sharedSecret, int requestLifetimeInMinutes, NameValueCollection parameters) { if ( string .IsNullOrEmpty(queryString)) throw new ArgumentNullException( "queryString" ); if ( string .IsNullOrEmpty(sharedSecret)) throw new ArgumentNullException( "sharedSecret" ); if (parameters == null ) throw new ArgumentNullException( "parameters" ); // Check if timestamp is correct and within acceptable range string timestampString = parameters[ "Timestamp" ]; if ( string .IsNullOrEmpty(timestampString)) { throw new SecurityAccessDeniedException( "Timestamp is not specified." ); } DateTime timestamp; if ( !DateTime.TryParse(timestampString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out timestamp)) { throw new SecurityAccessDeniedException( "Query string has an invalid timestamp(check that UTC time is passed and that server time is correct)" ); } timestamp = timestamp.ToUniversalTime(); if (timestamp < DateTime.UtcNow.AddMinutes(-requestLifetimeInMinutes) || timestamp > DateTime.UtcNow.AddMinutes(requestLifetimeInMinutes)) { throw new SecurityAccessDeniedException( "Query string has an invalid timestamp(check that UTC time is passed and that server time is correct)" ); } // Check signature string signature = parameters[ "Signature" ]; if ( string .IsNullOrEmpty(signature)) { throw new SecurityAccessDeniedException( "Signature is not specified." ); } // Remove signature from the querystring queryString = HttpUtility.UrlDecode(queryString); string queryStringWithoutSignature = queryString.Replace( string .Format( "&Signature={0}" , signature), string .Empty); if (ComputeHash(queryStringWithoutSignature + sharedSecret) != signature) { throw new SecurityAccessDeniedException( "Signature is invalid." ); } } /// <summary> /// Calculates MD5 of the string. /// </summary> /// <param name="input"></param> /// <returns></returns> internal static string ComputeHash( string input) { var md5Hasher = new MD5CryptoServiceProvider(); byte [] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input)); var sb = new StringBuilder(); // Loop through each byte of the hashed data and format each one as a hexadecimal string. for ( int i = 0; i < data.Length; i++) { sb.Append(data[i].ToString( "x2" )); } return sb.ToString(); } |
|
The following parameters are extended data: |
Extended data will only be passed as query string parameters if the app has been approved by a site admin to receive such data. |
|
|
Person email address. |
|
mobile |
Person mobile phone. |
|
synckey |
Person synchronization key. |
|
custom1id |
Custom field 1 name used on the site . |
|
custom1 |
Custom field 1 value for the person. |
|
custom2id |
Custom field 2 name used on the site. |
|
custom2 |
Custom field 2 value for the person. |
|
custom3id |
Custom field 3 name used on the site. |
|
custom3 |
Custom field 3 value for the person. |
|
custom4id |
Custom field 4 name used on the site. |
|
custom4 |
Custom field 4 value for the person. |
|
custom5id |
Custom field 5 name used on the site. |
|
custom5 |
Custom field 5 value for the person. |
Deleting a remote instance of the application
Deletion workflow
When an application instance is permanently deleted from itslearning, the URL which is registered as "Delete instance URL" is called.
Your application needs to handle the call by marking the LearningObjectInstance and/or LearningObject as deleted and send the response with code "OK" (200).
If the delete operation takes a long time (delete files, communicate with external systems, etc.), you can only mark your instance as deleted and delete asynchronously.
If the application experiences any difficulties when deleting or marking an instance as deleted, it can return an error and write a problem description into a response. If this is the case, a request will be sent again.
Query string parameters passed on deletion:
Here's sample HTTP request from itslearning to the application sent upon deleting:
GET https://myitslearningextension.net:2080/Delete.ashx?LearningObjectId=5&LearningObjectInstanceId=32&SafeToDeleteLearningObject=True&Timestamp=2014-01-17T13:08:36&Signature=af06dbc4aebfbc9461c5b8bc03696df4 HTTP/1.1
Host: myitslearningextension.net:2080
Connection: Keep-Alive
The parameters explained:
Parameter name |
Sample value |
Explanation |
LearningObjectId |
14345521 |
Numeric unique id of the learning object |
LearningObjectInstanceId |
15677744 |
Numeric learning object instance id, identifies a unique use of the learning object (e.g. in a course) |
SafeToDeleteLearningObject |
True |
Use this parameter to identify if it is safe to delete shared content. It is set to True when the last learning object instance is deleted, which indicates that it is now safe to delete the learning object. This means if a test is shared between several courses, the parameter will be False when one instance is deleted from one of the course. This means you can only delete test results for that particular instance, but not test content (description, questions) or results from other instances. Only when the test is deleted from the last course will this be set to True, which means it's safe to delete all content and data on your side. See more details about this below. |
TimeStamp |
2009 - 06 -20T21: 30 : 22 |
Time stamp in UTC |
Signature |
A signature created from all of the above parameters and shared secret |