Feb 22

Putting Token Login to work

So a few weeks ago I released JAuthTools 1.5.4 which features Token Login. Token Login was created to solve the need to generate a secure token that you can use for automatic login, for example with stuff like newsletters. Today I’m going to show you how you can write something simple with Token Login to handle automatic login with tokens in a unique problem case.

The other day on the JAuthTools mailing list there was an email of a weird case where the user’s session was being created initially with the SSO system but as soon as they clicked around it appeared like they logged out. With a bit of work we managed to work out the initial hit was proxied and the session was being created for the proxy not for the actual user. So initially the user was being successfully authenticated which gave me an idea.

My solution was to use token login to handle the actual request. The process is a tad convoluted, but the diagram should explain how the system works:

So the user logs into a remote service, which proxies a username to the Joomla! which is picked up by SSO HTTP in a custom component which generates a token using the detected username, redirects the user to the token login component (not through the proxy) which then lets the user log in and continue through the site.

So what we need to create is a new component to handle detecting the user, creating the token and them redirecting them. We can use the SSO HTTP plugin to handle detecting the remote user perfectly fine (this has already been tested) and the Token Login component can handle validating tokens and redirecting users.

Step 1: Prerequisites
I’m going to use the JAuthTools packages available from Joomla!Code. To install these, you will need to install the Advanced Tools package first before you get started. The latest version is Advanced Tools 1.5.1 available from JoomlaCode.

Once we’ve got the Advanced Tools installed, we’re going to need the JAuthTools 1.5.4 Core package. This will give us the SSO library that we’re going to use later on. We will also need the SSO plugins package (for the SSO HTTP plugin in our case) and the Token Login package. As we’re not using the user source plugins for this case (both LDAP and Session are provided by default) we don’t need to install them and since we’re going to write our own SSO detection component we don’t need to use the options offered by the SSO package.

Once we’ve got all of the prerequisites installed we can start building the component

Step 2: Building the component
So we’ll start building our component with the basic few lines all components require:

<?php
defined('_JEXEC') or die();

This basic check ensures that we’re within Joomla!’s confines or kills the execution if we’re not. From here, lets set up some basic variables:

$landingpage = 'index.php';
$autocreate = false;

These are two variables we’re going to use later. The landing page is used for token login to redirect the user to a page once they’ve been authenticated successfully. The autocreate option is utilised by the SSO system to determine if it should automatically create the user. Keep these in mind as we’ll use them later on.

In this next phase we’re going to take a copy of the current user and then use the SSO system to attempt to do the login. If its successful, the user’s ID will change and we can then create a token for them and redirect so they can login, if not we’ll redirect them with an error message:

$user =& JFactory::getUser();
$oldid = $user->id;
jimport('jauthtools.sso');
jimport('jauthtools.usersource');
$sso = new JAuthSSOAuthentication();
$sso->doSSOAuth($autocreate);

So we get a reference to the user object, get a copy of the user ID, import the SSO library, create a new SSO authentication object and handle authentication. We see the $autocreate variable we initialised before used here. We could load the plugins ourselves and handle everything but the doSSOAuth call will handle this for us, create the users session and if requested attempt to create the user if they don’t exist. We can then check if the user ID’s are different and then create a token to direct the user back:

if($oldid != $user->id) {
       jimport('jauthtools.token');
       $dbo =& JFactory::getDBO();
       $token = new JAuthToolsToken($dbo);

A sizable chunk of code. So we check if the user ID has changed (typically from unauthenticated to authenticated, we could also just check if the user ID != 0 as well). We then import the token login library, grab a copy of the database object and then create a new token.

       $token->set('username', $user->username);
       $token->set('expiry', time() + 3600); // now + 1 hr (60 * 60)
       $token->set('logins', 1);
       $token->set('landingpage', $landingpage);
       $token->store();

So with the token, we set the username to be that of the currently authenticated user (which we know is correct), set the expiry to be the present time plus an hour. Since this data is only ‘temporary’ we don’t bother with JDate and just use the server time. If the server transitions to or from daylight savings there could be an issue but since the user should be redirected rather quickly that seems like an unlikely possibility. We set the number of logins that the token is valid for, which for this case is only one and then we set the token’s landing page to be the value of $landingpage that we set before. Once we’ve set all of the data we call the ‘store’ function to save all of this to the database which will also trigger the generation of the login token.

       $session =& JFactory::getSession();
       $session->destroy();
       $app =& JFactory::getApplication();
       $app->redirect($token->generateLoginUrl());

Since the session we’re currently in is invalid, we destroy it for a bit of extra security and then we redirect the user to the token login component. Since this request will get proxied as a redirect to the real site (hopefully the proxy doesn’t rewrite the redirect header coming back otherwise this will fail), token login can then authenticate the user (again) and create a session for them without the proxies’ interference. There is however one last part of our component, which is the else case for if the user doesn’t get detected:

} else {
       $app =& JFactory::getApplication();
       $app->redirect('index.php', JText::_('Invalid SSO Request'));
}

So if we don’t detect anything, redirect the user to index.php with the message ‘Invalid SSO Request’. Too easy almost!

So for reference below is the final completed component file, don’t forget to update the values of $landingpage and $autocreate:

<?php
defined('_JEXEC') or die('nachos libre!');
$landingpage = 'http://www.google.com';
$autocreate = false;
$user =& JFactory::getUser();
$oldid = $user->id;
jimport('jauthtools.sso');
jimport('jauthtools.usersource');
$sso = new JAuthSSOAuthentication();
$sso->doSSOAuth($autocreate);
if($oldid != $user->id) {
       jimport('jauthtools.token');
       $dbo =& JFactory::getDBO();
       $token = new JAuthToolsToken($dbo);
       $token->set('username', $user->username);
       $token->set('expiry', time() + 3600); // now + 1 hr (60 * 60)
       $token->set('logins', 1);
       $token->set('landingpage', $landingpage);
       $token->store();
       $session =& JFactory::getSession();
       $session->destroy();
       $app =& JFactory::getApplication();
       $app->redirect($token->generateLoginUrl());
} else {
       $app =& JFactory::getApplication();
       $app->redirect('index.php', JText::_('Invalid SSO Request'));
}
14 comments

14 Comments so far

  1. Ole March 25th, 2009 7:28 pm

    Hello Sam

    Thanks for the explanation. I have installed JAuthTools 1.5.4 Core, I’m able to generate a token and login.

    However, I don’t understand how you proxy a username to Joomla? Is it possible you can explain it with a little more details?

    Best Regards
    Ole

  2. pasamio March 25th, 2009 10:55 pm

    The issue in this case was that there was a server that authenticated the user and in that instance acted as a proxy for the user passing along the authenticated username via a server variable. So the first request to Joomla! is through the authentication server proxy and then the next request comes from the actual client. This causes issues because Joomla! creates the session for the proxy server and ties it to that instead of the actual client so when the client connects again to Joomla!, a new session is created with their true IP address not that of the authentication server which means that the user isn’t logged in. In this case it was a bit of a hack to get this to work properly but its an interesting application of technology to solve a problem.

  3. yellen April 18th, 2009 12:13 am

    I am experiencing this same issue. I am using Apache on a ubuntu box, kerberos is working because the ssochecker get the username from the AD. My users get authenticated and as soon as they click around the joomla site, they get disconnected.

    Are there any hopes that you will release this component?

  4. pasamio April 18th, 2009 10:42 am

    What Apache auth handler are you using to get Kerberos to work?

    I haven’t thought of putting it into a release but if there is sufficient demand I could probably do a few extra things and release it out.

  5. yellen April 20th, 2009 9:44 pm

    I configured the Kerberos auth in the virtual host config file like so (I didnt you an .htaccess file):

    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
    AuthType Kerberos
    AuthName “Enter your Login”
    Require valid-user
    KrbMethodNegotiate On
    KrbMethodK5Passwd On
    KrbAuthRealms MYREALM.LAN
    Krb5KeyTab /etc/apache2/keytab/kerbjoomla-http.keytab

    BTW I had to add the site to IE Local Intranet to have it working without the password.

  6. pasamio April 21st, 2009 12:36 am

    Yeah, that’s not an uncommon fix as IE won’t forward credentials over the internet for security reasons. The other alternative is if you have a proxy and your site doesn’t go through a proxy it should work fine because IE automatically defines it as “local intranet”. Vista also introduces other interesting issues as well that broke stuff particularly with Sharepoint but if you explicitly put it things should be fine.

    It looks fine, certainly nothing wrong with that configuration. So transitioning between links on the site after the initial hit causes the user to lose their identity? Seems very strange. Can you email me with pasamio at gmail.com and I’ll find the source of the article and send it to you for testing.

  7. yellen April 23rd, 2009 6:49 pm

    Hi again,
    I would be really like to try it out 🙂

    BTW I’ve sent you an email so you can have my email address

  8. pasamio April 27th, 2009 10:18 pm

    I got your email, apologies for not getting back earlier but the email was from a .lan address. I’ve sent you a copy using the email’s you’ve provided to this site for your comments so you should get it. I was also a bit behind as well since I couldn’t immediately find the file.

  9. yellen May 14th, 2009 7:28 pm

    Hi again,
    I havent been able to use this, but I would like to point out something weird. First I would like to point out that the test are runned without this component, only your published component were used.

    Okay here we go.

    To test the HTTP single sign on, I use a vhost on apache. the intranet without kerberos auth is on tech.ieccdl.lan:80 and with kerberos auth is on tech.ieccdl.lan:84

    I add tech.ieccdl.lan to intranet sites on IE.

    I go to tech.ieccdl.lan and I am logged out. This is normal.

    I go to tech.ieccdl.lan:84 and I am logged on. This is normal, Kerberos is working.

    I click the menu and I am logged out. This is the known issue.

    I reload the page and I am logged on again. This is normal, Kerberos is working.

    If I now type in IE7 tech.ieccdl.lan, I remain logged on. Why? beats me… If I click on menu I am still logged on… I can browse the whole site and remain logged on… WHY?!!

    I’ve tried the SSO on port 80 and I still get disconnected when browsing the site.

    Do you understand this?

  10. pasamio May 14th, 2009 10:23 pm

    To be honest, I can’t say I do understand it, it sounds rather weird. What happens if you use Firefox? There is also some funkiness that might occur if you have more than one SSO system operating, so if you have the plugin and the module running at the same time these can conflict with each other and cause awkward behaviour. The same goes for any component that uses SSO to log the user in itself, this can conflict with the rest of the system and cause weirdness.

  11. yellen May 15th, 2009 11:58 pm

    I didn’t mention it in my previous message, but Firefox gives the same results.

    From what you just said, it could occur because of some duplicate SSO system? Maybe this is the problem. What I am trying to do is have the HTTP authtentication enabled with group mapping. There are no non-AD users. I’ve enabled the following Authentication Plugins and Modules:
    >>> Plugins
    – Authentication – Joomla
    – Authentication – LDAP
    – Authentication – Advanced LDAP
    – SSO – HTTP
    – System – JAuthTools Synchronization Plugin
    – System – Single Sign On
    – User – Joomla!
    – User Source – LDAP
    – User Source – Session
    >>> Modules
    None

    Are there some Plugins that need to be diabled?

  12. pasamio May 16th, 2009 12:06 am

    The only items that matter are the modules, the System – Single Sign On and any component that hooks into the SSO system (tokenlogin in part, com_sso and any other component that hooks in such as the component written in this tutorial).

    It seems a bit strange, I’m not quite sure what the answer is without digging around and having a look through things. I think I need to clone myself :S

  13. Michael December 16th, 2011 7:14 pm

    Hi,

    sorry to bring this up after a while. But is there a way in batch creating tokens? With a few hundred logins you cannot create the token manually.

    Thanks

  14. pasamio December 17th, 2011 2:21 pm

    You could use the library to build a component similar to the one that I released to batch provision tokens. There isn’t a way in the provided applications as it really isn’t designed to be created manually but via a scripted process (e.g. when you mail something or by providing a link in the site).

Leave a comment

%d bloggers like this: