Simple Single Sign-On for PHP (Ajax compatible)

by Arnold Daniels on 04/18/2009

Associated websites often share user information, so a visitor only has to register once and can use that username and password for all sites. A good example for this is Google. You can use you google account for GMail, Blogger, iGoogle, google code, etc. This is nice, but it would be even nicer if logging in for GMail would mean I’m also logged in for the other websites. For that you need to implement single sign-on (SSO).

There are many single sign-on applications and protocols. Most of these are fairly complex. Applications often come with full user management solutions. This makes them difficult to integrate. Most solutions also don’t work well with AJAX, because redirection is used to let the visitor log in at the SSO server.

I’ve written a simple single sign-on solution (400 lines of code), which works by linking sessions. This solutions works for normal websites as well as AJAX sites.

Without SSO

Let’s start with a website that doesn’t have SSO.
No SSO
The client requests the index page. The page requires that the visitor is logged in. The server creates a new session and sends redirect to the login page. After the visitor has logged in, it displays the index page.

How it works

When using SSO, when can distinguish 3 parties:

  • Client – This is the browser of the visitor
  • Broker – The website which is visited
  • Server – The place that holds the user information

The broker will talk to the server in name of the client. For that we want the broker to use the same session as the client. However the client won’t pass the session id which it has at the server, since it’s at another domain. Instead the broker will ask the client to pass a token to the server. The server uses the token, in combination with a secret word, to create a session key which is linked session of the client. The broker also know the token and the secret word and can therefore generate the same session key, which it uses to proxy login/logout commands and request info from the server.

First visit

-> Try it! (jan/jan1)<-

When you visit a broker website, it will check to see if a token cookie already exists. It it doesn’t it, the broker sends a redirect to the server, giving the command to attach sessions and specifying the broker identity, a random token and the originally requested URL. It saves the token in a cookie.

The server will generate a session key based on the broker identity, the secret word of the broker and the token and link this to the session of the client. The session key contains a checksum, so hackers can go out and use random session keys to grab session info. The server redirects the client back to the original URL. After this, the client can talk to the broker, the same way it does when not using SSO.

The client requests the index page at the broker. The page requires that the visitor is logged in. The broker generates the session key, using the token and the secret word, and request the user information at the server. The server responds to the broker that the visitor is not logged. The broker redirects the client to the login page.

The client logs in, sending the username and password to the broker. The broker sends the username and password to the server, again passing the session key. The server returns that login is successful to the broker. The broker redirects the client to the index page. For the index page, the broker will request the user information from the server.

Visiting another affiliate

-> Try it! <-

You visit another broker. It also checks for a token cookie. Since each broker is on their own domain, they have different cookies, so no token cookie will be found. The broker will redirect to the server attach to the user session.

The server attaches a session key generated for this broker, which differs from the one for the first broker. It attaches it to the user session. This is the same session the first broker used. The server will redirect back to the original URL.

The client requests the index page at the broker. The broker will request user information from the server. Since the visitor is already logged in, the server returns this information. The index page is shown to the visitor.

Using AJAX / Javascript

-> Try it! <-
SSO and AJAX / RIA applications often don’t go well together. With this type of application, you do not want to leave the page. The application is static and you get the data and do all actions through AJAX. Redirecting an AJAX call to a different website won’t because of cross-site scripting protection within the browser.

With this solution the client only needs to attach the session by providing the server with a token generated by the broker. That attach request doesn’t return any information. After attaching the client doesn’t talk at all to the server any more. Authentication can be done as normal.


The client check for the token cookie. It it doesn’t exists, he requests the attach URL from the broker. This attach url includes the broker name and the token, but not a original request URL. The client will open the received url in an <img> and wait until the image is loaded.

The server attaches the browser session key to the user session. When it’s done it outputs a PNG image. When this image is received by the client, it knows the server has connected the sessions and the broker can be used for authentication. The broker will work as a proxy, passing commands and requests to the sso server and return results to the client.

To conclude

By connecting sessions, you give the broker the power to act as the client. This method can only be used if you trust all brokers involved. The login information is send through the broker, which he can easily store if the broker has bad intentions.

Don’t be square, please share!

Demo
Broker ‘Alex’
Broker ‘Binck’
AJAX broker – created by Lukasz ‘Uzza’ Lipinski using Ajax.org PlatForm.

Play around, logging in and out at different brokers. Refresh the other after. Available users:
jan / jan1
peter / peter1
bart / bart1
henk / henk1

Download
Download the code @ github
2009-11-16: Updated the software with bugfixes mentioned in comments + alternative for using symlinks.

If I overlooked security issues with this SSO implementation, please leave a comment below.

This is a simple implementation of SSO. If you want enterprise stuff have a look at Novell Single Sign-On.

Arnold Daniels

I've spend a big part of my life behind a computer, learning about databases (MySQL), programming (PHP) and system administration (Linux). Currently I playing with HTML5, jquery and node.js.

More Posts

Follow Me:
TwitterLinkedIn

There are 276 comments in this article:

  1. 18 April 2009Daniel says:

    Nicely written article. However, I can’t help but feel that you are trying to solve the same problem OpenID is solving, just in a different way …

    Why implement this, when OpenID exists?

    ReplyReply
  2. 18 April 2009FACORAT Fabrice says:

    can be useful for someone willing to use SSO in his enterprise, for example between different intranet/extranet solutions.

    ReplyReply
  3. 20 April 2009caleng says:

    now problem

    user A and user B use the same pc, user A login but don’t logout, when user B visit this website, then user B use user A cookie.

    ReplyReply
  4. 20 April 2009Arnold Daniels says:

    Daniel: OpenID is shared authentication, but not single sign-on. You need to login at each site. The difference is explained at wikipedia http://en.wikipedia.org/wiki/Single_sign-on#Shared_Authentication_Schemes_which_are_not_Single_Sign-On.
    Also with this solution you have all the user information in one place. OpenID is purely authentication only.

    Caleng: This problem you would also have when you don’t do single sign-on, but authenticate at the website as normal. Therefore this is not within the problem space of SSO. If you already have a way of solving this, you can still apply this when using this SSO solution.

    ReplyReply
  5. 18 May 2009onge says:

    Is it possible to just take and use (and modify) this solution, or you have some specific licence requirements on in?

    ReplyReply
  6. 19 May 2009Arnold Daniels says:

    The AJAX part of this solution uses Javeline Platform, which is LGPL licensed.

    The rest of the software (including all of the PHP code) is in public domain and can be used freely. enjoy ;)

    ReplyReply
  7. 25 May 2009woras says:

    Hi, good tutorial. Based on this one I coded my own SSO server. Just one suggestion to yours solution it’s better to store client token in session, because cookies on client can be disabled. And it’s a good idea to use HTTPS :) between SSO server and Broker

    ReplyReply
  8. 26 May 2009Hermes Alves says:

    Great tutorial! Thanxs ;)

    ReplyReply
  9. 10 June 2009Stefan says:

    Hi Arnold,

    first of all, thanks for the nice tutorial.
    Nevertheless, I do have a question. In the source code I came across the checksum generating functions and figured that you are using the $_SERVER['REMOTE_ADDR'] var for that. Now my question is: Why? Doesn’t that prevent cross-server-SSO-solutions?

    Thanks,
    Stefan.

    ReplyReply
  10. 11 June 2009Arnold Daniels says:

    Hi Stefan,

    $_SERVER['REMOTE_ADDR'] is the IP address of the client. It is used to prevent session hijacking. It doesn’t ruin cross-server SSO.

    ReplyReply
  11. 23 June 2009Thanh says:

    Hi !
    I can’t setup server SSO. Server error. Can You send full source code and guide detail about SSO ?
    Thanks

    ReplyReply
  12. 26 June 2009Ram says:

    Hi,

    Iam getting curl_init() error , when iam using download files of SSO are using in local system.

    Please help me.

    ReplyReply
  13. 26 June 2009Arnold Daniels says:

    Ram, are you sure that you have the curl extension? If so, post the exact PHP error and we’ll have a look.

    ReplyReply
  14. 1 July 2009Rosa says:

    Hi Arnold Daniels!
    I can’t setup SSO. I have an error:
    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: Not attached’ in C:\AppServ\www\SSO\broker\sso.php:161 Stack trace: #0 C:\AppServ\www\SSO\broker\index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in C:\AppServ\www\SSO\broker\sso.php on line 161

    I use Apache server & PHP 5.2.6. Please help me fix it.

    Thanks so much.

    ReplyReply
  15. 1 July 2009Arnold Daniels says:

    Hi Rosa,

    This won’t work on Windows since it uses symlinks. You could make it work on Windows by rewriting server/sso.php to work without symlinks. Look at lines 132/133 and function sessionStart().

    I’m sorry I can’t help you any further. Good luck.
    - Arnold

    ReplyReply
  16. 6 July 2009Rosa says:

    Hi Arnold Daniels,
    - I fixed error above by change row 205 in borker/sso.php:
    CURLOPT_COOKIE -> CURLOPT_COOKIESESSION.Is it OK?
    - Now I get a error at value $sso->getInfo(). When log-in, value $sso->getInfo() in login.php is Array but it redirect index.php by header function (row 9 at login.php), $sso->getInfo() is Blank. So I can’t log-in successful.Why $sso->getInfo() is don’t save???

    Can you help me check it? I only change your code as above.
    Thanks,
    Rosa

    ReplyReply
  17. 6 July 2009Arnold Daniels says:

    Hi Rosa,

    No that is not right at all. The issue is not with the broker, so there is no need to change that code. You’re not not getting the previous error because the broker isn’t working correctly anymore.

    At line 132/133 of server/sso.php the program creates a symlink. Since Windows doesn’t support symlinks, the broker session id is not being attached (=symlinked to) to the client session id.

    You need to replace the use of symlinks by an alternative solution. For instance you can create a file with the name of the broker session id and write the client session id in it. In function sessionStart() you than need to readout that file and use it as session id. Something like:

    $client_session = file_get_contents($broker_session_file);
    session_id($client_session);
    session_start();

    This really is all the support I’m willing to give on this matter. Otherwise please switch to a linux based system.

    ReplyReply
  18. 13 July 2009sudhir says:

    This exactly what I was looking for my site http://www.ramanandi.org .

    I have a social network and a matrimonial site, I use symfony, and I need to share the userbase and a central authentication system.

    I think, it would be really helpful

    Thanks

    ReplyReply
  19. 20 July 2009yancey says:

    Thanks for your good sample.
    It’s work fine , but don’t know why I can’t use session_start()
    on my page !?
    It will bring out crash , is it normal situation ?

    ReplyReply
  20. 20 July 2009Arnold Daniels says:

    A program should never crash, so that is not normal.
    (I’ll talk to yancey and add comments if that is useful)

    ReplyReply
  21. 28 July 2009Bab says:

    Hi Arnold Daniels!
    I can’t setup SSO. I have an error:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: ‘ in /var/www/SSO/broker/sso.php:161 Stack trace: #0 /var/www/SSO/broker/index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in /var/www/SSO/broker/sso.php on line 161

    I use Apache server & PHP 5. Please help me fix it.

    Thanks so much.

    ReplyReply
  22. 29 July 2009Azwan says:

    Hi,

    Thanks for this great article, very useful to me. I will try it and give feedback here.

    Thanks again.

    ReplyReply
  23. 29 July 2009Arnold Daniels says:

    Hi Bab,

    On line 161 of broker/sso.php, the response of the server is checked. The exception that is thrown on a non-200 status is not really clear though.

    Please replace the line 161 by:

      default:  throw new Exception("SSO failure: The server responded with a $ret status" . (!empty($body) ? ': "' . substr(str_replace("\n", " ", trim(strip_tags($body))), 0, 256) .'".' : '.'));
    

    That should give you a clue what’s going wrong.

    ReplyReply
  24. 30 July 2009Bab says:

    Thanks Arnold’s

    Thanks for your help

    ReplyReply
  25. 31 July 2009Rob says:

    Thanks Arnold for such a nice piece of art:D

    I’m trying to run it in Windows changing the symlink for a file as you said in #17 to Rosa but I don’t know how to get the $broker_session_file var.

    Thanks in advance

    Rob

    ReplyReply
  26. 7 August 2009David says:

    Hi Arnold,

    Here’s the error message I get :

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status1: “Not attached”.’ in /var/www/SSO/broker/sso.php:162 Stack trace: #0 /var/www/SSO/broker/index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in /var/www/SSO/broker/sso.php on line 162

    Can you please help

    ReplyReply
  27. 7 August 2009Arnold Daniels says:

    Rob: Sorry for responding so late. The $broker_session_file var can be determined from the session id that the broker send. It could be something like

    $broker_session_file = (session_save_path() ? session_save_path() : sys_get_temp_dir()) . '/broker_' . session_id();
    

    In that case you should save the client session id (line 132/133) as

    $broker_session_file = (session_save_path() ? session_save_path() : sys_get_temp_dir()) . '/broker_' . $this->generateSessionId($_REQUEST['broker'], $_REQUEST['token']);
    if (!file_exists($broker_session_file)) file_put_contents('sess_' . session_id(), $link);
    

    David: Not attached means that PHP failed to create the symlink in function ‘attach()’ of server/sso.php.

    ReplyReply
  28. 8 August 2009Arnold Daniels says:

    Windows Vista and Server 2008 appear to have symlink support. In PHP 5.3 the symlink() function will work for these operation systems.

    If you’re running PHP 5.2 with Vista or Server 2008, try using the following function:

    define('SYMLINK_FILE', 0);
    define('SYMLINK_DIR', 1);
    define('SYMLINK_JUNCTION', 2);
    function symlink ($target, $link, $flag = SYMLINK_FILE) {
        switch ($flag) {
           case SYMLINK_DIR: $pswitch = '/d'; break;
           case SYMLINK_JUNCTION: $pswitch = '/j'; break;
           case SYMLINK_FILE:
           default: $pswitch = ''; break;
        }
        // Change / to \ because it will break otherwise.
        $target = str_replace('/', '\\', $target);
        $link = str_replace('/', '\\', $link);
        return exec('mklink ' . $pswitch . ' ' . escapeshellarg($link) . ' ' . escapeshellarg($target));
    }
    
    ReplyReply
  29. 3 September 2009gerard says:

    Great blog post. Thanks for the download. I am definitely going to adapt it for our code here.

    Haven’t run it myself, but I echo Stefan’s question: in server/sso.php, is $_SERVER['REMOTE_ADDR'] the IP address of the client or the broker? Looks to me that it is of the broker, i.e. the IP address of the server that makes the curl call. If so, then it does limit cross-server SSO. My guess is that your demo works because your virtual hosts are all on the same box. Am I wrong in this thinking?

    ReplyReply
  30. 5 September 2009Owen Rudge says:

    I had a play round with this earlier, and found that it gets rather messy if IPv6 becomes involved. In my case, I was connecting to the broker by IPv4, but the broker and the server had an IPv6 connection between them. This caused a fair bit of confusion with matching up IP addresses and checksums. After hacking away at it, I found the easiest thing to do for now is to force everything to be IPv4 (although, it’d be possible to detect whether the client connection is IPv4, and if so, set the CURL_IPRESOLVE_V4 flag between the broker and the server; if not, use IPv6. Unfortunately, that flag was only introduced in PHP 5.3.0). I guess the problem isn’t IPv6 per se, it’s just the mixing of IPv4 and IPv6. The sooner the whole Internet moves over to IPv6, the better. ;)

    Anyway, thanks for this code, it has proven useful, and is now working quite well. I have taken the code a step further and improved the security of logins – specifically, having the username/password handled by a form on the server, rather than the broker, therefore meaning the broker does not get a hold of the password at all. This form is then embedded via an IFRAME into the actual page.

    Oh, and while I remember, if anybody wants to access the server via SSL, and you’re getting “The server responded with a 0 status”, it may be due to an invalid/unauthenticated SSL certificate. If so, add this:

    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

    to the serverCmd routine in sso.php.

    Additionally, if you are running your lighttpd as the web server for your server, you may get HTTP 417 errors (see http://redmine.lighttpd.net/issues/1017). To fix that, place:

    curl_setopt($curl, CURLOPT_HTTPHEADER, array(‘Expect:’) );

    within the “if (isset($vars))” block in serverCmd.

    Those are some of the issues I’ve had, and managed to sort out. Hopefully it will prove useful for people!

    ReplyReply
  31. 6 September 2009Arnold Daniels says:

    Gerard: Look at the comment ‘// Broker session’ and ‘// User session’. Session id’s of brokers start with ‘SSO-’, therefore the code doesn’t get to the point of $_SERVER['REMOTE_ADDR'] if a broker connects. First the client connects directly to the server and leaves his IP address (in $_SESSION). That IP address is later used to validate the session id of the broker, to make sure the client talking to the broker is the same that talked to the server.

    This solution most definitely works cross server. The ‘Binck’ broker is on another server.

    $ host sso-server.adaniels.nl
    sso-server.adaniels.nl has address 82.94.236.135
    $ host sso-alex.adaniels.nl
    sso-alex.adaniels.nl has address 82.94.236.135
    $ host sso-binck.jasny.net
    sso-binck.jasny.net has address 82.94.182.130
    

    Owen Rudge: Thanks for your input Owen. Those are some great comments about issues that might occur. I’m sure that will help a lot of people.

    Since I work at a company that make AJAX apps, using an iframe won’t work for us. It really boils down to if both applications have the same owner and if the developer of the broker app can be trusted. If not, than you indeed don’t want to pass the password to the broken.

    Perhaps you want to share your code on your blog (I’ll add a link). I’m sure people will be interested.

    ReplyReply
  32. 7 October 2009test says:

    if (!file_exists($link)) $attached = symlink($targetDir, $file);, its nor working in my server. its always return null.

    ReplyReply
  33. 8 October 2009Arnold Daniels says:

    test: Your code looks flawed. Shouldn’t it be
    if (!file_exists($link)) $attached = symlink($targetDir, $link);

    Make sure you see E_NOTICE and E_WARNING errors, so you can see why the link is not created.
    Ps. This is not a help forum. So plz don’t ask non- and semi-related questions on this blog. Go to http://forums.devnetwork.net instead.

    ReplyReply
  34. 13 October 2009Garry says:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 0 status.’ in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\broker\sso.php:161 Stack trace: #0 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\broker\index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\broker\sso.php on line 161

    Your advice 23 does not help [in fact this you publish exactly same line you want us to replace].
    What do you mean in post 27, you want to place this code inside function ‘logout’? I do not think so…

    And same about 28 – WHERE you want to place this function?

    ReplyReply
  35. 13 October 2009Arnold Daniels says:

    Garry: I already changed the line of [23] in the source.
    Probably the server didn’t really return a 0, but the curl call fails.

    Add the following on line 216:

    if (curl_errno($curl) != 0) throw new Exception("SSO failure: HTTP request to server failed. " . curl_error($curl));
    

    Function ‘symlink’ [28], is used on the SSO server. You don’t need [27] if you use [28].

    ReplyReply
  36. 5 November 2009yunuz says:

    Parse error: syntax error, unexpected T_NEW in /usr/local/apache2/htdocs/nswapps/login/sso/broker/sso.php on line 120

    I use Apache server & PHP 4. Please help me fix it.
    urgent needed..

    ReplyReply
  37. 5 November 2009Chris says:

    I like the SSO server, really interested in using it but the way it works is the slightest bit beyond me, I would like to make a minor change to it where the brokers and the users are all stored in two separate mysql tables. Does anyone know how I would do this or has someone already achieved this and is willing to send me a copy. Thanks.

    ReplyReply
  38. 5 November 2009Arnold Daniels says:

    Yunuz: This code (or any other code I’ve ever posted or will post) won’t work with PHP 4. Upgrade to PHP 5, PHP 4 has been dead for over a year.

    Chris: Look at function generateSessionId() and generateAttachChecksum(). The secret phrase is fetch using self::$brokers[$broker]['secret']. You can replace that by a query like “SELECT secret FROM broker WHERE name=’$broker’”.
    Further you should replace function login() with something more sophisticated. You can probably replace this with your existing auth login method. Also replace the info() method.

    ReplyReply
  39. 8 November 2009ubuntu9 says:

    Hi,
    I just downloade the file sso.zip and unzip it to my ubuntu server root (ver 9.10). Change the sso server link like this:

    public $url = “http://localhost/server/sso.php”;

    Run the first time, it said curl_init is undefined, so i update php5-curl using this:

    apt-get install php5-curl

    The update is successful and then i restart apache2 server.

    The next try, i got this error:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status: “Not attached”.’ in /var/www/broker/sso.php:162 Stack trace: #0 /var/www/broker/index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in /var/www/broker/sso.php on line 162

    Can anyone help me out? any other settings i need to make?

    I guess the sso server and the broker on the same machine doesn’t matter, right?

    Thank you

    ReplyReply
  40. 9 November 2009Arnold Daniels says:

    ubuntu9: Not attached means that the session id used by the broker is not linked to the session of the client.

    Enable error logging (http://nl3.php.net/manual/en/errorfunc.configuration.php) and look at the error_log. You’ll probably see ‘Failed to attach; Symlink wasn’t created’, with one or more warning above it, telling you why the symlink wasn’t created.


    Also I want to point out that using localhost or a LAN might cause issues. If the broker is on the LAN but the SSO server isn’t, the $_SESSION['client_addr'] is different. The server will respond with ‘Invalid session id’. Since you’re getting a ‘Not attached’ message, this is not the issue in your situation.

    ReplyReply
  41. 10 November 2009ubuntu9 says:

    Thanks, Arnold for your explanation.

    Yes, you are quite correct, localhost should not be used in any case. The actual server name or IP address should be used instead. Deploy both broker and sso server on the same box may cause issue too.

    In my case, now i’m using two LAN machines:
    1. server1: windows 2003 with curl loaded, used as broker server
    2. server2: ubuntu 9.10, used as sso server

    in sso.php of the broker, i change sso url like this:
    public $url = “http://server2/server/sso.php”

    Using firefox 3.5.5, the first try to: http://server1/broker/index.php always result in indefinite redirect. The browsers display something like this:

    In the address bar: http://server1///////////broker/index.php

    Details of the error:

    ————————————————————
    The page isn’t redirecting properly

    Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

    * This problem can sometimes be caused by disabling or refusing to accept
    cookies.
    ————————————————————

    Look at the apache log file i see:
    ————————————————————
    192.168.84.246 – - [10/Nov/2009:13:10:09 +0700] “GET /broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:09 +0700] “GET //broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:09 +0700] “GET ///broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:09 +0700] “GET ////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET /////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET //////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET ///////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET ////////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET /////////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET //////////broker/index.php HTTP/1.1″ 307 -
    192.168.84.246 – - [10/Nov/2009:13:10:10 +0700] “GET ///////////broker/index.php HTTP/1.1″ 307 -

    ————————————————————

    I manually re-enter the URL like this http://server1/broker/index.php

    Now the login page showned up.

    I have no idea why there are so many redirects here? What can be the reason of this? I appreciate your help

    ReplyReply
  42. 10 November 2009Arnold Daniels says:

    ubuntu9: Try to see what is happening with the Tamper Data or Live HTTP headers plugin. You’re probably being redirected back-and-forth from broker to server. The most obvious reason for this is (as Firefox already suggested), an issue with the session_token cookie.

    The additional slash might be because $_SERVER["REQUEST_URI"] starts with a slash, adding the slash in the redirect url. This shouldn’t be a big issue, though see if it helps when you replace line 57 of broker/sso.php with

    header("Location: " . $this->getAttachUrl() . "&redirect=". urlencode("http://{$_SERVER["SERVER_NAME"]}{$_SERVER["REQUEST_URI"]}"), true, 307);
    
    ReplyReply
  43. 12 November 2009ubuntu9 says:

    Thanks Arnold. Your solution worked. $_SERVER["REQUEST_URI"] starts with a slash so there is no need for another slash in header function. Now everything works for me.

    To help other developers make this SSO solution work for them, i would like to summarize my experience here:

    1. The SSO server must be a unix/linux server. As Arnold said, windows 2008 and vista may work, but i’m not sure.
    2. LOCALHOST cannot be used in any case, must be server name or ip address.
    3. Change line 57 in broker/sso.php as below (remove the slash before $_SERVER["REQUEST_URI"])

    header(“Location: ” . $this->getAttachUrl() . “&redirect=”. urlencode(“http://{$_SERVER["SERVER_NAME"]}{$_SERVER["REQUEST_URI"]}”), true, 307);

    Looking at the server/sso.php, i guess this solution will not work if there are many visitors behind a proxy server. Because their IP address will be the same for all (to the outside world). This make the SSO server to treat them as the same client.

    Can anyone confirm this? Thanks.

    ReplyReply
  44. 15 November 2009jirin says:

    Thank you for your article. Could you write solution for working without symlink()? I tried solution you write in article, but it is not working. I try to do it for 3hours but no success. I have probably permited symlink() on hosting, I tried it on 2 different hosting

    ReplyReply
  45. 16 November 2009Arnold Daniels says:

    jirin: The code is just mend to be an example, not an open source project. However, since there have be so many requests to make this work without symlinks. I’ve modified the code so it can do so. Simply set the links_path property to something like ‘/tmp’ and the SSO server will use files containing the session id, instead of symlinks.

    PS. Don’t forget to delete all cookies (broker and server) after changing links_path.

    ReplyReply
  46. 16 November 2009jirin says:

    Thank you very much Arnold, it looks working! Once more thanks

    ReplyReply
  47. 18 November 2009Kevin says:

    Thanks Arnold, I almost have this fully working. However, when a users IP changes, eg. from LAN to Wireless, I get the 406 – Invalid Session Id error. I know this is because the $_SESSION['client_addr'] != the $SERVER['REMOTE_ADDR'] originally stored in the session. What is the best way to reset the client state? I don’t want to have them clear cookies each time this happens. I’m having trouble figuring out where to put the logic as well. Thank you.

    ReplyReply
  48. 18 November 2009Arnold Daniels says:

    Kevin: The IP check is there against session hijacking. You could disable that by simply removing all $_SERVER['REMOTE_ADDR'] entries. They’re not essential for making this SSO method work, but only increase security.

    Also, instead of using $_SESSION['client_addr'] to check if a session is initialised (line 86), use $_SESSION['init'] and set that to true (line 103).

    ReplyReply
  49. 20 November 2009Kevin says:

    Hi Arnold,
    Thank you for the help on the REMOTE_ADDR. I am having a separate issue regarding infinite redirects. I find this happens when the client somehow holds a ‘session_token’ linked to session ‘a’ using broker ‘x’, and a ‘session token’ linked to session ‘b’ using broker ‘y’. How can I protect against this case?

    ReplyReply
  50. 21 November 2009Arnold Daniels says:

    Kevin: Hmm, that’s a bit of an edge-case. I must admit that I didn’t think about that occurring.

    I tried to reproduce this, by deleting only the session of the sso-server. In that case the 2 brokers are using different server sessions. However, I’m not able to reproduce the infinite redirecting. Please post how this redirection goes by using something like fiddler or tamper data.

    ReplyReply
  51. 27 November 2009Amit says:

    Hi,
    I am looking forward to use it. Since it is not not using symlinks so I can easily use this on windows server as well. Very basic question: Do I need seperate server for broker?

    Thanks,
    Amit

    ReplyReply
  52. 27 November 2009Arnold Daniels says:

    Amit: The server needs to be on a different domain than the brokers. Using a different subdomain like ‘auth.example.com’ for the server and ‘www.example.com’ for the broker, will work as well. The server/brokers can be on a different fiscal server, but don’t need to be.

    ReplyReply
  53. 4 December 2009Mathias says:

    Arnold,

    I see where it checks for $_SESSION['client_addr'] and destroys the session if it’s not set. But I don’t see where this is actually set.
    My implementation hits this session_destroy() everytime. Where in the class were you intending to define the ‘client_addr’ session var?

    Thanks.

    ReplyReply
  54. 4 December 2009Arnold Daniels says:

    $_SESSION['client_addr'] is set by the client as it creates the session on line 103.

    If you are getting ‘Not attached’ each time, the client is either not connecting to the server or the symlink (or link file) isn’t created correctly. Have a look at the previous comments.

    ReplyReply
  55. 5 December 2009Mathias says:

    I have the client attaching correctly and the symlink is working. The problems seems to be that there is a sessionStart() at the beginning of the attach(). Here within the sessionStart() it never gets to the bottom where it sets the client_addr. It always matches on the session_name() and then fails on the client_addr.
    If I just comment this session_destroy() segment out – I’m able to attach just fine.

    ReplyReply
  56. 5 December 2009Thiet Doan says:

    Hi Arnold,

    Firstly, I want to thank you about your SSO implementation.
    When I deployed your source code in my local computer, it worked very well.
    But It always gets 403 for bidden error when I deploy it to my hosting.
    - SSO server: http://service.mio.vn/server/index.
    - SSO client: http://mio.vn/customer/login

    Any ideas?

    Thank you,

    ReplyReply
  57. 5 December 2009Thiet Doan says:

    I have just modified SSO implementation to make it do not use symlink function by saving data to a table in database.

    Firstly, you can create a table named “links”:

    CREATE TABLE IF NOT EXISTS `links` (
      `id` int(11) unsigned NOT NULL auto_increment,
      `code` varchar(128) NOT NULL,
      `link` varchar(64) default NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;
    

    Then, you should modify the server class (SingleSignOn_Server) to save data to database instead of saving it to a file.

    Just modify 2 functions sessionStart and attach as follow:

    protected function sessionStart()
    {
        if ($this->started) return;
        $this->started = true;
        
        // Broker session
        $matches = null;
        if (isset($_REQUEST[session_name()]) && preg_match('/^SSO-(\w*+)-(\w*+)-([a-z0-9]*+)$/', $_REQUEST[session_name()], $matches)) {
            $sid = $_REQUEST[session_name()];
            
            // check the ID existed or not
            $result = $database->query("SELECT `* FROM `links` WHERE `code` = '" . $sid . "'")
            if (isset($result['link'])) {
                session_id($result['link']);
                session_start();
                setcookie(session_name(), "", 1);
            } else {
                session_start();
            }
    
            if (!isset($_SESSION['client_addr'])) {
                session_destroy();
                $this->fail("Not attached");
            }
            
            if ($this->generateSessionId($matches[1], $matches[2], $_SESSION['client_addr']) != $sid) {
                session_destroy();
                $this->fail("Invalid session id");
            }
    
            $this->broker = $matches[1];
            return;
        }
    
        // User session
        session_start();
        if (isset($_SESSION['client_addr']) && $_SESSION['client_addr'] != $_SERVER['REMOTE_ADDR']) session_regenerate_id(true);
        if (!isset($_SESSION['client_addr'])) $_SESSION['client_addr'] = $_SERVER['REMOTE_ADDR'];
    }
    
    public function attach()
    {
        $this->sessionStart();
        
        if (empty($_REQUEST['broker'])) $this->fail("No broker specified");
        if (empty($_REQUEST['token'])) $this->fail("No token specified");
        if (empty($_REQUEST['checksum']) || $this->generateAttachChecksum($_REQUEST['broker'], $_REQUEST['token']) != $_REQUEST['checksum']) $this->fail("Invalid checksum");
    
        $sid = $this->generateSessionId($_REQUEST['broker'], $_REQUEST['token']);
        $result = $database->query("SELECT `* FROM `links` WHERE `code` = '" . $sid . "'")
        if (!isset($result['link'])) {
            $attached = $database->query("INSERT INTO `links`(`code`, `link`) VALUES('" . $sid . "', '" . session_id() . "')");
            if (!$attached) trigger_error("Failed to attach; Symlink wasn't created.", E_USER_ERROR);
        } else {
            $attached = $database->query("UPDATE `links` SET `link` = '" . session_id() . "' WHERE `code` = '" . $sid . "'");
            if (!$attached) trigger_error("Failed to attach; Link file wasn't created.", E_USER_ERROR);
        }
    
        if (isset($_REQUEST['redirect'])) {
            header("Location: " . $_REQUEST['redirect'], true, 307);
            exit;        
        }
        
        // Output an image specially for AJAX apps
        header("Content-Type: image/png");
        readfile("empty.png");
    }
    

    After that, you can completely remove links_path property and its initializing in __construct funnction.

    Hope it helps

    ReplyReply
  58. 7 December 2009Arnold Daniels says:

    Thiet Doan: The script doesn’t return a 403 http response, so check the URLs and otherwise look at the apache error log.

    ReplyReply
  59. 8 December 2009Mathias says:

    I guess I don’t see how line 75(server) evaluates false when it is being set every time in the cookie by the broker on line 205(broker). If this evals true everytime (mine does) it will never get to line 103 where the client_addr is set. What am I doing wrong? Should this be evaluating false the first time around?

    ReplyReply
  60. 8 December 2009Mathias says:

    Ok, I see how it’s supposed to work. It does indeed evaluate false the first time through on the attach. The session appears to be set (the first time through). But the second time the sessionStart() is fired, the $_SESSION[client_addr] is no longer set. Do you know what may cause that?

    ReplyReply
  61. 8 December 2009Arnold Daniels says:

    Mathias: If no session variables are set, the broker probably isn’t using the session file that was created by the client when connecting to server.

    On line 85 AND line 103, insert

    header('X-SessionId: ' . session_id());
    

    Use something like tamper data (firefox) or fiddler (windows) to check the HTTP headers. Check the session dir and see if the session file of the broker is a symlink to the session file of client.

    ReplyReply
  62. 15 December 2009Alex says:

    Hi Arnold,

    First I would like to thank you for your nice work! It’s so great to find this kind of help.

    I have a particular question about your single sign on. I would like to implement it on my website to allow my partners to use my API.

    At the present time, my partners insert my API on their own website for their own users. But these users have to register and then login when they come to the API pages.

    My question is, can I use your single sign on script to allow to my user’s partner to log on once only?

    And my second question is, if my partners have their own users registered in their DB, will I have to registered their users first on my own DB before? Or will I have to create accounts on the fly?

    I don’t know if I’m clear enough so please let me know,

    Thanks again,

    Alexandre

    ReplyReply
  63. 15 December 2009Arnold Daniels says:

    Alex: In this example, the SSO-server does all the authentication, though the brokers collect the username and password. That means that a.) the brokers need to be completely trusted (aka your sites). This is probably not the case for partners. And b.) it assumes that the SSO-server holds all user information and the brokers hold none.

    If the SSO-brokers hold their own user information, the role of the SSO-server changes. He no longer has to do authentication, the broker can simply tell the server that that user is logged in. The server can tell the next broker, that this user is logged in. For this the SSO-servers needs to know which user of broker A is which user on Broker B.

    Example; I’m known as ‘arnolddaniels’ on LinkedIn, but as ‘adaniels_nl’ on Twitter. LinkedIn would tell the SSO-server that ‘arnolddaniels’ has logged in. If I would visit Twitter next, Twitter would as which user is logged in. If the server would reply ‘arnolddaniels’, this would not work.

    That whole issue can be overcome by not having the brokers pass a username, but pass an e-mail adress instead. In that case, the server does not have to create any accounts (not at forehand and not on the fly).

    ReplyReply
  64. 15 December 2009Alex says:

    Hi Arnold,

    Thanks for your answer.

    I think I got it. So in my case, if I want to allow my Partners to use the single sign on for their own users, I will need to ask them to import first their users into my own DB (through a CSV file and a simple form in my front site for e.g).

    Then, once their users have been added to our DB, I could match them thanks to their email as the ID as per your suggestion.

    So finally, User A) will go to Partner site and connect to their own DB during the authentifaction, then once he will come to our API included inside the Partner site, he will be automatically recognized and logged in (so we could save information related to this particular user in our own DB when he will use our API).

    This sounds good, but I have another question: How can I have the Partner’s users list always up to date?
    I mean, I can’t ask to my Partners to update their user’s list everyday through my website thanks to a .CSV file for e.g… it’s too constraining… Do you have any idea for this?

    Alex.

    ReplyReply
  65. 15 December 2009Arnold Daniels says:

    Alex: ehh no… The server doesn’t need to have any account information of the users.

    User A will go to Partner X site. He will be redirected to the SSO-server, where a new session is created and attached. Partner X asks if the user is already logged in and the SSO-servers replies ‘no’. User A logs in at Partner X. Partner X sends the e-mail address to the SSO-server. The SSO-server will save this e-mail in the attached session.

    Now user A visits Parner Y site. He will be redirected to the SSO-server, where his existing session is attached. Parner Y asks if the user is logged in and the servers replies with the e-mail adress. Parner Y looks up the user in his own DB based on the e-mail adress and logs in the user without asking for a password.

    Do know that you need to completely trust all partners. An administrator of any partner can get into any account of any other partner, without having to specify a password. This is due to the fact that logging in to any of the partner sites means you’re logged in to all of the partner sites.

    ReplyReply
  66. 15 December 2009Alex says:

    Sorry but I have some difficulties to understand properly the whole process.

    When you said:
    “Now user A visits Parner Y site. He will be redirected to the SSO-server, where his existing session is attached. Parner Y asks if the user is logged in and the servers replies with the e-mail adress. Parner Y looks up the user in his own DB based on the e-mail adress and logs in the user without asking for a password.”

    => What happens if User A is not in Partner Y DB?
    The thing is, all my partners will have different DB (obviously) with different users so how User A could connect to Partner Y site although User A is a user of Partner X?

    Also my main goal is to allow the registered users of each of my partners to connect to my own DB / users system when they will use my API without having to sign in again (twice: first on the partner home page, and then when they come to our API included in Partner’s website pages).

    But my partners won’t accept to share their users credentials with the others partners…

    Actually, I though I could use your Single sign on like the following procedure:
    - http://getsatisfaction.com/developers/fastpass
    - http://getsatisfaction.com/developers/fastpass_technical

    Is it possible?

    Thanks again, and sorry for my misunderstanding,

    Alexandre

    ReplyReply
  67. 15 December 2009Arnold Daniels says:

    Alex: Remember, the trick of this whole method is shared sessions. The broker (the server of your partner site) can use the same session as the client, therefore the broker can do anything the client (user) would normally do. This can be logging in, but also registering, adding a product in a shopping cart, enabling a service, etc.

    After logging in on the partner site, the broker might tell the server that user ‘somebody@example.com’ has logged in. The server should return whether or not the user exists (as HTTP response). If the user does not exist, the broker can send the user information to the server, which can create a user OR the broker can simply redirect the client to register himself. If the sign-on is only 1-way, simply leave out the part where the broker requests the e-mail address of the logged in user.

    Also, if I understand correctly, sessions shouldn’t be shared between brokers. The best way to solve that is to make 1 subdomain per broker, eg:
    http://partner-x.example.com
    http://partner-y.example.com
    This can be done by a virtual host with ‘ServerAlias *.example.com’. Than get the broker name from $_SERVER['HTTP_HOST'] instead of from $_REQUEST['broker'].

    ReplyReply
  68. 23 December 2009sriman says:

    Hi Arnold,
    First I would like to thank you for your great work.
    I have two domain name like http://testsso.com/test/ and http://session.com/session/ how i will configure?.I am new to this concept can you please explain.I got the error.i am using php 5.2.3 version and apache

    Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 404 status: “Object not found! Object not found! The requested URL was not found on this server. If you entered the URL manually please check your spelling and try again. If you think this is a server error,

    Thanks
    Sriman

    ReplyReply
  69. 23 December 2009Arnold Daniels says:

    Sriman: The url to the SSO server (in broker/sso.php on line 16) is not configured correctly.

    ReplyReply
  70. 23 December 2009sriman says:

    Hi Arnold,

    Thanks for your help,After i give proper url i got the
    Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status: “Not attached”.’ in C:\xampp\htdocs\phpsvn\test\sso.php:161 Stack trace: #0 C:\xampp\htdocs\phpsvn\test\login.php(8): SingleSignOn_Broker->getInfo() #1 {main} thrown in C:\xampp\htdocs\phpsvn\test\sso.php on line 161.why its coming error.whats the problem?can you help me.

    Thanks
    Sriman

    ReplyReply
  71. 23 December 2009Arnold Daniels says:

    Sriman: Please read the comments of the properties of the class SingleSignOn_Broker and class SingleSignOn_Server. Most of them are settings. You should configuring them. Also read the comments below the article. In there this question is already answered.

    In this case, since you are using Windows, you can’t use symlinks. Instead use normal files for attaching by setting $links_path ( server/sso.php line 15) to some kind of tempdir.

    ReplyReply
  72. 24 December 2009sriman says:

    Hi Arnold,

    First of all Wishing you a Merry Christmas…..
    still i have big doubt that is i login to gmail account… now go to my localhost give that gmail url as public url in broker sso.php and url not specify the any php file just url of gmail.i configure the ur code in my localhost.is it possible to autologin in my site when i login gmail……kindly give some clarification of example….please.

    Thanks
    Sriman

    ReplyReply
  73. 24 December 2009Arnold Daniels says:

    sriman: This is an example of how to set up your own Single Sign-On system, with your own user data. It has absolutely nothing to do with Google accounts / GMail or those kind of things.

    To validate google users, you need to use OpenID. See http://code.google.com/intl/nl/apis/accounts/docs/OpenID.html

    ReplyReply
  74. 24 December 2009Arnold Daniels says:

    sriman: The download is not a install and configure application. This is an example showing how to implement SSO in your own application. Installing this software on your server should give you the exact same functionality as the demos. You can log in with the users, set on server/sso.php line 43.

    You need write your own authentication implementation, replacing login() and info().

    Again, this is just an example, not a full fledged SSO solution. If you need that, look at simpleSAMLphp.

    This is all I can say about this. Just read the article and comments carefully. You’ve asked nothing that is not explained in there.

    ReplyReply
  75. 7 January 2010Crash says:

    Very informative article. This just made things quite clear. Specially i like the part when images have been explained using http response codes.

    ReplyReply
  76. 8 January 2010Paul Harman says:

    Hi,

    Interesting article. One point I don’t quite understand is what information a second broker is passing to the SSO server which allows it to be linked to the session of the first broker. Am I correct in thinking that the client IP address is used to identify the client on multiple domains? Thus if the IP address of a logged in client is known then security is compromised?

    Thanks,
    Paul

    ReplyReply
  77. 10 January 2010Arnold Daniels says:

    Paul: No, the IP is purely against session hijacking and can be left out.

    Read the article again and look at the images more closely. Don’t try to deduce the working by looking at the code. The trick lies in the broker token that is issued by the broker, than passed to the client, which passed it to the server. The server knows who the client is by the session cookie.

    The server will generate a session key based on the broker identity, the secret word of the broker and the token and link this to the session of the client.

    ReplyReply
  78. 17 January 2010Chris says:

    Does anyone have any idea of how to customize this so that it uses a database to store brokers, users, and sessions. Need it to be able to easily scale to support anything from 3 sites to 50 sites and an unlimited number of users.

    ReplyReply
  79. 18 January 2010Nizar says:

    Thank you, it really works, We’ve implemented your code on program using CI framework. Still wondering if it can be used with Moodle.

    ReplyReply
  80. 27 January 2010Deni says:

    Hi Arnorld,
    it works fine on my localhost, nice share..
    @nizar : it would be nice if you could share your implementation on CI application…

    ReplyReply
  81. 7 February 2010sarada says:

    Hi Arnold,
    I copied ur server/sso.php to sso.sahooshare.com and broker directory contents to http://www.konnectp.com, but still it won’t work.

    It displays the below error when i try to access http://www.konnectp.com.

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: HTTP request to server failed. couldn’t connect to host’ in /hsphere/local/home/sarada/konnectp.com/sso.php:216 Stack trace: #0 /hsphere/local/home/sarada/konnectp.com/sso.php(155): SingleSignOn_Broker->serverCmd(‘info’) #1 /hsphere/local/home/sarada/konnectp.com/index.php(7): SingleSignOn_Broker->getInfo() #2 {main} thrown in /hsphere/local/home/sarada/konnectp.com/sso.php on line 216

    broker= http://www.konnectp.com/index.php
    sso server= http://sso.sahooshare.com/sso.php

    but still it shows the above error.
    Please help me.

    Thanks in advance.

    ReplyReply
  82. 8 February 2010Arnold Daniels says:

    Sarada The broker is unable to connect to the server. Make sure you have the right URL in broker/sso.php on line 16. Check if there is a firewall in place blocking outbound traffic on port 80.

    ReplyReply
  83. 8 February 2010sarada says:

    Hello Arnold,

    I have given correct url in my broker. U can see as below.

    public $pass401=false;

    public $url= “http://sso.sahooshare.com/sso.php”;

    public $broker = “LYNX”;
    public $secret = “klm345″;

    I can able to access the above server url, its working.

    But as you said how can i know whther there is a firewall which blocks port 80 or not .
    Could you please help me.
    Thanks in advance.

    ReplyReply
  84. 8 February 2010Arnold Daniels says:

    Sarada This is a system administration problem, not a software issue. If you’re not the sysadmin, please consult your sysadmin. If you are the sysadmin, you should know how to solve this.

    ReplyReply
  85. 9 February 2010sarada says:

    Hi Arnold,

    It was some system issue. I consult the System admin and it got fixed. Now it is working.

    You can see the demo at @ http://www.konnectp.com

    Thanks.

    ReplyReply
  86. 21 February 2010Jack says:

    Hi Arnold,

    How to implement the single sign in my site.
    give me proper explanation in step by step. i am new to this concept .
    Give proper response is appreciated.

    Thank
    Jack

    ReplyReply
  87. 22 February 2010Arnold Daniels says:

    Hi Jack ,

    This is about as step-by-step as it’s going to get here. Make sure you read the article carfully, so you understand the concept behind the code.

    You might want to take 3 steps for implementing the SSO solution in your own site:
    1.) Download the code from GitHub and get it working, as is, on your server.
    2.) Replace line 140 of server/sso.php with a method that check the referentials against your database. Replace function info() to get the user info from the DB.
    3.) Copy/paste line 1 to 10 from broker/index.php into your own site. Replace broker/login.php with your own login screen.

    If you need more help, try one of the many PHP forums like http://forums.devnetwork.net

    Good luck

    ReplyReply
  88. 23 February 2010Jack says:

    Hi Arnold Daniels,

    Thanks for your help.I follow the what your mention.
    If any doubts kindly help me.

    Thanks
    Jack

    ReplyReply
  89. 23 February 2010Jack says:

    Hi Arnold,

    I have started to implement SSO in my http://www.test.com.
    1. I just down load and copy the your folder in to my test.com.
    2.I made changes that in server/sso.php for credential and get user info based on userName and password.
    3. you said Copy/paste line 1 to 10 from broker/index.php into your own site where i am going to copy the that 10 lines?
    4.i have copy that login screen in my own.

    could you please help me to finish the task…

    Thanks
    Jack

    ReplyReply
  90. 23 February 2010Arnold Daniels says:

    Jack: Some advise in advance, after each step, make sure that the app is working properly.

    Line 1 to 10 from broker/index.php checks if a user is logged in. If that is not the case it redirects the client to login.php. If your site doesn’t require a user to be logged in, you don’t need it.

    ReplyReply
  91. 23 February 2010Jack says:

    Hi Aranold,

    Thanks for your advise. App is working fine and i integrate your code in my site and logged in my site of your broker login and after that i refresh your demo http://sso-alex.adaniels.nl/index.php its logging in with out log of again and if log out your demo site in mysite broker also logout.
    So i reached the single sign on or i need to do any thing else……
    Kindly explain to finish the task….

    Thanks
    Jack

    ReplyReply
  92. 23 February 2010Arnold Daniels says:

    Jack I don’t understand your last comment.

    In the end you should be using your own SSO-server and SSO-brokers. The brokers are your websites which share their authentication. Based on the article and my previous comments you should be able to implement your own SSO solution.

    Please remember that this is not a help forum.

    ReplyReply
  93. 18 March 2010David says:

    Hi Arnold,

    I have downloaded the files from github and ran it on Linux and Windows, but I couldn’t make it work properly. Maybe I’m missing something, but there’s a strange problem.
    Suppose that you copy the directory broker with a new name like broker2. Now it’s supposed to have SSO between /broker and /broker2 but it’s both of them work separately and once logged in /broker , there’s no SSO in /broker2
    The most strange part is that on windows they work completely separate, but on Linux once you log in /broker and then open a page to /broker2 , you will be logged out of /broker !
    Thanks

    ReplyReply
  94. 19 March 2010vij says:

    Hi Arnold,

    i have made changes as mentioned above.
    i made changes as

    server/sso.php

    array(‘secret’=>”abc123″),
    ‘BINCK’ => array(‘secret’=>”xyz789″),
    ‘UZZA’ => array(‘secret’=>”rino222″),
    ‘AJAX’ => array(‘secret’=>”amsterdam”),
    ‘LYNX’ => array(‘secret’=>”klm345″),
    );

    /**
    * Information of the users.
    * This should be data in a database.
    *
    * @var array
    */
    protected static $users =”select * from mdl_user where username=’$username’ AND password=’$password’”;

    and

    IN BROKER/sso.php as
    <?php
    /**
    * Helper class for broker of single sign-on
    */
    class SingleSignOn_Broker
    {
    /**
    * Pass 401 http response of the server to the client
    */
    public $pass401=false;

    /**
    * Url of SSO server
    * @var string
    */
    public $url = "http://localhost:81/broker/sso.php&quot;;

    /**
    * My identifier, given by SSO provider.
    * @var string
    */
    public $broker = "LYNX";

    /**
    * My secret word, given by SSO provider.
    * @var string
    */
    public $secret = "klm345";

    /**

    i am getting login page tats all.. nothing is working

    ReplyReply
  95. 19 March 2010Sam says:

    Hi,
    Thanks for a great sso implementation.
    I did implement it with database(actually using webservices provided by one of our .net site) in my local server and every thing works great.
    The problem is when I uploaded it to live server.the first time i load the site, it goes directly to my sso_server.php file(seems it redirects physically ).
    second time i load the site, i get 406 error.
    IF i clear my cookies, the same thing happens.
    Is it some kind of settings i need to do ffor production?
    we have a linux dedicated box with apache and php 5.12
    have mamp in may local computer on mac.
    Other thing.
    I do get 406 error in my local computer some time. I think it’s when I don’t logout and local cookie expires. Guess something with session expire. butright now i am really looking to make this thing work on my real server.
    Thanks for a great implementation.

    ReplyReply
  96. 23 March 2010dacus says:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status: “Not attached”.’ in C:\apache2triad\htdocs\SSO\sso\broker\sso.php:161 Stack trace: #0 C:\apache2triad\htdocs\SSO\sso\broker\index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in C:\apache2triad\htdocs\SSO\sso\broker\sso.php on line 161

    please help me…

    i use windows 7 and apache2triad with PHP 5.1.2

    thanks before…

    ReplyReply
  97. 23 March 2010Arnold Daniels says:

    David Make sure that the brokers are configured with different identifiers.

    vij Changing $users to a database query won’t work. This example doesn’t have database support. You need to add that yourself. See comment 87.

    Sam Make sure that the symlinks to the session files are created correctly. Have a look at the remarks in some of these comments about ‘Not attached’ issues. Ask again if you’re unable to fix it.

    dacus Try manually setting $links_path in broker/sso.php and make sure you can write to that path.

    ReplyReply
  98. 23 March 2010David says:

    Hi Arnold,

    Well my windows machine creates 2 files for 2 brokers I have set ( using the same broker name ) as follows :

    1. sess_SSO-LYNX-dfe09fcdc0a9e9d7f31aa39d15e9f794-9d0d2a9eb1468eb324502615d9a427dd
    2. sess_SSO-LYNX-7488f04b107e05e943d027531a871688-172c95da16538918869b814bb0fae579

    at the time I just visit the broker’s page. when I login, the content of the session files changes and includes information. But the wrong part is that when I login in /broker1 it only changes one of the session files and when I refresh the page on /broker2 it still thinks that I have not logged in!
    I just downloaded the files again and made no changes on the files. I have no idea why it’s not working properly on my machine. Maybe it needs some PHP settings that are not set on my machine!
    Thank you in advance for your kind help

    ReplyReply
  99. 24 March 2010dacus says:

    hi arnold,

    now , i got it

    Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : Start tag expected, ‘__construct(’1′) #1 C:\apache2triad\htdocs\SSO\sso\broker\sso.php(158): SingleSignOn_Broker->parseInfo(true) #2 C:\apache2triad\htdocs\SSO\sso\broker\index.php(5): SingleSignOn_Broker->getInfo() #3 {main} thrown in C:\apache2triad\htdocs\SSO\sso\broker\sso.php on line 143

    thanks

    ReplyReply
  100. 24 March 2010Arnold Daniels says:

    David Do not use the same name for multiple brokers. A name (identifier) needs to be unique per broker.
    Those sess_SSO files should be symlinks to the same session file. Please check if this is the case. If this is not the case, check if the attach request is done (using fiddler, tamper-data, live-http-headers, or something similar).

    dacus The info function in server/sso.php isn’t outputting valid XML or you output other (debugging) text.

    ReplyReply
  101. 1 April 2010Sam says:

    Hi,
    Though it works on server( I changed the links path location to save it in a httpdocs folder. using db slow downs. )seems it was permission issue.
    Now the problem
    I don’t think I can explain what’s going wrong with me, but why do we have thisin broker constructor, inside $auto_attach loop.
    header(“Location: ” . $this->getAttachUrl() . “&redirect=”. urlencode(“http://{$_SERVER["SERVER_NAME"]}

    I have ajax request posting some variable. The issue is when I don’t logout, or say I visited the page after some time(it could be cookie expire time), it popsup saying ( the server is redirecting, would you like to send the form data you sent). This is because I send post data to a page, and when it tries to auto attach it the redirection call blocks it askign to send form data. This is only for ajax requests.
    Surprisingly, this wont happen all the time. it’s just if I visit one page and come back after some time. Secondly it’s not consistent too.
    any clue?

    ReplyReply
  102. 4 April 2010Arnold Daniels says:

    Sam When using AJAX, don’t use auto attach. Using SingleSignOn_Broker as a controller, assumes you are doing ajax. Line 222 to 229 sets $auto_attach to false and enables 401 passing.

    With AJAX, the Javascript client should check if the token cookie exists. If not, it should attach by getting the attach URL and loading it in an tag. To make sure that you don’t get ‘Not attached’ errors, the lifetime of the token-cookie needs to be smaller than that of the session.

    Alternatively you can pass 406 results, like 401 results are passed. On a 406 reattach and try again. Make sure you only do this retrying once, not to create a dead-loop.

    Make sure you’ve read the ‘Using AJAX / Rich Internet Application’ paragraph.

    ReplyReply
  103. 7 April 2010Sam says:

    Thanks Arnold,
    I appreciate your responses. I am getting close.
    I have one issue though. If I do not have a session attached to a broker, and I do a post request, firefox will popup with “This web page is being redirected to a new location. Would you like to resend the form data you have typed to the new location?”
    It’s again because of that 307 redirect. Can’t I use curl request to attach instead of header().
    Thanks

    ReplyReply
  104. 9 April 2010Maxime says:

    Hi Arnold,

    Thank you for this great article. I’ve implemented my own SSO Client / Broker / Server on Symfony (largely) inspired by yours.
    So far, everything’s fine ! I’ve used HTTPS along the whole process to ensure there won’t be any session hijack.

    Again, thanks a lot for this great explaination.

    ReplyReply
  105. 21 April 2010Arnold Daniels says:

    Sam No you can’t use curl to attach. The broker doesn’t know the session of the client at the SSO server. Otherwise this whole method would not be needed in the first place. Attaching always takes place through the client (browser).

    Attach on first visit on your website. Remember that attaching is not the same as logging in. It simply means that you have a session running at the SSO server and that the broker is attached to it. You can use it to log in at any time.

    OR

    Don’t use a redirect (using header) to attach. Instead you can place an node. Use AJAX to get the source of the image with the getAttachUrl() method. Use Javascript to write an node.

    ReplyReply
  106. 6 May 2010remo says:

    Hi arnold, thanx for the download. Im not getting any errors while accessing the two different brokers from my client but they are being independent. when i login at one broker and refresh the other broker page it still shows the login page, not showing the user info. im not able to understand where it is going wrong. please help.

    ReplyReply
  107. 6 May 2010Arnold Daniels says:

    Remo have a look at the cookies from the SSO server. See if the session file is created correctly and if there is symlink linking to it.

    Also there are issues when running the broker or server on your local computer.

    ReplyReply
  108. 17 May 2010muswanto says:

    hi arnold, thnx for your sso source code..but i want to connect user name to database(mysql),can you halp me?thnx before..:)

    ReplyReply
  109. 5 June 2010Raju Mazumder says:

    Hi,
    I have been used your solution with one of my zend framework project.
    I had o customize your solution to use with zend framework.

    It was working with php 5.2 but whenever I have upgraded my php version 5.3 it is not working. I have been debug your source code I don’t find anything to create problem with php 5.3.

    It is now all the time create new session and session expire for every request.

    Do you think is there anything which will not work with php 5.3? I am looking forward your suggestion
    thanks
    Raju Mazumer

    ReplyReply
  110. 3 July 2010Marty says:

    I have the same proble like David. The script is running on linux server – php 5.2.6
    Where is the problem ?
    please, help me.
    thanks

    ReplyReply
  111. 4 July 2010Arnold Daniels says:

    Marty Not attached means that PHP failed to create the symlink in function ‘attach()’ of server/sso.php. With a bit of PHP skills you should be able to figure out why. First of all check the HTTP requests that the client does (using firebug) and see if it calls server/sso.php in the first place.

    Good luck

    ReplyReply
  112. 5 July 2010Marty says:

    Where I check HTTP requests, is it Firebug->Net ? But there is only GET sso-broker.web.com
    I can try it, what Thiet Doan wrote(MySQL without symlink), but there is still the same error.

    ReplyReply
  113. 6 July 2010Marty says:

    At the first visit I am redirected to sso server with this error :
    Warning: file_exists() [function.file-exists]: open_basedir restriction in effect. File(/var/lib/php5/sess_SSO-BINCK-8acf06bc3a44412293e1d0bc5fae5146-44158a9d368cd1ff913349943e63a204) is not within the allowed path(s): (/home/www/web.com:/tmp) in /home/www/web.com/sso-server/sso.php on line 170

    Fatal error: Failed to attach; Symlink wasn’t created. in /home/www/web.com/sso-server/sso.php on line 171

    Thanks for advice

    ReplyReply
  114. 6 July 2010Arnold Daniels says:

    Marty open_basedir is a PHP setting that a (crappy) shared hosting might set to prevent you from accessing the session files. You can do 2 things:

    1.) Set $links_path in server/sso.php. This forces the SSO server to use handle attached sessions himself instead of using symlinks.

    2.) Store your sessions in an alternative (assessable) path by setting session.save_path. You can do this in an .htaccess file

    php_value session.save_path /var/www/example.com/tmp
    

    In both cases make sure that the path is not accessible for your website visitors.

    ReplyReply
  115. 9 July 2010Stefan says:

    Arnold, Thanks for this great framework!

    I’ve used it to glue WordPress, TYPO3, Scuttle, MyBB, and MediaWiki together by using LDAP authentication against Active Directory. I wrote authentication plugins for every application that use their own SSOProvider. Now our intranet users only need to authenticate once! :-)

    Btw, I had to set our cookie timeout to 8h via session.gc_maxlifetime = 28800 so that the users don’t have to login again after 24 minutes (PHP’s default value).

    ReplyReply
  116. 13 July 2010John Adigue says:

    Hi Arnold, thanks for this great tuts. Have a question.
    When the first visit broker sends a redirect to the server.
    Would my SEO will be affected when implementing it to my sites? because I’m planning to put the login form on the index page.
    Please advice.

    Thanks

    ReplyReply
  117. 13 July 2010Arnold Daniels says:

    John First of I’m not an SEO expert in any form. I guess it depends on how you implement this. If you implement is as described above I’d say yes. Google probably doesn’t like to be ping ponged around.

    An option is not to directly attach when a client visits your site. Instead when a user tries to log in, first save his username/password in a session and redirect to attach. After the client is attached and redirected back to the broker, let the broker authenticate the user.

    Another option is to skip the redirecting completely and solve this with javascript. How to do this is described above. This will work if your login form uses AJAX, but also with normal HTML forms.

    ReplyReply
  118. 22 July 2010Lonjan says:

    Yo man,
    You doing a very good job..answering all questions over and over again..
    I really appreciate your effort on helping other ppl, even though, some of the question is already answered by you previously..

    Thanks again mate!

    ReplyReply
  119. 27 July 2010Alexander Vassbotn Røyne says:

    I’m trying to wrap my head around the code you’ve made.

    I’ve implemented the code (ajax version) and altered brokers/server to comply with my backend.

    I get logged in (well, it returns 1 when i use the correct credentials, but no cookies or sessions are saved on the client side. Is this how it should work?

    How can I check if a user is logged in for all services, if not a cookie/session is set? Seems kinda redundant to check the sso server for every service on one page.

    ReplyReply
  120. 27 July 2010Alexander Vassbotn Røyne says:

    Some more info:
    I am not using the jaml thingy, it wouldnt work, so i made a simple login form and ajax script instead.

    ReplyReply
  121. 27 July 2010Alexander Vassbotn Røyne says:

    Hm, if I load the class with true

    $ctl = new SingleSignOn_Broker(true);

    a session cookie is created.

    but, i get a 307 temporary redirect on the ajax request, and before the redirect happens, i get a prompt asking me if its ok to send form data..

    ReplyReply
  122. 27 July 2010Arnold Daniels says:

    Alexander The $auto_attach argument means that the server will automatically redirect a client to the server if it detects that the client is not attached. You don’t want this use ajax, so keep this to false.

    In javascript you should check if the session_token cookie exists. If not call sso.php?cmd=getAttachUrl with ajax. This will set the session_token cookie and return a url. That url is to the sso-server and can therefore not be requested with ajax. Open that URL in an image instead. As soon as that image is loaded, the client is attached and the broker can make requests to the server.

    Note that session_token has nothing to do with PHP sessions. This example stores no information about the client on the broker. There is no reason why you can’t do that if you wish. You need to write that yourself though ;).

    About checking with the SSO server. Note that the server will not push any information to the SSO broker. This is strictly a polling service. This means that an SSO broker can know that a client has logged off on a different broker by asking the server. If you don’t care about single sign-off, just call getInfo() once and store it in a session on the broker.

    ReplyReply
  123. 28 July 2010hucs says:

    hi. Arnold

    when logined http://sso-alex.jasny.net/index.php ,
    how to generated shanghai@sso-binck.dutchc5 cookie?

    My English is bad, do not know whether what I mean。

    Thanks !

    ReplyReply
  124. 28 July 2010Arnold Daniels says:

    hucs You don’t, that not possible and not needed. Each broker has it’s own cookie. The session cookie is from sso-server.jasny.net. Please read the article again. It seems like you’re missing the point.

    ReplyReply
  125. 2 August 2010Kacper says:

    Great tip! Thanks!

    ReplyReply
  126. 4 August 2010Silver says:

    Good. I just try to write an SSO application for several decentralized web applications. Each application will be located in different and independent domain if it’s possible, and they will use the same SSO-application to verify and authenticate the user. I think your solution is good, but may it will not suitable for this situation. In your system, if I want to sign-up any application, I need to input user information for each one, and I just think it’s possible to use an central user validation system, and restore one copy of the information of the user. Seems your system doesn’t work for it. So..do you have any good ideas? Would like to know it if you can write email to me. well I wish! :) Good luck!

    ReplyReply
  127. 4 August 2010Arnold Daniels says:

    Silver The method described here does exactly what you want (I think). Only the SSO-server contains the information about the user. The SSO-brokers will communicate to the SSO-server continuously.

    In my example the SSO-server has only 2 API calls: login and getInfo. However, after you’ve attached you can do all kinds of things. Push user data, create a cart that works across all brokers, etc. The sky is the limit ;).

    Best way to think about it is a shared session + shared DB across different domains/systems.

    ReplyReply
  128. 5 August 2010Silver says:

    Yeah, you are right. Thanks for your message. I am still working on my own SSO-Library. Let me tell you what’s my idea, and this is first part of it. You know that I think there are four different situation to be meet when to make a share user validation system. (note, in the context, “application” is any application to use “sso-server” to authenticate users)

    1. All applications are on the same domain, so a local Library is good enough.
    2. All applications will be located in different sub domains of the same domain. Need a SSO server.
    3. All applications will be located in different domains. Need a SSO server.
    4. Hyper-one involves any of the situation above. (?)

    And in each situation, the first things’ first is not how to communicate with others, but how do you do with the architecture of that system. I mean, how do you make it works for these applications, and make it more effective and security? I think there are two way to put the user information across different application:

    1. Storing all different user information in the same server, so when the application need to know the information, it will need to get those user information from sso-server.
    2. Just storing the share part of user information, I mean “username, password, email validation, recovery question && answer, location”, and any other user information will be stored in its own application scope.

    Which one is good? I think the first one is simply not good, because when the application need to know any part of the user information, it must use HTTP-REMOTE-CALL/SOAP to get the information from sso-server, it will be more heavy and slow.

    The second one is good and simple, the sso-server will be accessed only in register/login/recovery/change password. The any other part of user profile will be stored in the application, and the application will load it from its own scope, so it needn’t to use HTTP-REMOTE-CALL/SOAP or else likes. (What’s google account’s idea?)

    What’s your idea? :) (BTW, I take my own consideration of that problem, and want to know your idea well if you are willing and free to tell me. Anyway like to learn from you, if luckily for me. To be continued. The next part – I want to discuss the communication way in different situation – register/login/recovery password/change password/even more)

    ReplyReply
  129. 5 August 2010Arnold Daniels says:

    Silver About the 4 situations: You only need to use an SSO-server if the applications are different domains. If the applications are on the same domain, you can simply have a single cookie.

    Where to store what information? That completely depends on your situation. All the information you need across applications, should be supplied by the SSO-server. This includes volatile data (sessions) as well as non-volatile data (database). Data that is specific to 1 app, can be stored by that app.

    Google does not do SSO, they only do shared authentication. If I’m logged into iGoogle and goto YouTube, I still need to login there. OpenID covers shared authentication.

    ReplyReply
  130. 5 August 2010Silver says:

    Thank you very much. Very appreciate your works, and I learned a lot from it. Thanks again. :/

    ReplyReply
  131. 17 August 2010zapatista says:

    Hi Arnold,

    i’ve try ur work with different domain, my config broker

    public $url = “http://mygoogleconnect.tld/jasny/server/sso.php”;

    and i tested with url
    http://mytwitterclient.tld/jasny/broker/

    why phpsession not generated only session_token, can u pleaz help me

    thanx

    ReplyReply
  132. 17 August 2010Arnold Daniels says:

    zapatista The broker doesn’t has a session, only the server has a session. Any information you store in a session on the broker is *not* shared with other brokers.

    Also read comment #129

    ReplyReply
  133. 23 August 2010williamjlp says:

    On login page, How can access to $_SESSION['username']?

    ReplyReply
  134. 24 August 2010Arnold Daniels says:

    williamjlp Please read the previous comments. There is no session on the brokers. You need to request the username from the SSO server.

    ReplyReply
  135. 31 August 2010ar_raudy says:

    @Arnold, thanks for your nice tutorial…
    I have some question. I hope you can answer them :
    1. I get task to build a system that can handle (using SSO) some domain that have some different database server. what must I do to that. must I move all of the user information from all database server to just one database server?can I use LDAP to implement that purpose? (I’m sorry, I’m newbie :))
    2. can you give me some advice about framework in PHP for that purpose ?

    thanks alot for your answer..

    ReplyReply
  136. 1 September 2010Arnold Daniels says:

    raudy 1. The SSO server should hold all login credentials. The broker should not hold that information. You can do authentication anyway you are doing it now. Using a MySQL db is most common, but LDAP is possible as well.

    2. There is no framework I know that has this (or something similar) implemented. Zend Framework could be easily extended to have this feature. You will need to program that yourself though.

    Good luck

    ReplyReply
  137. 2 September 2010Katravalli says:

    Hi Arnold Daniels,
    Your SSO is very much useful for our site(s). But need a small clarification from you. As in earlier post somebody also asked that how to display/print SESSION Value (Username, though which was used for logged in). You given reply stating that use SSO Sever to call session variable.
    But i’m unable to retrieve user information from Server SSO. Can you please give a brief note and solution how to call the user details or session from Server SSO.
    If u can explain it is very much useful for me as well as somany users using this script.
    Regards
    Pavan

    ReplyReply
  138. 3 September 2010Arnold Daniels says:

    Pavan Katravalli Well to be honest, the main article tries to explain just that.

    There is 1 session, which lives on the SSO server. Let’s say that the broker would know the session id of the client, the broker could act like the client. However since the session id is in a cookie a another domain, the broker has no way to fetch that session id.

    Instead, the broker will tell the client to please tell the server that he (the broker) is privileged to act on behalf of the client. The server will respect that, allow the broker to use the session on the server. That’s the basic trick.

    Any calls that the client would normally make directly to a website regarding a session, like logging in, adding products to a cart, etc, can now be done by the broker instead. Since the broker is a machine and not a human, the server should return XML of JSON instead of HTML.

    That’s all there is to it :)

    ReplyReply
  139. 3 September 2010Katravalli says:

    Hi Arnold Daniels,
    Thanks for your reply and I understand what you are saying but unable to retrieve and print the user session info from server. Can you please give simple example that how to call and print user data. For example, If login with a username “katravalli” and password “abc123″….. after login I would like to welcome the user something like “Welcome Katravalli”…. Here is my problem…. I’m unable to print Username after welcome…. unable to call from server sso…
    Hope you got my point…. can u pls give simple example how it is.. and how to call…!!!!
    regards
    pavan

    ReplyReply
  140. 3 September 2010Arnold Daniels says:

    The client sends the login credentials to the broker. The broker sends them to server. It is just the middle man.

    You should not see the broker as a special kind of server. The broker holds no information. You can see it as a special kind of client. Therefore it needs to request any information from the server using an HTTP request, just like a regular client would.

    In short: If the broker wants to print the name of the user, it sends an HTTP request to the server asking the name (and perhaps more user details).

    ReplyReply
  141. 3 September 2010Katravalli says:

    I didn’t get you Arnold. If you can give an example it may be understandable to my lazy brain. Just i need how would I print username after login… through HTTP request or whatever you say.
    Pls explain with example Arnold
    Regards

    ReplyReply
  142. 3 September 2010Arnold Daniels says:

    Katravalli You can find the example code on github http://github.com/jasny/SSO.

    On line 152 of broker/sso.php you see a function where the broker requests the information of the currently attached user. After the broker has gotten that data, it can print it. An example of this is broker/index.php

       $sso = new SingleSignOn_Broker();
       $user = $sso->getInfo();  // Requests the user info from the SSO server
       if ($user) {
           echo $user->name; // Outputs the name of the user
       } else {
           echo "No user logged in";
       }
    

    This is all the help I can give you. All the information you need is in this article and in the demo software.

    ReplyReply
  143. 3 September 2010Katravalli says:

    Thanks Arnold. Some how, i’m on the track now.
    Regards

    ReplyReply
  144. 4 September 2010ar_raudy says:

    @arnold, I hope you can give me some solution for my thinking.
    this source didnt use LDAP server, right? when I want to use Database server or LDAP server to get some user information I must modify this source. how about you about using LDAP server or database server (like MySQL) for multiple and big applications ?. what i must use from both ?when multiple an big application have their own database, how to integrate them ?

    thanks alot for your answer @arnold :)

    ReplyReply
  145. 5 September 2010Lumpas says:

    Good solution, thanks for sharing.

    ReplyReply
  146. 8 September 2010Arnold Daniels says:

    ar_raudy The SSO server does all the authentication. You can use any method you would normally use there.

    Replace the login, loutout and info functions of server/SSO.php.

    You can find info about php ldap in the manual: http://php.net/manual/en/book.ldap.php

    ReplyReply
  147. 9 September 2010Adrian Pawlik says:

    Thank you Arnold for the library! I’ve noticed that SSO server won’t work if request_order is not set correctly in php.ini. Make sure it contains cookie array (request_order = GP_C_). SSO server class uses $_RESQUEST to get session_id from cookie sent by broker.

    ReplyReply
  148. 14 September 2010ar_raudy says:

    thank you very much @arnold,…
    sorry, what you mean to 307 and 200 in that picture?

    ReplyReply
  149. 14 September 2010Arnold Daniels says:

    ar_raudy Those are HTTP status codes: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

    ReplyReply
  150. 22 September 2010manoj says:

    i Want to implement this on codeigniter with tank auth

    ReplyReply
  151. 25 September 2010Adrian Pawlik says:

    I found another problem. This solutions works if each website has own domain. When you try to set up 2 applications in the same domain, i.e. example.com/ and example.com/app2/ this will not work becouse the website user enters firstly creates cookie (session_token) and second application will use it while asking SSO for authentication.

    The solution is to set diffrent names for session_token cookie for each broker, for example session_token_brokername.

    In this case it works for the same and for diffrent domains.

    A.P.

    ReplyReply
  152. 27 September 2010Arnold Daniels says:

    Adrian Pawlik The whole reason of using this SSO solution is so you can share session information (like user credentials) across multiple domains. There is no good reason to use this on a single domain (other than testing purposes).

    ReplyReply
  153. 5 October 2010ob1 says:

    Finally !
    Something that works !

    Nice tutorial, you saved many peoples time
    Not even one tutorial, except this one, on the subject of shareing cookies, sessions across multiple domains.

    Good work ^_^

    ReplyReply
  154. 5 October 2010Paul says:

    Hi Arnold,

    Firstly, congratulations on some great coding – I’ve implemented your solution on a range of my blogs and it’s working wonderfully. I’ve done a lot of research into SSO and your solution is by far the most efficient and easy to implement.

    The only downside that I’ve encountered so far is problems with persistence when the browser is closed, reopened, and a new session is started. Logins persist for domains that have been visited with the previous session, but not for domains that haven’t been visited in the previous (logged in) session.

    For example:
    exampleA.com, exampleB.com and exampleC.com are all using your SingleSignOn_Broker class (php, not ajax) to check whether a client is logged in. Assume the sso server is sso.example.com (although I don’t think it’s relevant).

    A client logs in via exampleA.com, then goes to exampleB.com….. the client will still be logged in.

    However, if the client then closes the browser (killing the current session) and reopens it, the client will still be logged in to exampleB.com, but if they go to exampleC.com, they will no longer be logged in. Bear in mind that if the client doesn’t close the browser, then they appear as logged in across A B and C.

    I’ve tried to extend your code to fix this problem but without success. Have you got any ideas? I’d really appreciate it.

    Thanks – Paul.

    ReplyReply
  155. 16 October 2010Buzzknow says:

    Hi Arnold,

    its really great code!!

    i want to try this with CodeIgniter, wish me luck :D

    regards

    ReplyReply
  156. 21 October 2010Chris says:

    Is this code meant to crash when using PHP’s session_start() function. I use a PHP session to maintain persistence of data within my site but when I have the function running it seems to stop the SSO code working, holds it in an infinate lock where no redirects are occuring, it just refuses to load the page, it acts like a super slow connection, but when I remove the session_start() function it works fine. I have tried figuring out why it iss doing this but cant find where in the classes the session_start() function is clashing with other code. Do you have any ideas Arnold?

    ReplyReply
  157. 20 November 2010ob1 says:

    Arnold, I wanted to extend script to keep user logged in for longer period of time, by setting cookie with expire time for one year.
    Are there any drawbacks I could encounter?
    How would you do that?

    Thanks

    ReplyReply
  158. 20 November 2010Arnold Daniels says:

    ob1 That won’t work because the session on the SSO server will already be expired.

    You should solve this, as you would solve it without SSO. Let the SSO server write a cookie with the username + auth hash and check that to automatically log in.

    ReplyReply
  159. 20 November 2010ob1 says:

    Will Do.
    Tnx

    ReplyReply
  160. 26 November 2010chris says:

    Hi Arnold,

    great code.

    One question: Is there any simple possibility to secure the login? The username and the password is hand over in plain text.
    I think one possibility is to secure each broker. But we have arround 50 brokers so that would be a very expensive solution.
    Do you have any idea or advise?

    Thanks in advance,
    chris

    ReplyReply
  161. 29 November 2010Arnold Daniels says:

    chris You could send over an authorization hash instead of the password. This can still be snatched through a man in the middle attack, but by using a timestamp it’s only valid for a few seconds.

    http://www.jasny.net/articles/authentication-without-sessions/

    ReplyReply
  162. 2 December 2010Binit says:

    Thanks Arnold Daniels. I have wasted my three important days, but not get any Script. Finally I have used your script for “Single Sign On”. Its really quite simple & easy to use.

    Thanks again.

    ReplyReply
  163. 3 December 2010andrew says:

    Hi, Arnold

    What’s this error mean “String could not be parsed as XML”. What should i do?

    Thanx,

    ReplyReply
  164. 3 December 2010Kadek says:

    Great..!

    Thanks for the codes :)

    ReplyReply
  165. 17 January 2011guntur says:

    I want single sign-on is using the mysql database.
    is there any script.. help me
    thanks you :)

    ReplyReply
  166. 23 January 2011Скопище ссылок на тему SSO at Electronic Information Technologies says:

    [...] http://www.jasny.net/articles/simple-single-sign-on-for-php/ [...]

  167. 26 January 2011guntur says:

    Warning: SimpleXMLElement::__construct() [function.SimpleXMLElement---construct]: Entity: line 2: parser error : Extra content at the end of the document in C:\xampp\htdocs\ssoprovider\sso.php on line 143

    Warning: SimpleXMLElement::__construct() [function.SimpleXMLElement---construct]: Parse error: syntax error, unexpected ‘”‘ in C:\xampp\htdocs\server\s in C:\xampp\htdocs\ssoprovider\sso.php on line 143

    Warning: SimpleXMLElement::__construct() [function.SimpleXMLElement---construct]: ^ in C:\xampp\htdocs\ssoprovider\sso.php on line 143

    Fatal error: Uncaught exception ‘Exception’ with message ‘String could not be parsed as XML’ in C:\xampp\htdocs\ssoprovider\sso.php:143 Stack trace: #0 C:\xampp\htdocs\ssoprovider\sso.php(143): SimpleXMLElement->__construct(‘?Parse…’) #1 C:\xampp\htdocs\ssoprovider\sso.php(158): SingleSignOn_Broker->parseInfo(‘?Parse…’) #2 C:\xampp\htdocs\ssoprovider\login.php(8): SingleSignOn_Broker->getInfo() #3 {main} thrown in C:\xampp\htdocs\ssoprovider\sso.php on line 143

    ReplyReply

  168. 10 February 2011Lang Nguyen says:

    Dear friend,

    good article but i have prolem

    When i use session in php.ini with memcache

    How to change code support memcahce session in php.ini

    Thank

    ReplyReply
  169. 13 February 2011Arnold Daniels says:

    guntorThe result from the SSO server isn’t valid XML. Probably there is a server error. Output the result from curl and see what is wrong.

    Lang Remove line 168 to 172. Now look at the part where I’m attaching using a file. Replace that with code using memcache.

    On line 78 remove the isset() and replace the file_exists and file_get_contents with memcache.

    ReplyReply
  170. 22 February 2011guntur says:

    I want to change database
    protected static $users = array(
    ‘jan’ => array(‘password’=>”jan1″, ‘fullname’=>”Jan Smit”, ‘email’=>”jan@smit.nl”),
    ‘peter’ => array(‘password’=>”peter1″, ‘fullname’=>”Peter de Vries”, ‘email’=>”peter.r.de-vries@sbs.nl”),
    ‘bart’ => array(‘password’=>”bart1″, ‘fullname’=>”Bart de Graaf”, ‘email’=>”graaf@bnn.info”)
    );

    with database mysql.. is there any script.. help me

    ReplyReply
  171. 24 February 2011Erik Kloeze says:

    Hello Arnold,

    First of all, well coded script! I have read all the comments about the ‘Not attached’ error, but I still cannot seem to figure it out. My client is running Windows Server 2003 and my server is running Linux.

    Symlink is working and also seems to attach. When using fiddler I can see a sequence of requests (sso.php?cmd=attach) from the client to the server, all with a different broker and checksum and all being redirected to the client index.php.

    Error reporting (error_reporting(E_ALL)) is enabled in the server script. The only response I get from the client index.php is:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status: “Not attached”.’ in D:\…\sso\sso.php:162 Stack trace: #0 D:\…\sso\index.php(6): SingleSignOn_Broker->getInfo() #1 {main} thrown in D:\…\sso\sso.php on line 162

    I did have some problems with mod_security in the beginning, but after adding some exceptions, I do not recieve errors from this anymore.

    I have tried pretty much all the suggetions in the above comments. Do you have any idea what I can try to do?

    ReplyReply
  172. 25 February 2011Arnold Daniels says:

    Guntur There is no script I know of Please read comment 87.

    Erik Kloeze Check the symlinks. If they are being created correctly, output the contents of the session files. Is there a variable ‘client_addr’. Also make sure the server writes the error to the (Apache) error log.

    ReplyReply
  173. 27 February 2011Erik Kloeze says:

    The symlink seems to be created, as there is no “Failed to attach; Symlink wasn’t created.” error.

    In sessionStart, ‘User session’ there is a client_addr mentioned, in the ‘Broker session’ after the session_start there isn’t. After the symlink is created, there also is a client_addr in the session file.

    I think that altough there is a symlink, the ‘old’ session simply isn’t picked up? Adding session_name($sid) before the session_start in the ‘Broker session’ also did not work out.

    For the errors, as far as I know, all errors show up in the Plesk Log Files.

    Any ideas left?

    ReplyReply
  174. 28 February 2011Erik Kloeze says:

    Hello Arnold,

    I did some additional debugging, outputting the session_id in the attach function and the sessionstart function.

    When I use the readlink function in the sessionstart function, I get the same session_id as in the attach function. Futhermore, the link variable in the attach function is equal to the session_id in the session_start function (besides the path).

    But it still is not working?

    ReplyReply
  175. 1 March 2011Arnold Daniels says:

    Erik Kloeze Login using SSH and check what is happening.

    ReplyReply
  176. 15 March 2011tomcat says:

    Dude you got a lot of patience answering these questions eh

    ReplyReply
  177. 23 March 2011wawan says:

    Greetings,

    i’ve try ur work but it seems doesn’t work in multiple sub domain?
    what do i have to change if the applicationt are in multiple sub domains?

    Tks

    ReplyReply
  178. 23 March 2011Arnold Daniels says:

    Wawam If it doesn’t work for sub domain, but does work for completely different domains, your session cookie is valid for the whole domain. This is set with the cookie-domain ini directive.

    If you only need to share a session over sub domains and not over different domains, don’t use this SSO solution at all. Simply share the PHP session for the different sites.

    ReplyReply
  179. 23 March 2011wawan says:

    Thanks, for your answer. Very appreciate your works, and I learned a lot from it.

    ReplyReply
  180. 30 March 2011Goose says:

    Have you ever tried this with PHP and .NET. I am looking for a SSO between a PHP website and a .NET website. Can you think of any reasons why this wouldn’t work with both?

    ReplyReply
  181. 31 March 2011Arnold Daniels says:

    Goose No, that should work fine. Set up an SSO server using PHP. You would need to write a broker in .NET. It needs to redirect to the SSO server and than request the data using HTTP, just like the PHP broker.

    ReplyReply
  182. 18 April 2011Ana says:

    Dear Sir,

    Pls help me change code support session store on memcache
    When i change php.ini file use session memcache code error

    I look and research but i dont can change code support memcache
    i read all comment of vistit here but i can not change my code support my memcache

    Pls help me

    Thank verry much

    Ana

    ReplyReply
  183. 24 June 2011Krikil.COM » Blog Archive » Simple Single Sign-On for PHP (Ajax compatible) says:

    [...] Source : Jasny.net [...]

  184. 23 August 2011Luke Barton says:

    For those worrying about SSL certificates for your brokers, perhaps you may consider redirecting the client to the server for authentication, initiating the session on the server then redirecting the client back to the broker?

    ReplyReply
  185. 3 October 2011Charles says:

    Hello everyone,

    Thanks to the developers for this script; I think it’s the answer to my SSO implementation troubles, but I can’t get my head round the installation. Apologies for asking what may appear to others to be quite “basic” questions, I’m no web guru but can get things done once I see the instructions in human-readable language :-)

    I have 2 web sites, already set up and running, both LAMP based with separate but synchronized user databases (same usernames and passwords on both). They are on two separate domains.

    What I have done so far:

    1. Created subdomain for each site: sso.domain1.com and sso.domain2.com.

    2. Uploaded the SSO files to both subdomains, but putting the brokers in the root of each subdomain, along with the index and login files.

    3. Edited each broker sso.php to reference its own server/sso.php e.g. broker sso.php on sso.domain1.com has the entry

    public $url = “http://sso.domain1.com/server/sso.php”;

    4. Fill in the other details.

    5. Go to http://sso.domain1.com in my browser. See a login page, which I fill with credentials in the server sso.php on domain1.com.

    6. Script returns identity, fullname and email, with a logout link.

    7. Now for the really important bit: I go to http://sso.domain2.com, and because I have the same “protected static $brokers” and “protected static $users” data on both server sso.php files, I was not expecting to be asked to log in again.

    8. Script takes me to login page on sso.domain2.com. I don’t log in but when I refresh the browser, I get this fatal error:

    Fatal error: Uncaught exception ‘Exception’ with message ‘SSO failure: The server responded with a 406 status: “Not attached”.’ in /home/bizemail/.weh/sso.php:161 Stack trace: #0 /home/bizemail/.weh/index.php(5): SingleSignOn_Broker->getInfo() #1 {main} thrown in /home/bizemail/.weh/sso.php on line 161

    I know I’m doing something (maybe many things) wrong, and I’d grateful for pointers to properly install the script.

    Regards,

    Charles.

    ReplyReply
  186. 10 October 2011Arnold Daniels says:

    Hi Charles,

    The developers is me :p. So thanks for your praise. Just doing my bit to make the internet world a better place :)

    I looked at what you’re doing. Your creating a multi-master set-up. Where all sites are both server and broker. Though interesting, I think this approach is making the problem complexer than it needs to be.

    Ask yourself the question: Why do I need to have multiple masters?

    Whatever you come up with, you can probably also do with 1 server, even without losing the autonomy. This will make the whole thing much easier ;)

    Let’s take the following: domain1.com is a fully working website. You’ve got your database with your users, an authentication system, etc. Cool…

    Now you’ve got domain2.com which is also a fully working website including database with users, authentication system, etc.

    To share the users across the sites your simply copying them between databases. No magic there… but it works.

    Does this sound about right?

    Now the hard part (which isn’t really that hard). If users login to domain1.com and go to domain2.com you want them automatically to be logged in there as well. That’s what SSO does for you.

    However you want domain1.com as well as domain2.com both handle the authentication by them self and notify the other one. What a pickle :p

    Lets take a slightly different approach. The site on domain1.com stays how it is, but gets the SSO server software as well. The site on domain2.com (and all further domains) get the broker software.

    But you want domain2.com to handle authentication himself you tell me. Ahh, but that’s the easy part. Instead of domain2.com having to set the username and password, just let him send the userid (or username) by modifying function login() on server/sso.php.

    Calling this function will instantly login the user on domain1.com as well.

    Just make sure that only a valid broker can call that method and not some evil hacker.

    Now you only need domain2.com to check at domain1.com is the user is logged in when first visited. Lucky for you, that the broker can already do that :D.

    Told you it was easy.

    ReplyReply
  187. 21 November 2011marios says:

    Dear Sir,

    first of all, i would like to thank you for sharing your code with us.
    I would like to ask you if it is possible to test this at localhost.
    For example, i have a server (folder jasny-SSO/server) and two brokers (Alex: jasny2-SSO/broker and Binck: jasny3-SSO/broker).
    I have connected as jan (username: jan, password: jan1) in the url: http://localhost/jasny2-SSO/broker/index.php and then i tried to connected to the url: http://localhost/jasny3-SSO/broker/index.php when i encountered with the login page.
    What i should do in order to make this work.

    Thank you in advance,

    Marios

    P.S: I comment the line ;session.auto_start = 0 in my php.ini file.

    ReplyReply
  188. 22 November 2011mobile version of the forum? says:

    [...] Canada goose business just as '57 udsalg canada goose . canada goose vest canada goose store canada goose chilliwack bomber canada goose expedition parka canada goose store canada goose montebello parka canada [...]

  189. 23 November 2011marios says:

    Dear Sir,

    once again thank you for your code.
    I am writing again because i do not hear from you since today.
    I would like to ask you if it is possible to test your code at localhost.
    I tried to use two brokers and one server at different folders but it does not work.
    I would appreciate if you help me.

    Thank you in advance,

    Marios

    ReplyReply
  190. 28 November 2011dhtmlextreme says:

    After studying the model here, i created a slightly different version – using the model to run my site – http://www.dhtmlextreme.net
    I just made a blog-post about 2 models – one that runs across subdomains on a website and another version that runs across multiple domains and subdomains or even within the same website.
    I made a plugin for drupal so that the sso can integrate with drupal –
    my server is http://www.accounts.dhtmlextreme.net
    my brokers are http://www.blogs.dhtmlextreme.net, http://www.classrooms.dhtmlextreme.net and others.

    ReplyReply
  191. 29 November 2011butter says:

    Hi Arnold

    I have tried the script, i have to say “wow! its damn great!”
    It work pretty fine in my local and my testing server.
    However, im facing the issue with “406″ stuff, when i place my broker on my local (win7) and sso server on test server (linux). I read every comments above and tried with several fix. yet i cant get it right.

    understand that, this sso suppose to centralise the login auth across domains. im confusing about the _server["REMOTE_ADDR"] as it matching the IP add from local and server IP and final it goes to invalid checksum

    please help and appreciate alots…

    ReplyReply
  192. 30 November 2011butter says:

    Yes! I got the issue solved.

    ReplyReply
  193. 5 December 2011wira says:

    Hi Arnold…
    I want to implement your code using LDAP, which part should I make a change?
    2nd question, I still confuse with ajax-broker implementation, plus your demo site is not working right now, would you active back the demo site so I can learn from it?
    I really appreciate your kindly help

    Thanks for your help…

    ReplyReply
  194. 14 December 2011Gowtham says:

    @Arnold Daniels: Hi Arnold I have the Same problem as Charles. Can you please Explain me wat to modify in server/sso.php as mentioned below

    “But you want domain2.com to handle authentication himself you tell me. Ahh, but that’s the easy part. Instead of domain2.com having to set the username and password, just let him send the userid (or username) by modifying function login() on server/sso.php .”

    ReplyReply
  195. 14 January 2012Arnold Daniels says:

    Hi all, the demo’s are currently broken indeed. I need to look at that soon. Also I’ve decided to create a full featured lib from this example, since I’m still getting a lot of response years after writing this article.

    Sorry @Gowtham I didn’t reply to you earlier. Since the broker will do the authentication, it can simply send the userid to the SSO server instead of the username/password.

    ReplyReply
  196. 16 January 2012Sir Đoàn says:

    Thank you so much for this toturial ^^

    ReplyReply
  197. 25 January 2012Gougousis Alexandros says:

    Hi! Nice code!
    I have used it to create an SSO-based application using the Yii Framework. It’s cool!
    I would like to ask you one thing. What is the reason of “attaching” to the SSO-Server?
    Why not direclty sending the un-logged client to the SSO-Server for logging?

    Anyway,thanks for sharing the code!

    ReplyReply
  198. 8 February 2012Sunil Singh says:

    Hi Arnold, great tutorial, but I still unable to find how to achieve this on a PHP CMS, as I am developing two social networking site having different concept using Boonex Dolphin CMS of php. But the client wants single sign-on on both site. just like, gmail, googleplus, orkut.
    So how to achive this … if you can help me out by clearly mentioning it step by step, then it will be very easy for me to understand.

    Thanks n Regards
    Sunil Singh

    ReplyReply
  199. 15 February 2012gps says:

    Thanks for great tutorial. I’m looking for a SSO solution for my websites but with no luck. As your mention, I will try in a different approach. Thanks again!

    ReplyReply
  200. 6 March 2012ST says:

    I’ve been using your SSO solution for about 6 months now. Some of our customers do have problems to login due to cookie restrictions. They use an open wireless network which you can find in hotels or other public locations. It seems that there are specific cookie restrictions which does not allow to share the cookie information from server to broker.

    Does anybody else have problems with that?

    ReplyReply
  201. 3 April 2012elier says:

    hi, sorry i speak a little english

    which are the required configuration for the sso server ?

    i put it in a server with php 5.1 and it work good

    i put it in a server with php 5.3 and it does not work

    the session configuration in php.ini is the same in both servers, any other parameter is required ?

    i have 3 clients and when the domain of sso server is the server with php 5.1 clients work good, but when i put in the client configuration the domain of sso server with php 5.3 it does not work.

    thanks and sorry for my english

    ReplyReply
  202. 3 April 2012elier says:

    hi again, i have found the problem is with symbolic link, in the server with php 5.3, the sso server script does not create the symbolic link, someone know why does happen ?

    thanks.

    ReplyReply
  203. 4 April 2012Gisela Maja says:

    Hi guys,

    i have 2 online systems; joomla cms and xtcommerce shop and i am looking for sso for both system.

    my goal is: i want to login into joomla and after on clicking on shop i want to login through sso into shop

    also is there is a need, if user changes password on joomla, also password should be changed automatically in shop system.

    so my question, what is to do, that i can implement your script to make a sso for my systems.

    can you please provide me with more informations how to do!!

    cheers

    gisela maja

    ReplyReply
  204. 6 April 2012flamencoman says:

    @elier:
    I had that problem and resolved it by creating directory with ‘Apache user’, by allowing to all to write to that directory and pointed session_save_path to that directory.

    ReplyReply
  205. 6 April 2012flamencoman says:

    Hi Arnold,
    I’ve implemented your SSO code and after one smaller fix it worked.
    This part created a problem for me:
    if (isset($_SESSION['client_addr']) && $_SESSION['client_addr'] != $_SERVER['REMOTE_ADDR']) {session_regenerate_id(true);}

    Scenario:
    I logg in via broker_1.
    When broker redirects (with 307) first time to the SSO server, server puts in $_SESSION client’s remote addres and redirects to broker’s login page after which “info()” method is called where broker checks via cURL if user is logged in.
    Problem is that when broker asks SSO server via “info()”, SSO server sees broker’s $_SERVER['REMOTE_ADDR'] and sets it in $_SESSION and that triggers session_regenerate_id(true);

    Changes I’ve implemented:
    Broker SSO: serverCmd -> added “client’s_remote address” as POST variable
    Server SSO: sessionStart -> instead of asking if (isset($_SESSION['client_addr']) && $_SESSION['client_addr'] != $_SERVER['REMOTE_ADDR']) {
    ask
    if (isset($_SESSION['client_addr']) && $_SESSION['client_addr'] != $_REQUEST['remote_address']) {

    I’m using PHP 5.3

    What’s more interesting, “symbolic link” problem (that elier mentioned) exists when brokers are at the same server.
    Code with

    ReplyReply
  206. 12 April 2012Gisela Maja says:

    @flamencoman or others

    can you please briefly help me how to testablish a single sign on between my 2 web-systems ( Joomla and XT-Commerce) so that there is only one login possible.

    what is to do to make this issue happen??

    note: you can also send me how-to description to: maja340@gmail.com

    cheers

    Gisela Maja

    ReplyReply
  207. 18 April 2012Mikesch says:

    Good job!
    I did the SSO login with this script and everything works fine regarding the login.
    I also need to store information in my own session variables, if I put some information into session variables at the login and call for example at the main view the session variable, they are no more accessible.
    So how to tell a script so use the initialized session from SSO during login?

    Thx in advance!

    ReplyReply
  208. 15 May 2012Thomas says:

    I just released a PHP-based SSO server/client solution and would like feedback:

    http://barebonescms.com/documentation/sso/

    This article did make me go “hmm” in a couple spots. You say that there are many SSO solutions out there, yet my research turned up basically nothing – and still turns up nothing that even compares to what I’ve built. You’ve got OpenID, OAuth 1 and 2, and not much else. The landscape is pretty barren. And if you want to offer the user multiple sign in options at the server level, it gets even more sparse (HybridAuth and my solution are pretty much it).

    You do address AJAX in this article but you are proxying requests to a server. Anyone can build a proxy and, as you pointed out, you have to trust the servers that proxy the requests. I don’t know how I feel about that, especially if you want to support mobile devices – you might want to consider the possibility that the application was poorly designed in the first place. The SSO solution I’ve built saves the request ($_GET, $_POST, etc.), redirects to the server, the server manages the login process, and then the request is restored when the server redirects back to the client. So you could author a comment or forum post and, once you completed the entire sign up and/or sign in process, the comment/forum post would finish posting as if you had been logged in the entire time.

    ReplyReply
  209. 15 May 2012witi says:

    Hello ppl,

    First of all, thx for that library that is very powerful ! We are using the Ajax implementation on our network and just finished to install it.
    After several days of test / bug / debug, we notice that broker name SHOULD NOT contains ‘-’ because of

    preg_match('/^SSO-(\w*+)-(\w*+)-([a-z0-9]*+)$/', $_REQUEST[session_name()], $matches)

    In server’s sessionStart() function.

    Just in case, if some of you are trying to use it with a broker name like xxxxx-xxxxx ;)

    Cheers

    ReplyReply
  210. 15 May 2012Arnold Daniels says:

    @Thomas: Cool that you’ve implemented an SSO solution. I’ve just browsed through it, so far it looks pretty good.

    You’ve got a number of solutions based on SAML like http://simplesamlphp.org and a whole number of things in Java. There definitively space for easier and better libs though.

    It depends on your use case. If you choose to redirect the client to the SSO server, you can easily choose to have the user login directly instead of through the broker. However, you can also just load an image from the SSO server and proxy the authentication, so the client does not have to leave the page. You can choose which of the 2 ways you prefer, other SSO implementations (including yours) don’t give you that option :(.

    ReplyReply
  211. 15 May 2012Arnold Daniels says:

    @flamencoman: Forgot to say thanks… Thanks :)

    ReplyReply
  212. 4 June 2012Robert says:

    @flamencoman: hmm how can i added “client’s_remote address”? im amateur in SSO

    ReplyReply
  213. 15 June 2012Umesh Kulkarni says:

    Hi Arnold Daniels,

    Demo
    Broker ‘Alex’
    Broker ‘Binck’
    AJAX broker – created by Lukasz ‘Uzza’ Lipinski using Ajax.org PlatForm.

    Play around, logging in and out at different brokers. Refresh the other after. Available users:
    jan / jan1
    peter / peter1
    bart / bart1
    henk / henk1

    These demo links are not working.
    Can you please let me know which links should I use to see the demo?

    Thanks,
    Umesh Kulkarni

    ReplyReply
  214. 14 July 2012Jmatt says:

    @ Witi

    Untested, but this might work.


    preg_match('/^SSO\-(\w*+)\-(\w*+)\-([a\-z0-9]*+)$/', $_REQUEST[session_name()], $matches)

    ReplyReply
  215. 18 October 2012Bill says:

    I’m wondering if this is still working and what php applications are working. Any further development or better solutions available now? I’d like to integrate Drupal, Magento and WordPress into a SSO solution but I realize all the synching, updating, ect that would have to occur between the different “application architectures for customer roles (username, password, ect)”… Just wondering if anyone’s trying to do anything like that out there…

    I have a partial working solutions for wordpress/mage but syncing customers and password updates not so much..

    ReplyReply
  216. 22 October 2012Arnold Daniels says:

    @Bill. The demo’s aren’t working anymore. I should really fix them. This is basically just a proof of concept and far from a solid lib. I planned to create a lib, but it’s unlikely I’ll get around to it soon.

    ReplyReply
  217. 30 January 2013Whoops says:

    the demo links no longer seem to be working….?

    ReplyReply
  218. 15 February 2013Arnold Daniels says:

    @Whoops I’ll fix it soon.

    ReplyReply
  219. 29 April 2013Jeet Chaudhari says:

    Really Thank You…!

    I was struggling from many days to implement SSO system for my website and my other websites which are in development. I tried many things but did not get success.

    I even tried installing barebones sso, but it was too complicated with so many tables in database, as I already have all website’s user database and session database developed, with their classes.

    This is the place where I found exactly what I was searching for, an easy code to understand and modify. I implemented it on my website, But I am getting one small problem.

    When I visit the page which just checks if user is logged or not, (On this page I do not want to force user to login, so removed redirect) It returns 406 error, which says invalid checksum (The generate attach checksum returns null). If I refresh same page again I was visiting, then it works.

    If you can tell me, why 1st time it gets invalid checksum when user isn’t logged in, I would be really thankful. to avoid this, should I just put redirect statement, instead of header 406? Or I did something wrong in checking if user is logged in?

    This is the code I used to check if person is online or not.

    function isLoginValid () {
    $sso = new SingleSignOn_Broker();
    $user = $sso->getInfo();

    if (!$user) {
    return false;
    } else {
    return true;
    }

    ReplyReply
  220. 26 May 2013Kyle says:

    I tried going to the github to download the SSO you wrote but cannot find it on there….did you remove this? Is there still a way to get it?

    ReplyReply
  221. 28 May 2013Arnold Daniels says:

    @Kyle: GitHub changed the download section. I’ve fixed the link.

    ReplyReply
  222. 1 June 2013David Baker says:

    We are looking to implement an SSO piece from a PHP marketing site to our ASP.NET enterprise portal.
    In other words, a user would be on a PHP marketing page, be able to put in their username and password in the appropriate fields and be redirected, authenticated (or not) against our other site user database.
    Is this something you could assist / consult with us on? Fee?
    Thanks in advance –
    David

    ReplyReply
  223. 3 July 2013nhymxu says:

    Some user manager system have two part: client site and server site, work with API (return json, xml, …)

    Why you need three part: client, ajax, server?

    I don’t know about this?
    sorry because my english not well.

    Can you talk about this?

    Thanks you

    ReplyReply
  224. 15 July 2013OSS says:

    Hello Arnold

    Thanks for this article and its nice code

    i wonder if i can use your code in two different virtual hosts : the first one is the broker and the second one will be the server side.

    Thanks and good continuation .

    ReplyReply
  225. 2 October 2013conglin.deng says:

    hi,

    i have a website want to use this php login framework, but encounter a problem, that any page need login, so i change the sso.php below line code. just refer U. make the sessionToken not change.

    56 $this->sessionToken = ’476bdd2c2e296936a91a411dfefdb38c’;

    53 public function __construct($auto_attach=true)
    54 {
    55 #if (isset($_COOKIE['session_token'])) $this->sessionToken = $_COOKIE['session_token'];
    56 $this->sessionToken = ’476bdd2c2e296936a91a411dfefdb38c’;
    57
    58 if ($auto_attach && !isset($this->sessionToken)) {
    59 header(“Location: ” . $this->getAttachUrl() . “&redirect=”. urlencode(“http://{$_SERVER["SERVER_NAME"]}{ $_SERVER["REQUEST_URI"]}”), true, 307);
    60 exit;
    61 }
    62 }

    ReplyReply
  226. 2 October 2013conglin.deng says:

    @conglin.deng:

    just ignore what i say,sorry, the method have problem。

    ReplyReply
  227. 14 October 2013trampoline installer says:

    I got this wweb page from my buddy who told me about this site and at thee moment this time
    I am browsing this web page and reading very informative content at this place.

    ReplyReply
  228. 19 October 2013Tinnitus Treatment says:

    I loved as much as you will receive carried out right here.
    The sketch is attractive, your authored material stylish.
    nonetheless, you command get bought an edginess over that you wish be delivering the following.

    unwell unquestionably come further formerly again
    as exactly the same nearly very often inside case you shield this increase.

    ReplyReply
  229. 2 November 2013gusseisen ofentüren says:

    you’re in point of fact a good webmaster. The website loading
    pace is amazing. It kind of feels that you’re doing any unique trick.

    Also, The contents are masterpiece. you’ve done
    a wonderful process in this subject!

    ReplyReply
  230. 3 November 2013Hcg Weight Loss Reviews says:

    Am I able to take splenda all through the Hcg Weight Loss?

    ReplyReply
  231. 7 November 2013iPhone says:

    Howdy! I’m at work surfing around your blog from my new iphone 3gs!
    Just wanted to say I love reading through your blog
    and look forward to all your posts! Carry on the great work!

    ReplyReply
  232. 15 November 2013udaya says:

    Hi,

    I have three different PHP web application and planning to implement SSO for these. Could you please explain how to integrate your code to make it working. Thanks in advance.

    ReplyReply
  233. 11 April 2014Wahid says:

    Hi Arnold,

    I’m teaching the SSO and I’m so interest your article about the SSO.

    My questions are:
    1. How to implement the SSO using the user existing in database?
    I am changing the code on server\sso.php like below, but it is still not work.
    protected static $users = “select * from user”;

    2. How to implement on 2 (two) different domains?

    Any idea for me. Thank you so much.

    ReplyReply
  234. 12 April 2014Romain says:

    Hi Arnold.
    Thank you very much for the download, it seem to be exactly what I need.
    But I have the same problem of remo:


    remo said:
    Hi arnold, thanx for the download. Im not getting any errors while accessing the two different brokers from my client but they are being independent. when i login at one broker and refresh the other broker page it still shows the login page, not showing the user info. im not able to understand where it is going wrong. please help.

    But I don’t understand your answer :


    Arnold said:
    have a look at the cookies from the SSO server. See if the session file is created correctly and if there is symlink linking to it.
    Also there are issues when running the broker or server on your local computer.

    Where can I check if the session file is created?
    I don’t understand what can I do to fixe the problem. I hope you can help me.
    Thanks

    ReplyReply
  235. 13 April 2014Arnold Daniels says:

    @Romain: Check your session directory. The directory is configured in php.ini by session.save_path. (Probably /tmp or /var/lib/php5 under linux).

    ReplyReply
  236. 14 April 2014dragons world hack says:

    There are many diverse and complex features that are depicted by dragons.
    ‘Eternity Warriors 3′ is also rated 9+ for violence and suggestive themes.

    Quidditch gadgets such as the quaffle balls, bludgers,
    and the snitch.

    ReplyReply
  237. 14 April 2014search engine optimization portland says:

    Hi there. Many thanks for the wonderful write up.
    Perfectly timed answers just like what I’m certainly
    looking for a quite a while. Glad to uncover this
    and I will be going to mention it on some social bookmarking platforms.
    Bookmarked this too for reference someday as well. Talk to you soon!

    ReplyReply
  238. 14 April 2014Testosterone says:

    In case your work out mainly concentrates of muscle tissue development, then this article has info that will be of use for your needs.

    You may need to change your diet regime along with exercising to acquire the final results you want.
    Check into locations and concentrate on aspects of your overall exercise routine training that you sense
    you could utilize assistance with.

    Target a very high amount of repetitions with medium-intensity body weight whenever you coach.
    For each and every individual exercise you need to do, attempt to do a pair of ten to fifteen
    reps, sleeping under 1 minute between every establish.
    This will cause lactic acid to build up inside your muscle tissue, that makes you “experience the burn off” when exercising progress.

    In case you are seeking to develop muscle tissue, it is essential to try to eat caloric-thick meals with the proper time.
    The best time to eat your largest dinner during the day is
    after you have finished your muscle-creating workout period.
    It can be at this time the energy needs of your body
    are at maximum amounts because your body needs the nutrients to fix and build muscle tissues.
    If you continue to eat even more caloric-dense meals every couple of hrs, you may offer a chance
    for your whole body to add even more muscle tissue.

    Crank up some tunes. Studies have revealed that paying
    attention to tunes you cherish while you are lifting may help you do a lot more
    repetitions than not listening to any audio in any way or otherwise not hearing the tunes that you like.
    Moreover, getting earphones might help distract from using a discussion with
    others that will defer your regular workout.

    It is very important that you remain appropriately when doing standing up exercise routines, for example
    business expense presses and leg squats. These exercise routines
    require a kind of sporting stance. To experience this, you must stay with your ft .
    at regarding the breadth of your shoulder area. Then, slightly level your foot outward, flex the knees, and arch your back.
    Make sure that your eyesight are seeking forwards.

    A 60 moment workout is the ideal duration for max effects. Over and above 60 minutes, the body begins releasing the worries hormone, cortisol.

    Cortisol lessens your androgenic hormone or testosterone ranges,
    which just waste products your time and efforts towards boosting your muscle mass.
    A great means of making certain you increase your workouts is to keep
    exercises at less than one hour very long.

    Prevent assessing you to ultimately others in the club.
    It may be beneficial to view others to see their type, new
    exercise routines, or new varieties of gear, but direct assessment will not be
    helpful. The reason being people have another physique what matches your needs might not benefit other people.

    Pay attention to your body fat and evaluate it consistently.
    Do not be frustrated if you have not substantial fat loss when muscle
    building, on account of your body weight might not alter a lot using a bodyweight and
    body building regimen. Your system excess fat is a much better way of measuring your state
    of health in contrast to weight.

    Make certain you are consuming the amount of calories that your system needs.
    There are a variety of on the internet calculators that can be used to figure
    out caloric requirements reliant on your goals. Use one or two
    of your calculators then alter your diet appropriately, including the proper quantities
    of carbs, necessary protein and other natural vitamins to create
    your muscles.

    Work your muscle mass to exhaustion for the greatest is a result
    of your workouts. Keep nothing at all on the desk.
    When doing a pair of exercise routines, continue to
    keep driving on your own up until you could not full an additional force-up or elevate the nightclub one more time.
    After that you can begin to use more heavy weight loads and performing a lot less reps to boost muscle mass dimensions.

    Creating a wise schedule for your muscles developing routines
    helps keep your muscle mass developing and prevent you from injuries.
    Our recommendation is that amateur muscle mass building contractors work
    out only two times each week, although those that have
    experience is capable of doing so 3 times per week.

    As you may study from the above post, there are many approaches to enhance
    your muscles. This short article offered some very
    nice suggestions so that you can stick to. Consider picking the ones that you think will
    assist you to. Blend it and test combos to find out the direction they feel.

    ReplyReply
  239. 14 April 2014Santana Cazorla says:

    Nice post. I was checking continuously this blog and I am impressed!
    Extremely helpful information specially the last part :
    ) I care for such information a lot. I was looking for this particular information
    for a very long time. Thank you and good luck.

    ReplyReply
  240. 15 April 2014halogen says:

    With havin so much content do you ever run into any issues
    of plagorism or copyright violation? My site has a lot of completely unique content I’ve either written myself or outsourced but it seems a lot of it is popping it up all over the web without my
    permission. Do you know any methods to help reduce content from being stolen?
    I’d really appreciate it.

    ReplyReply
  241. 15 April 2014dating online says:

    Woah! I’m really enjoying the template/theme of this site.

    It’s simple, yet effective. A lot of times it’s very difficult to get
    that “perfect balance” between superb usability and visual appeal.
    I must say you’ve done a great job with this. Also, the blog loads extremely quick for me on Safari.
    Superb Blog!

    ReplyReply
  242. 15 April 2014Alexandria says:

    Made exclusively for Playstation the Gran Turismo is often viewed as
    a selling point for the gaming console. Some of them may even be hiding spy codes under the free itunes
    code they are presenting on their own sites.
    More and more people are switching to X-Box 360 because this mess-up is
    becoming an annoying every day thing.

    ReplyReply
  243. 16 April 2014wood projects says:

    but here again, some experimenting will be necessary.
    For example, if you would like to buy a simple Adirondack chair,
    you would have to pay around 300$. An eye-catching project is something that is worthy and a valuable addition to your home or even a marvelous gift for family or friends.

    ReplyReply
  244. 16 April 2014explosive says:

    Faux Suede Footstools

    Summer is here, this means the sun’s rays is shining along with your
    lawn is increasing faster than you can on top of it. We know how frustrating it is usually when “mow the lawn” is on
    your own honey-do list along with your riding mower isn’t working.

    Here are a few troubleshooting tips to get the riding mower gonna trim your lawn and that
    to do list!

    One of the favorite honest home based companies
    right this moment is performing special events videos.
    If you like as a persons vision behind it camera and obtain
    that you use, you could turn out trading tomorrow. Seriously,
    bring to mind each of the special attractions in people’s lives that they’d like to own on video.
    Weddings, marathons, club events, Little League games, retirement dinners, family reunions are a few gatherings that searchers want on video.

    You can probably think about tons more. Which is good before
    you choose this because honest home-based business
    available to you.

    Toro riding mowers have long been named the very best inside lawnmower industry.
    These mowers consistently lead the market industry in sales.
    Toro mowers are incredibly popular simply because they require almost no maintenance.
    Lubricating the idler bearings, spindle bearings and steering controls is a particularly important maintenance part of those
    who own Toro mowers. Continue to lubricate each component using the correct lithium complex
    once every use. These are the steps you need to follow while greasing
    your Toro riding mower:

    For example, you would not pay $500 to fix a lawnmower
    that set you back $100. However, if your
    lawnmower is a huge riding lawnmower that amount to several
    thousand dollars, $500 in repair costs are not unreasonable.
    The only way to learn how much a repair would cost is to acquire a bid.
    You can always decide not to correct after that. But generally speaking,
    you probably shouldn’t spend more than half the buying price of a replacement mower for repairs.

    Created by Japanese textile technologists within the 1980s, faux suede
    was developed being a micro fibre to readily accept colouration.
    The fabric has useful performance applications in the clothing along with the field of furnishings.
    The base of faux suede is polyester, a man made fibre extracted being a derivative from petroleum.
    Polyester could be blended with every other textile fibre however to keep performance and satisfactory texture a faux suede fabric should ideally
    be woven from 100% core polyester.

    ReplyReply
  245. 16 April 2014Indonesia chanel Bags says:

    online chanel Bags
    Hello, Neat post. There is an issue along with your site in internet
    explorer, may test this? IE nonetheless is the market leader and a big component
    to other people will miss your magnificent writing because of this problem.

    ReplyReply
  246. 16 April 2014Web Hosting Paraguay says:

    Simply want to say your article is as astonishing.
    The clearness for your put up is just cool and that i
    can suppose you’re an expert on this subject. Fine with your permission allow me to
    take hold of your feed to stay up to date with imminent post.
    Thank you 1,000,000 and please continue the enjoyable work.

    ReplyReply
  247. 17 April 2014twitter.Com says:

    Today, I went to the beach with my kids. I found a sea shell and gave it to my 4 year old daughter and said “You can hear the ocean if you put this to your ear.” She placed the shell to her ear and screamed.
    There was a hermit crab inside and it pinched her ear.
    She never wants to go back! LoL I know this is
    totally off topic but I had to tell someone!

    ReplyReply
  248. 18 April 2014types of hpv warts says:

    Remember that you have n’ precise as well as confirmed penile
    wart treatment options. Every last single lawsuit is still equipped with a tall
    choice of repeating, and thus are aware of the it all as it can get may still be infected.
    If you are already dealt with therefore the hpv
    can be pulled, you can actually company this in turn may be the best and therefore strong dietary regimen.
    Food quite a few produce and thus fruits, particularly those abundant in
    vitamin C can certainly enhance ones defenses to cut back your
    chance of finding these kinds of computer in the future.Hpv will definitely be face progression or possibly a patch brought
    on by Warts (normal papilloma herpes simplex virus).
    It can appear to be anywhere over your person together with feet and toes.

    Skincare development on a tread around the paw a consequence of Warts
    is plantar hpv warts. Genital warts are really very simple but once on top of work places
    appreciate the soles on your legs, it may be totally symptomatic.
    Restoring plantar hpv warts is essential decrease all of
    the aching and also cramps.

    ReplyReply
  249. 18 April 2014o que é a meditação says:

    Hi, this weekend is good in support of me, for the reason that this
    occasion i am reading this impressive informative article here at
    my house.

    ReplyReply
  250. 18 April 2014maurice lacroix watches says:

    Thank you a lot for sharing this with all of us you actually recognise what you’re speaking
    approximately! Bookmarked. Kindly additionally consult with my web site =).
    We could have a link exchange agreement among us

    ReplyReply
  251. 18 April 2014Florine says:

    It’s an remarkable piece of writing designed for all the online users; they will obtain benefit from it I am sure.

    ReplyReply
  252. 18 April 2014best bottle warmer says:

    Hello to every one, as I am actually eager of reading this web site’s
    post to be updated daily. It includes nice information.

    ReplyReply
  253. 19 April 2014laithwaites wine promotional coupons says:

    Now I am going away to do my breakfast, afterward having my breakfast coming
    again to read more news.

    ReplyReply
  254. 19 April 2014Evangeline says:

    Wow, this article is nice, my younger sister is analyzing such
    things, thus I am going to inform her.

    ReplyReply
  255. 19 April 2014Warren says:

    It can make it the first choice of the users as well as the most
    wanted and comfy P2P torrent engine available in the world.

    In most the events the lenders might find it hard in order to
    meet with your specific requires of customers. Many people that weren’t really in search with the
    underneath bit of content but researching bits of writing in relation to domain name registration
    considered the beneath little bit of writing good.

    ReplyReply
  256. 20 April 2014Game of Thrones Saison 4 Episode 3 says:

    Hi, I desire to subscribe for this weblog to
    get most recent updates, so where can i do it please help.

    ReplyReply
  257. 20 April 2014create blog says:

    Keep an eye on your blog stats so that you can determine great
    and bad your overall approach. With the price of registering
    a custom domain name being so low (anywhere from $1 to $50 a year for your basic domain names) there
    is no reason to not register a domain name of your own.
    World wide web products and services this sort of as writing, programming, and style and design
    are naturals.

    ReplyReply
  258. 21 April 2014subway surf hack says:

    What’s up colleagues, its fantastic article on the topic of tutoringand fully
    explained, keep it up all the time.

    ReplyReply
  259. 21 April 2014coque iphone 4s says:

    I’ve been surfing online more than 4 hours today, yet I never found any interesting article like
    yours. It’s pretty worth enough for me. In my view, if all site owners and bloggers made good content as you
    did, the web will be a lot more useful than ever before.|
    I couldn’t refrain from commenting. Perfectly written!|
    I’ll immediately seize your rss feed as I can not in finding your email subscription hyperlink or e-newsletter service.
    Do you’ve any? Kindly permit me know so that I may subscribe.
    Thanks.|
    It’s the best time to make some plans for the future and
    it is time to be happy. I have read this post and
    if I could I want to suggest you few interesting things or tips.
    Perhaps you can write next articles referring to this article.
    I desire to read even more things about it!|
    It is the best time to make a few plans for the long
    run and it is time to be happy. I have learn
    this submit and if I may just I wish to recommend you few attention-grabbing
    things or tips. Maybe you could write next articles referring to this article.
    I want to learn even more issues about it!|
    I’ve been browsing online more than 3 hours these days, but I by no means found any interesting article like yours.
    It is lovely worth enough for me. In my opinion, if all web owners and bloggers made
    just right content material as you did, the internet
    shall be much more useful than ever before.|
    Ahaa, its good dialogue regarding this article here at this weblog, I have read all that, so now me also commenting here.|
    I am sure this piece of writing has touched all the internet
    users, its really really fastidious paragraph on building up new webpage.|
    Wow, this piece of writing is fastidious, my younger sister is analyzing such
    things, therefore I am going to let know her.|
    bookmarked!!, I love your site!|
    Way cool! Some very valid points! I appreciate you
    writing this post plus the rest of the website is also really good.|
    Hi, I do think this is an excellent blog. I stumbledupon it ;) I will revisit once again
    since I book marked it. Money and freedom is the greatest way to change, may you be rich and continue to help others.|
    Woah! I’m really loving the template/theme of this website.
    It’s simple, yet effective. A lot of times it’s very hard to get
    that “perfect balance” between user friendliness
    and visual appeal. I must say that you’ve done a very good job with this.
    Additionally, the blog loads extremely fast for
    me on Opera. Outstanding Blog!|
    These are in fact enormous ideas in concerning blogging.
    You have touched some pleasant factors here. Any way keep up
    wrinting.|
    I really like what you guys are usually up too. Such clever work and coverage!
    Keep up the good works guys I’ve you guys to my personal blogroll.|
    Hi there! Someone in my Facebook group shared this site with us so I came to take a look.

    I’m definitely loving the information. I’m bookmarking and will be
    tweeting this to my followers! Fantastic blog and excellent design.|
    I like what you guys are usually up too. This kind of
    clever work and reporting! Keep up the superb works guys I’ve included you guys to our blogroll.|
    Hi would you mind sharing which blog platform you’re working with?
    I’m looking to start my own blog in the near future but I’m
    having a tough time choosing between BlogEngine/Wordpress/B2evolution and Drupal.

    The reason I ask is because your design seems different then most blogs and I’m looking for something unique.
    P.S My apologies for being off-topic but I had to ask!|
    Hello would you mind letting me know which web host you’re
    using? I’ve loaded your blog in 3 different browsers and I must say this blog loads a lot faster then most.
    Can you suggest a good web hosting provider at a
    reasonable price? Thank you, I appreciate it!|
    I love it when people come together and share views. Great site,
    keep it up!|
    Thank you for the auspicious writeup. It in fact was
    a amusement account it. Look advanced to more added agreeable
    from you! By the way, how can we communicate?|
    Howdy just wanted to give you a quick heads up.
    The text in your article seem to be running off the screen in Safari.

    I’m not sure if this is a formatting issue or something to do with web
    browser compatibility but I figured I’d post to let you know.
    The design and style look great though! Hope you get the
    problem resolved soon. Thanks|
    This is a topic which is near to my heart… Cheers! Exactly where are your contact
    details though?|
    It’s very trouble-free to find out any topic on
    web as compared to books, as I found this post at this web site.|
    Does your site have a contact page? I’m having trouble locating it but, I’d like to shoot you an email.

    I’ve got some recommendations for your blog you might be interested in hearing.
    Either way, great blog and I look forward to seeing it expand
    over time.|
    Hola! I’ve been following your web site for some time now and
    finally got the bravery to go ahead and give you a shout out from Austin Texas!

    Just wanted to say keep up the good job!|
    Greetings from Carolina! I’m bored at work so I decided to check out your website
    on my iphone during lunch break. I really like the information you present here and can’t wait
    to take a look when I get home. I’m surprised at how quick your blog
    loaded on my cell phone .. I’m not even using WIFI, just 3G
    .. Anyways, awesome blog!|
    Its such as you read my thoughts! You seem to understand a lot about this, like you wrote the ebook in it or something.

    I feel that you simply can do with some % to
    force the message home a bit, however instead of that,
    this is great blog. A fantastic read. I will certainly be back.|
    I visited several blogs however the audio feature for audio
    songs present at this web site is really wonderful.|
    Hello, i read your blog occasionally and i own a similar one and i
    was just curious if you get a lot of spam responses? If so how do you
    prevent it, any plugin or anything you can advise? I get so much lately it’s driving me
    crazy so any support is very much appreciated.|
    Greetings! Very helpful advice within this article!

    It’s the little changes that will make the greatest changes.
    Thanks a lot for sharing!|
    I really love your site.. Pleasant colors & theme. Did you create this site yourself?

    Please reply back as I’m attempting to create my own website
    and would like to learn where you got this from or what
    the theme is named. Thanks!|
    Hello there! This blog post could not be written any
    better! Looking at this post reminds me of my previous roommate!

    He always kept talking about this. I most certainly will forward this information to him.

    Fairly certain he’s going to have a very good read.
    I appreciate you for sharing!|
    Whoa! This blog looks just like my old one!

    It’s on a completely different topic but it has pretty much the same page layout and design.
    Excellent choice of colors!|
    There is certainly a great deal to find out about this issue.
    I really like all the points you made.|
    You’ve made some really good points there.
    I checked on the web for more information about the issue and found most individuals will go along with your views on
    this site.|
    Hi, I log on to your blogs regularly. Your story-telling
    style is awesome, keep it up!|
    I simply could not leave your website prior to suggesting
    that I really loved the usual information an individual provide to your guests?
    Is going to be again regularly to investigate cross-check new posts|
    I want to to thank you for this wonderful read!! I absolutely loved every little bit of it.
    I’ve got you book marked to check out new stuff you post…|
    Hi, just wanted to mention, I enjoyed this blog post.
    It was inspiring. Keep on posting!|
    I comment whenever I appreciate a post on a site or if I have something to contribute to the discussion.

    Usually it is triggered by the sincerness communicated in the article I read.
    And on this article Simple Single Sign-On for PHP (Ajax compatible)
    - Jasny · web development. I was excited enough
    to drop a thought :-P I actually do have 2 questions
    for you if you usually do not mind. Is it simply
    me or do a few of these responses appear like written by brain dead
    individuals? :-P And, if you are posting at additional sites, I’d
    like to keep up with anything new you have to post.
    Would you list all of all your social sites like
    your Facebook page, twitter feed, or linkedin profile?|
    Hello, I enjoy reading through your post.

    I like to write a little comment to support you.|
    I every time spent my half an hour to read this blog’s posts every day along with a cup of coffee.|
    I all the time emailed this blog post page to all my contacts,
    since if like to read it after that my links will too.|
    My coder is trying to convince me to move to .net from
    PHP. I have always disliked the idea because of the expenses.
    But he’s tryiong none the less. I’ve been using Movable-type on several websites for about a year and am nervous about switching to
    another platform. I have heard good things about blogengine.net.
    Is there a way I can import all my wordpress content into it?

    Any kind of help would be really appreciated!|
    Howdy! I could have sworn I’ve visited this site before but after going through a few of the posts I realized it’s new to me.
    Nonetheless, I’m certainly happy I stumbled upon
    it and I’ll be bookmarking it and checking back frequently!|
    Terrific article! This is the type of info that are supposed to be
    shared around the web. Disgrace on the search engines for
    now not positioning this publish upper! Come on over
    and seek advice from my website . Thanks =)|
    Heya i’m for the first time here. I came across this board and I
    find It really useful & it helped me out much. I hope to give something
    back and help others like you aided me.|
    Greetings, I believe your blog might be having browser compatibility problems.
    When I look at your blog in Safari, it looks fine however, if opening in IE, it has some overlapping issues.
    I merely wanted to give you a quick heads up!
    Besides that, excellent website!|
    Someone essentially help to make critically posts I’d state.
    That is the first time I frequented your web page and thus far?
    I amazed with the analysis you made to create this particular submit extraordinary.
    Great job!|
    Heya i’m for the primary time here. I found this board and I in finding It truly
    helpful & it helped me out much. I’m hoping to offer one thing again and aid others
    like you aided me.|
    Hi there! I simply would like to offer you a huge thumbs up for the great info you have
    here on this post. I’ll be returning to your site for more soon.|
    I all the time used to study article in news papers but now as
    I am a user of internet thus from now I am using net for content, thanks to web.|
    Your method of explaining the whole thing in this paragraph is
    actually pleasant, all be able to without difficulty be aware of it, Thanks a
    lot.|
    Hi there, I discovered your blog by way of Google at the same time as
    searching for a related subject, your site came up, it looks great.
    I’ve bookmarked it in my google bookmarks.
    Hi there, simply changed into alert to your weblog via Google, and
    found that it is really informative. I am going to
    watch out for brussels. I’ll be grateful if you happen to continue this in future.
    Numerous people can be benefited from your writing.

    Cheers!|
    I’m curious to find out what blog system you’re
    using? I’m experiencing some small security problems with my
    latest site and I’d like to find something more
    safe. Do you have any suggestions?|
    I am really impressed with your writing skills as well as with the
    layout on your weblog. Is this a paid theme
    or did you customize it yourself? Either way keep up the nice quality writing,
    it’s rare to see a nice blog like this one these days.|
    I’m really inspired together with your writing skills as well
    as with the layout on your weblog. Is that this a paid subject or did you
    modify it yourself? Either way keep up the nice high quality writing, it’s rare to peer a great weblog like this one today..|
    Hi, Neat post. There is an issue with your website in web explorer, may test
    this? IE still is the marketplace chief and a huge
    portion of folks will miss your wonderful writing due to this problem.|
    I am not sure where you’re getting your info, but great topic.
    I needs to spend some time learning more or understanding more.
    Thanks for great info I was looking for this information for
    my mission.|
    Hello, i think that i saw you visited my web site thus i came
    to “return the favor”.I am trying to find things to enhance my website!I suppose
    its ok to use some of your ideas\

    ReplyReply
  260. 21 April 2014joann fabric coupon says:

    What’s up to all, how is the whole thing, I think every one is getting more from this web site, and
    your views are fastidious for new users.

    ReplyReply
  261. 21 April 2014foundation problems chicago says:

    If some one needs expert view concerning running a blog afterward
    i recommend him/her to go to see this website, Keep up the good job.

    ReplyReply
  262. 21 April 2014Bf4 hack says:

    Does it make sense to drop multiple twenty dollar bills on a disc
    with only a Saturday afternoon’s worth of gameplay.
    While these attacks only last a short while, there are indications
    that they cost companies around $65 million annually (Cashell, et al.
    Soon, their best artists were drawing every conceivable type of story with a Zombie twist”.

    ReplyReply
  263. 22 April 2014hill climb racing coins hack says:

    They seemed to treat him like a new toy in which they soon lost interest.
    David Brower- First Executive Director of the Sierra Club.
    Fully realizing that future battles could very well have to be fought in winter conditions, Dole began a campaign
    of pestering President Franklin D.

    ReplyReply
  264. 22 April 2014top it certifications 2013 in india says:

    Today, while I was at work, my sister stole my iPad and tested
    to see if it can survive a thirty foot drop, just
    so she can be a youtube sensation. My iPad is now destroyed
    and she has 83 views. I know this is completely off topic
    but I had to share it with someone!

    ReplyReply
  265. 22 April 2014film indonesia jaman dulu yg panas says:

    If you are going for most excellent contents like I do, just go to see this
    site all the time since it gives feature contents, thanks

    ReplyReply
  266. 22 April 2014sell structured settlements says:

    A structured settlement relieves the claimant off the responsibility of planning
    a tax sgelter for their award. You are strongly suggested to do the research before taking this intense decision.
    A bankruptcy purchase may also serve as an effective way to eliminate a competitor.

    ReplyReply
  267. 22 April 2014Hay Day iPhone Hack says:

    Hello, i think that i saw you visited my site so i came to “return
    the favor”.I am trying to find things to improve my web site!I suppose its
    ok to use some of your ideas!!

    ReplyReply
  268. 23 April 2014house cleaning mesa az says:

    My spouse and I absolutely love your blog and find most of your post’s to be exactly what I’m looking
    for. Would you offer guest writers to write content for yourself?
    I wouldn’t mind creating a post or elaborating on many of the subjects you
    write with regards to here. Again, awesome site!

    ReplyReply
  269. 23 April 2014Garageband software free download for pc says:

    I have later on this article described this approach to watching satellite online for free TV in more detail.
    Believe it you aren’t, many investors would like astrological reading and divination to guide them inside their venture.

    Today you will find several free virus scan and removal utilities available on the
    Internet which you’ll be able to take good thing about.

    ReplyReply
  270. 23 April 2014Maxwell says:

    This helps to describe how much sound decibels the sound proofing material to
    block or absorb. They arrive with designed in amplifiers to
    give you the ideal sounds. Quick Fix – Turn off any music or TVs
    you normally leave on.

    ReplyReply
  271. 23 April 2014Wordpress says:

    Thank you for the good writeup. It actually used to be a amusement account
    it. Look advanced to more added agreeable from you!
    However, how can we be in contact?

    ReplyReply
  272. 23 April 2014Ask fm anonymous finder says:

    You really make it seem so easy with your presentation but
    I find this topic to be really something that I think I would
    never understand. It seems too complex and extremely broad for me.
    I’m looking forward for your next post, I will try to get the hang of it!

    ReplyReply
  273. 24 April 2014Best hiring service in dubai says:

    But if you have an area to fill in, it makes a good nurse-maid plant, while other plants are establishing
    themselves, or where other plants don’t want to grow. For the largest selection, start early
    and ask about early booking discounts. Now with some historical context
    in mind we can see that in a very short time how equality can slip away from you.

    ReplyReply
  274. 24 April 2014payday loans says:

    Hi my friend! I wish to say that this post is amazing, nice
    written and include almost all important infos.
    I would like to see more posts like this.

    ReplyReply
  275. 24 April 2014Nuvie Skin reviews says:

    Hi! I could have sworn I’ve been to this blog before but after going through
    many of the posts I realized it’s new to me. Anyhow, I’m definitely delighted I discovered it and I’ll be bookmarking it
    and checking back regularly!

    ReplyReply
  276. 25 April 2014dragons world cheat says:

    First called Labbu by the Sumerians in 3000 BC, this dragon came to be known as Tiamat when that
    civilization gave way to the Babylonians and their mythologies blended.
    If you like world building with a touch of fantasy that isn’t too complex, I would
    recommend Dragons World. s like playing poker, except you have to go through an elaborate application process to get into a game, and
    then when your there, everyone.

    ReplyReply

Write a comment:


eight + = 12