-
Notifications
You must be signed in to change notification settings - Fork 3
Creating Remote Content And Authenticating Users
This tutorial will guide you through the process of developing and deploying your base, initial remote content file.
Requirements
In order to complete this tutorial, you will need the following:
- A web-server to host your content files
- An operational InCert server
- An xml or text editor
Setup
This tutorial assumes that you have created the tutorial, Customizing the engine and setting its defaults, and have a version of the engine that will start and attempt to contact your web-server.
If you have not already, you will need to edit your version of init.xml to point to your remote content directory. To do this, edit the following block in your init.xml:
<WebServices.SetEndpointUrlForFunction>
<Properties>
<Function>GetContent</Function>
<Url>https://certdev0.incommontest.org/incommon/windows/content/</Url>
</Properties>
</WebServices.SetEndpointUrlForFunction>
The engine uses simple HTTP GET requests to acquire its content files. This means that you can use a web-browser to view your content files and test your web-server. For example, click here to view InCert's current remote initial tasklist.
Once you have edited init.xml, repackage it into settings.cab, and sign and place settings.cab in your working engine folder. Again, see the tutorial, Customizing the engine and setting its defaults, for detailed instructions.
A Note On Security
Before we get into the tutorial proper, there are two things to keep in mind:
-
the engine can handle HTTPS requests, and we recommend that you host its content files on an HTTPS- secured site. This prevents man-in-the-middle attacks, etc.
-
by design, all of the engine's content files are publicly accessible. It's not a good idea to store secret information in your content files, and you shouldn't need to.
Creating tasklist.xml
After the engine initializes successfully, it downloads "tasklist.xml" from your content site. Here, the name "tasklist.xml" is a bit misleading, as this file will usually contain more than a single list of tasks. Tasklist.xml is essentially the remote equivalent of init.xml, inasmuch as it loads other remote content files and, generally, contains the engine's basic remote logic.
To create tasklist.xml
- Create a new sub-directory in your working directory called "Content."
This directory will contain local versions of your remote content files.
- Create a new file inside your content directory called tasklist.xml. The content of this file should be as follows:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Branches>
<RoleBranch name="main" role="Remote" roleMode="Normal">
</RoleBranch>
</Branches>
</Content>
After the engine acquires and parses tasklist.xml from your content endpoint, it will execute the role-branch for the role "remote" and for the normal role-mode.
Role-modes are an advanced topic, but for now, the "main" role-branch of our tasklist.xml file is the first task-branch that the engine will execute. This, essentially, starts the engine proper.
- The first thing that we'll want to do is to deactivate the engine's splash-screen dialog. To do this, modify tasklist.xml to the following:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Branches>
<RoleBranch name="main" role="Remote" roleMode="Normal">
<UserInterface.StopMessageTimer>
<Properties>
<SettingKey>Splash screen progress text</SettingKey>
</Properties>
</UserInterface.StopMessageTimer>
<UserInterface.HideDialog>
<Properties>
<Dialog>Splash screen dialog</Dialog>
</Properties>
</UserInterface.HideDialog>
</RoleBranch>
</Branches>
</Content>
Here, UserInterface.StopMessageTimer
tells the engine to stop animating the message timer entitled Splash screen progress text
, and UserInterface.HideDialog
tells the engine to hide the dialog named Splash screen dialog
. Both Splash screen dialog
and Splash screen progress text
are defined by default. But, this is another advanced topic.
-
Upload tasklist.xml to your web-server. It should live in your remote content directory.
-
In your engine folder, start your engine by running "elevator.exe." If everything is in order, your engine should start, display the splash screen, and then exit.
Here, we're using "elevator.exe" instead of "engine.exe" to start the engine. In normal mode, the engine expects to be run with elevated, administrative privileges. If not, it will prompt the user to elevate. Elevator.exe just prompts the user to start the engine elevated.
Yes, it is possible to run the engine in non-elevated mode. We'll cover this later, though.
Displaying an Authentication Dialog
One of the first things that we're going to want to do is to prompt users to authenticate against our web-service. To do this, we'll need to create and display an authentication dialog.
- Create a new xml file in your local content directory called "banners.xml." The content of this file should be as follows:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Banners>
</Banners>
</Content>
This file will hold the xml definitions for our custom user-interface components. It's entirely possible to include Banners
content in tasklist.xml, but we like to keep things in separate files. Otherwise, tasklist.xml can grow so long that it becomes difficult to edit.
- Add a
SimpleBanner
namedLoginBanner
to banners.xml:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Banners>
<SimpleBanner name="LoginBanner" height="550" width="500">
<Content>
<SimpleParagraph margin="0,36,0,36" fontSize="24" alignment="Center">
<Content>
<DirectTextContent>!ApplicationTitle! Login</DirectTextContent>
</Content>
</SimpleParagraph>
</Content>
<Buttons>
<ResultButton>
<Target>NextButton</Target>
<Text>Login</Text>
<IsDefaultButton>true</IsDefaultButton>
<Result>ControlResults.NextResult</Result>
</ResultButton>
<DisabledButton>
<Target>BackButton</Target>
<Text>Back</Text>
</DisabledButton>
<UrlButton>
<Target>HelpButton</Target>
<Text>Help</Text>
<Value>https://certdev0.incommontest.org/incommon/index.html</Value>
</UrlButton>
</Buttons>
</SimpleBanner>
</Banners>
</Content>
Here, we're defining a banner that will be 550 pixels wide and 500 pixels high. Our banner will have a title, and next, back, and help buttons.
- Tell the engine to retrieve and parse banners.xml. To do this, modify tasklist.xml as follows:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Branches>
<RoleBranch name="main" role="Remote" roleMode="Normal">
<Control.GetContentFromEndpoint>
<Properties>
<ContentName>banners.xml</ContentName>
</Properties>
</Control.GetContentFromEndpoint>
<UserInterface.StopMessageTimer>
<Properties>
<SettingKey>Splash screen progress text</SettingKey>
</Properties>
</UserInterface.StopMessageTimer>
<UserInterface.HideDialog>
<Properties>
<Dialog>Splash screen dialog</Dialog>
</Properties>
</UserInterface.HideDialog>
</RoleBranch>
</Branches>
</Content>
Here, Control.GetContentFromEndpoint
instructs the engine to import and parse additional content files. We have placed it before the xml blocks that hide the splash dialog because we want to show the splash dialog until all of our content files have been processed.
- Tell the engine to display our login banner by adding a
UserInterface.ShowBorderedBannerModal
block to tasklist.xml:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Branches>
<RoleBranch name="main" role="Remote" roleMode="Normal">
<Control.GetContentFromEndpoint>
<Properties>
<ContentName>banners.xml</ContentName>
</Properties>
</Control.GetContentFromEndpoint>
<UserInterface.StopMessageTimer>
<Properties>
<SettingKey>Splash screen progress text</SettingKey>
</Properties>
</UserInterface.StopMessageTimer>
<UserInterface.HideDialog>
<Properties>
<Dialog>Splash screen dialog</Dialog>
</Properties>
</UserInterface.HideDialog>
<UserInterface.ShowBorderedBannerModal>
<Properties>
<Dialog>Main dialog</Dialog>
<Banner>LoginBanner</Banner>
</Properties>
</UserInterface.ShowBorderedBannerModal>
</RoleBranch>
</Branches>
</Content>
-
Upload tasklist.xml and banners.xml to your content server.
-
Double-click elevator.exe in your working folder to start the engine. If everything is working, the engine should start, show its splash screen, and display its login dialog.
Clicking Help
should open a web-browser to the InCert provisioning api page and clicking Next
should close the dialog and exit the engine. Back
should be disabled.
Authenticating the User
Now that we have an authentication dialog, we actually need to authenticate the user. To do this, we'll add input fields to our authentication dialog and then use the content of these fields to authenticate to the server via our web-service authentication endpoint.
- Modify
LoginBanner
in banners.xml as follows:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Banners>
<SimpleBanner name="LoginBanner" height="550" width="500">
<Content>
<SimpleParagraph margin="0,36,0,36" fontSize="24" alignment="Center">
<Content>
<DirectTextContent>!ApplicationTitle! Login</DirectTextContent>
</Content>
</SimpleParagraph>
<SimpleParagraph>
<Content>
<DirectTextContent>Username:</DirectTextContent>
</Content>
</SimpleParagraph>
<SimpleInputField settingKey="username" controlKey="username"/>
<SimpleParagraph margin="0,8,0,0">
<Content>
<DirectTextContent>Passphrase:</DirectTextContent>
</Content>
</SimpleParagraph>
<PasswordInputField settingKey="passphrase" controlKey="passphrase"/>
<SimpleParagraph margin="0,8,0,0">
<Content>
<DirectTextContent>Credential 2:</DirectTextContent>
</Content>
</SimpleParagraph>
<SimpleInputField settingKey="credential2"/>
<SimpleParagraph margin="0,8,0,0">
<Content>
<DirectTextContent>Credential 3:</DirectTextContent>
</Content>
</SimpleParagraph>
<SimpleInputField settingKey="credential3"/>
<SimpleParagraph margin="0,8,0,0">
<Content>
<DirectTextContent>Credential 4:</DirectTextContent>
</Content>
</SimpleParagraph>
<SimpleInputField settingKey="credential4"/>
<SimpleParagraph controlKey="Instructions" margin="0,12,0,0">
<Content>
<DirectTextContent>
Please provide your network credentials and click Login to continue.
</DirectTextContent>
</Content>
</SimpleParagraph>
</Content>
<Buttons>
<ResultButton>
<Target>NextButton</Target>
<Text>Login</Text>
<IsDefaultButton>true</IsDefaultButton>
<Result>ControlResults.NextResult</Result>
</ResultButton>
<DisabledButton>
<Target>BackButton</Target>
<Text>Back</Text>
</DisabledButton>
<UrlButton>
<Target>HelpButton</Target>
<Text>Help</Text>
<Value>https://certdev0.incommontest.org/incommon/index.html</Value>
</UrlButton>
</Buttons>
</SimpleBanner>
</Banners>
</Content>
We've added a lot of xml here. Essentially, what we've done is add five fields (with labels) to our dialog and some instructions text. Four of the fields are standard input fields, while one of the fields in masked, or password, input field.
- Upload banners.xml to your content server and start your engine by clicking elevator.exe. If everything worked, your login banner should look like this:
Note that SimpleInputField
and PasswordInputField
both take a settingKey
attribute. When users input content into one of these fields, that content is persisted in the engine's temporary settings store and associated with the key specified in the field's settingKey
attribute. This allows the engine to reference these values at a later time.
- In tasklist.xml, add an
Authentication.AuthenticateUser
block to the end of yourmain
role-branch:
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://incert.incommon.org/schemas ../Schemas/tasklist.xsd">
<Branches>
<RoleBranch name="main" role="Remote" roleMode="Normal">
<Control.GetContentFromEndpoint>
<Properties>
<ContentName>banners.xml</ContentName>
</Properties>
</Control.GetContentFromEndpoint>
<UserInterface.StopMessageTimer>
<Properties>
<SettingKey>Splash screen progress text</SettingKey>
</Properties>
</UserInterface.StopMessageTimer>
<UserInterface.HideDialog>
<Properties>
<Dialog>Splash screen dialog</Dialog>
</Properties>
</UserInterface.HideDialog>
<UserInterface.ShowBorderedBannerModal>
<Properties>
<Dialog>Main dialog</Dialog>
<Banner>LoginBanner</Banner>
</Properties>
</UserInterface.ShowBorderedBannerModal>
<Authentication.AuthenticateUser>
<Properties>
<UsernameKey>username</UsernameKey>
<PassphraseKey>passphrase</PassphraseKey>
<Credential2Key>credential2</Credential2Key>
<Credential3Key>credential3</Credential3Key>
<Credential4Key>credential4</Credential4Key>
<CertificateProvider>incommontest.org</CertificateProvider>
</Properties>
</Authentication.AuthenticateUser>
</RoleBranch>
</Branches>
</Content>
If you consult the InCert Provisioning Tools API Examples, you'll see that properties of Authentication.AuthenticateUser
correspond to those required by the authentication web-service endpoint.
Here, Authentication.AuthenticateUser
retrieves the values persisted in the engine's temporary settings store and passes them up to the authentication web-service endpoint. Note that the values of the various "key" properties correspond to those assigned to the settingKey
attributes of the fields on our login dialog.
- Upload tasklist.xml and banners.xml to your content server and run the engine again. If everything worked properly, clicking
Next
after providing the correct credentials will cause the engine to exit.
If you provide the wrong credentials, you should see this error dialog:
Conclusion
Our new authentication dialog works, but it leaves a lot to be desired. It allows users to click Next
if fields are empty, and it does nothing to signal to the user that authentication is in progress. We'll work on this in the next tutorial....