Archive for the ‘Domino’ Category

Domino Authentication using AJAX and JSON

Monday, November 25th, 2013

A while back, I had a requirement for a Domino hosted public jQuery Mobile web application to access private data held on the same Domino server in a database which required authentication, but from within the app itself, using either stored credentials or those provided via an in-app pop-up dialog.

Whist I found plenty of useful How-to’s on Domino Authentication via web pages and associated customisations, I just couldn’t seem to find what I was specifically looking for – although they did provide me with plenty of pointers and ideas to try…

Eventually, after much research and even more experimentation, I finally managed to pull all of the pieces of the puzzle together and produced a very simple solution which not only fulfilled all of my requirements, but is also as secure as it can to be (when using HTTPS).

Alas, this aspect of the web app has yet to make it into the app as originally planned, so in the meantime I thought that I’d document how to do this should anyone else out there be struggling to do the same…

It uses traditional Domino web design techniques, and I assume that the reader is comfitable with using javascript to make AJAX/JSON calls using jQuery, and is already familiar with Domino ACL settings for both Anonymous and Authenticated database access.

For the purposes of this article and to keep this simple for now, I shall assume that both the web application and the private data are stored in separate databases, called for example, PublicApp.nsf and PrivateData.nsf respectively, but on the same Domino server.

Stage 1 – Domino Pages.

First we need to create a couple of very basic Pages – each of which simply returns JSON data back to the caller using Computed Fields to fill in the missing blanks.

In the web app database (ie PublicApp.nsf), create a single page called getLoginStatus – which just returns some basic JSON data pertaining to the connected user, in particular whether they are authenticated or not.

This Page contains just the following:-

{

"authenticated": Computed Value,

"user":
{

"username":"Computed Value"

},

"returnStatus": "0",
"returnResponse": "Success"

}

Now set the authenticated Computed Value to:-

@If(@Name([CN];@UserName)= “Anonymous”;”false”; “true”)

and the username Computed Value (note the enclosing quotes) to:-

@Name([CN];@UserName)

Finally in its Page Properties, set Web Access = Other of type application/json, and ensure that this page is accessible by both Anonymous and Authenticated users.

After saving this page, copy it into the Private Database (ie PrivateData.nsf), renaming it as doLoginSuccessAuth in the process.

Ensure that this second page is only accessible to Authenticated users of the database. It is this second page that we actually use for login attempts.

Stage 2 – Javascipt.

Second, we need to add to the web app, some javascript functions plus a couple of global variables which act as URL pointers to the web app and private data.

The functions are:-

getLogonStatus – gets the getLogonStatus page data (returned as JSON) from PublicApp.nsf.

doLogout – sends the logout parameter (to PrivateData.nsf).

doLogin – attempts to get the doLogonSuccessAuth page data from PrivateData.nsf after POSTing to it the users login credentials.

getPrivateData – attempts to get the private page data from PrivateData.nsf.

This is the minimum code required – I’ve stripped out all of the original code – and whilst there is minimal comment, the code should be fairly self explanatory:-

// Global URL pointers for separate public and private databases

var homeURL = "http://MyServerName/PublicApp.nsf"
var dataURL = "http://MyServerName/PrivateData.nsf"

function getLogonStatus() {

function onSuccess(ajax_results, status, xhr) {

// get a value from returned JSON
var usernameLoggedOn = ajax_results.user.username;

if (ajax_results.authenticated) {

alert("getLogonStatus - Authenticated");

/*
* We are successfully accessing Domino
* as an Authenticated
* (non-anonymous) user.
* Code appropriate actions here...
*/

} else {

alert("getLogonStatus - Non-authenticated");

/*
* We are successfully accessing Domino
* as a Non-authenticated
* (Anonymous) user.
* Code appropriate actions here...
*/

}

};

function onError(xhr, status, errorThrown) {

alert("getLogonStatus - Error");

/*
* An error has occurred.
* Code appropriate actions here...
*/

};

$.ajax( {

url : homeURL + "/getLoginStatus?OpenPage",
dataType : 'json',
success : onSuccess,
error : onError

});

};

function doLogout() {

function onSuccess(ajax_results, status, xhr) {

alert("doLogout - Successful");

/*
* We have successfully logged out of Domino.
* Code appropriate actions here...
*/

};

function onError(xhr, status, errorThrown) {

alert("doLogout - Error");

/*
* An error has occurred.
* Code appropriate actions here...
*/

};

$.ajax( {

url : dataURL + "/?Logout&RedirectTo=" + homeURL
+ "/getLoginStatus?OpenPage",
dataType : 'json',
success : onSuccess,
error : onError

});

};

function doLogin(loginUsername, loginPassword) {

var loginRedirectTo = dataURL
+ "/dologinSuccessAuth?OpenPage";

var loginObject = {
username : loginUsername,
password : loginPassword,
redirectto : loginRedirectTo
};

function onSuccess(ajax_results, status, xhr) {

alert("doLogin - Successful");

/*
* We have successfully logged in to Domino
* using the provided
* credentials.
* Code appropriate actions here...
*/

};

function onError(xhr, status, errorThrown) {

if (status == "parsererror") {
// invalid JSON returned

alert("doLogin - Error Authentication");

/*
* An authentication error has occurred.
* Code appropriate actions here...
*/

} else {

alert("doLogin - Error");

/*
* An error has occurred.
* Code appropriate actions here...
*/

}

};

$.ajax( {

// If login successful returns the contents of
// doLoginSuccessAuth page
// (which requires authentication).
// else, Domino returns the HTML login page
// which we do not use

url : dataURL + "/?Login",
dataType : 'json',
type : 'POST',
data : loginObject,
success : onSuccess,
error : onError
});

};

function getPrivateData() {

function onSuccess(ajax_results, status, xhr) {

alert("getPrivateData - Successful");

/*
* We have successfully logged in to Domino
* using the provided
* credentials.
* Code appropriate actions here...
*/

};

function onError(xhr, status, errorThrown) {

if (status == "parsererror") {

alert("getPrivateData - Error Authentication");

/*
* An authentication error has occurred.
* Code appropriate actions here...
*/

} else {

alert("getPrivateData - Error");

/*
* An error has occurred.
* Code appropriate actions here...
*/

}

};

$.ajax( {

url : dataURL + "/getDataPrivateAuth?OpenPage",
dataType : 'json',
success : onSuccess,
error : onError

});

};

And that is all there is to it!

The above has been successfully tested against Domino 9 – I’ve not tried using Domino Data Services (DDS), although I see no reason why it would not work – and it should also be fine with all recent Domino versions, as it has no dependancies on XPages. That said, your own mileage may vary.

Enjoy!

SnTT: In Situ Domino Server Rename

Thursday, October 1st, 2009

One of the benefits of Domino server upgrades, when compared to some other emails systems, is the ease with which it is possible to perform upgrades in situ, without having to migrate to new hardware.

So with this in mind, it came as somewhat of a surprise to discover that when renaming an existing Domino server, Lotus actually advise that “The easiest way is to create a new server and move all users, databases, and needed functions to the new server using the AdminP task”.

Whilst I agreed that this approach is certainly appropriate if you are renaming a mail, or other user facing server (in order to maintain service availability), however if you need to rename a hub, or other non-user facing server, there is absolutely no reason why not to perform a very simple in situ upgrade as detailed below:-

1. Register the new Domino server name in the normal way

2. Add the new Domino server name to DNS (I assume the OS host name will remain the same)

3. Review and update the new Server Document, comparing it with the original server. This should include (but is not limited to):
– Directory Assistance
– Directory Catalog
– Transaction Logging

4. Create a new Server Configuration Settings Document for the new server, and copy across any necessary settings from the original server’s Configurations Settings Document

5. Review events4.nsf and create new probes and monitors for the new server as required, based on those configured against the original server

6. Review all mail routing and replication Connection Documents for the original server and create equivalent documents for the new server (as appropriate)

7. Review Program Documents for the original server and create equivalent documents for the new server (as appropriate)

8. Add the new server name to any relevant ACL groups in the Domino Directory

9. Add the new server name to the relevant DDM collection hierarchy (if appropriate)

10. Take a local (i.e. to your workstation) non-replica copy of catalog.nsf (for future reference)

11. Immediately prior to starting the actual rename process on the original server:
– Force AdminP to process any pending requests using tell adminp process new
– Force routing of any pending emails, ensure that there is no undelivered mail in any mail.box
– Force a database cache flush using dbcache flush

12. Shutdown Domino in the normal way

13. Take backup copies (outside of the Domino Data folder) of the following files:
– notes.ini
– server ID file
– log.nsf
– catalog.nsf
– busytime.nsf, or clubusy.nsf (as appropriate)
– all mail.box(es)

14. Delete the following files:
– original server ID file
– log.nsf
– catalog.nsf
– busytime.nsf, or clubusy.nsf (as appropriate)
– all mail.box(es)

15. Copy the new server ID file to the existing server

16. Edit notes.ini as follows:
– Replace any instances of the original server name with the new one name. Typically for the settings: mailserver and servername
– Edit the serverkeyfilename setting to reflect the file name of the new server ID file

17. Start the newly renamed server, ensuring that it recognises it’s new name and check the console and log file for any unexpected errors

18. Verify that you can access the new server from a Notes Client, and a web browser (if appropriate) using it’s new Domino and DNS name

19. Update the ACLs and Administration Server Database property of all server specific databases on the server, to reflect the new server name (making use of the previously saved catalog.nsf to help identify appropriate databases)

20. Review the directory assistance database (if applicable) and update any instances of the original name with the new one

21. Review any application databases and update the ‘run on server’ agent settings to reflect the new server name (if appropriate)

22. Decommission the original server from the Domino Directory (and of course DNS) in the normal way

Please let me know if you think I’ve missed anything, or if you have any suggestions on how to improve this process.

Enjoy!