Declan has a post on his blog on how to create a login window using a Dojo dialog box. Its a very nice example on how to do a quick login control using Dojo and AJAX to log in a user versus using the standard Domino style login.
I use a slightly different approach using an XPage custom control that allows me to have more control over the look of the login, so that I can integrate it with the site's overall look and feel, as well as use some dojo fadeIn/fadeOut animations to give it a little bit of extra flair. It also allows me to authenticate against a specific domino resource of my choice so that I can not only verify they are an authenticated user for the application, but also that they might have a specific role that allows them access to a particular resource.
To use the custom control, you just place it on the XPage where you want the "Log In" prompt to appear, set the control's properties, and customize the prompt's text through the use of some editable areas (facets).
Here is a description of the different properties:
loginText: This is the text you want to appear on the page as the link for the end user to click. I usually use 'Log In'
loginURL: This is the URL that the control uses to actually process the login. 99% of the time, its /names.nsf?login.
verifyAccessURL: After the control issues a successful login attempt to loginURL, the control validates access against this URL, verifying they user has access to what I want to redirect them to. If they don't have access, I tell them so.
logoutText: If a user is currently logged in, the control displays this text, instead of the loginText. I usually use "Log Out"
logoutURL: This is the URL to use for the logout. usually its /names.nsf?logout which takes them back to the default site for the domain/domino server. If I want to redirect them to a different page, then i might use /names.nsf?logout&RedirectTo=/mynew/url/page
successURL: This is the URL to send them to after a successful login and verification.
There are also 2 other properties which I haven't implemented yet, numberAttempts and failureURL, the idea being after numberAttempts failed logins, I'd redirect to failureURL.
In order for the control to work, there are two additional resources you'll need to add to your database. The first is a stylesheet that controls the look of the login window, and the other is a short script that sets up the controls on page load. There isn't alot to them, the control just needs them. If you want to change the look and feel of the control, then you modify the login.css. Both files are included in the download for the control at the end of the article.
Let's get down into the meat of the control so you can see how it works, and see how to develop a custom control.
style="display:inline;">
Above is the first 8 lines of the custom control, pretty basic for any XPage. Two things to note off the bat, is first the xp:view has a custom style set to "display:inline". This allows the "Log In" link to appear right along with and next to any code or elements surrounding it, without causeing the margins to clear on either side. By default, a custom control renders as an XHTML div tag, which is a block element (clearing both margins). The other item to note is the inclusion of the startsHidden javascript and login.css stylesheet.
This particular version of the login custom control displays as a floating panel above the page. To help distinguish it from the rest of the page when it is displayed, I "lower the lights" on the rest of the page by creating a div that is 100% width and height, and black, then set the opacity to 70%. This keeps the user from clicking on other controls, and focuses their attention on the login. I call this the 'dither panel.' That is done with the next three lines of code:
styleClass="pnlDither startsHidden" id="pnlDither">
The properties of this panel are all controlled in the login.css, and later, i'll show you the code that makes it fade in and out with the login panel.
After that, the next bit of code creates the link on the page where the custom control is embedded.
There is a hefty amount of code in there, so I'll just explain and break down a little bit, download the code below and follow along if you like. The first block ... creates the first part of the link, the XHTML tag. If the user is logged in, the link's href is set to the logoutURL property. If the user is not logged in, the onclick of the anchor is used to execute some javascript that makes the dither panel, and the login panel itself visible, then animates them with a fade in. We can use a straight-forward dojo.fadeIn for the panel because we are going to display it at 100% opacity, however we want to stop the opacity of the dither panel at 70% opacity so we can see through it, so we use the dojo.animateProperty to animate the opacity of the panel from it's current setting (currently 0) to 70% (css: opacity: 0.7).
The next block of code, again an block decides whether the user is logged in or not, and displays the appropriate text, either loginText or logoutText.
And the final block simply closes the XHTML anchor tag.
The next bit of code just lays out the actual login panel, called loginWindow. It uses several nested elements (the XHTML equiv to div tags) to define the window, its title bar, etc. There are facets (editable regions) that allow you to set the text for the title bar, the welcome message, etc. I won't post all the code for it as it's lengthly, but its all in the download at the end of the article.
I will however go through the actual login script so you can see how the exchange actually happens.
The first part of the code simply posts a the username and password to the loginURL using dojo.xhrPost:
dojo.xhrPost({ url : '#{javascript:compositeData.get("loginURL");}',
handleAs : "text",
preventCache : true,
content: {
"UserName": dojo.byId('#{javascript:getClientId("inpUser")}').value,
"Password": dojo.byId('#{javascript:getClientId("inpPassword")}').value },
You can see in the second line how I retreive the value of the loginURL parameter using the inline XSP javascript command #{javascript: ... } that block is executed on the server side and the result is put back into the code in replacement. In this case the server executes compositeData.get("loginURL") to get the value entered in the parameter loginURL.
Next we have the load function for the xhrPost. This gets executed if the xhrPost is is successful, and data is returned. Here's the first part of that code:
load : function(response, ioArgs) {
if (response.indexOf('reasonType')==-1) {
dojo.xhrGet({
Here all we do is take the response back from the server, held in the variable 'response', and look for a string 'reasonType.' That is the key to telling if the login was successful. If it was not a successful login, then the returned HTML includes a variable reasonType indicating the type of error. So far, I haven't cared enough about what the actual error is with the login, so I display a generic message if it fails, shown below (but actually appears later in the script):
} else {
dojo.byId('#{javascript:getClientId("loginErrorPanel")}').innerHTML = "You have entered an invalid username or password, or do not have sufficient credentials."; }
If the login was successful, I then proceed to actually check against the specific element that I want to veryfiy they have access to. This is done by issueing a dojo.xhrGet to the verifyAccessURL property, then checking again if the access attempt was successful. This time, i do not check for reasonType, as it has caused me a few problems here and there in the past that are really irrelevent to this code. Instead I check for the string 'action="/names.nsf?Login"' that appears in the