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 261 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. 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
  228. 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
  229. 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
  230. 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
  231. 26 June 2014Best Miami Dade Roof Repair says:

    Good info. Lucky me I found your site by chance (stumbleupon).

    I have book marked it for later!

    ReplyReply
  232. 27 June 2014Pikavippitila says:

    Olen on selailu verkossa yli 3 tuntia tänään, mutta en koskaan löytänyt mitään mielenkiintoinen artikkeli kuten sinun. On melko arvoinen riittää minulle.

    Mielestäni, jos kaikki sivuston omistajat ja bloggaajat teki hyvää sisältöä kuten teit,
    net on paljon enemmän hyötyä kuin koskaan ennen.
    I voinut vastustaa kommentoi. Poikkeuksellisen hyvin kirjoitettu!

    Tulen heti grab teidän rss koska en voi löytää teidän email tilaus
    linkkiä tai e-uutiskirje palvelu. Onko sinulla mitään? Ystävällisesti anna minut tunnustettava jotta I voi
    tilata. Kiitos.
    On parasta aika tehdä tulevaisuuden suunnitelmia ja on aika olla onnellinen.
    Olen lue tämä viesti ja jos voisin halu ehdottaa sinulle muutama
    mielenkiintoisia asioita tai neuvonta. Ehkä voit voi
    kirjoittaa seuraavaksi artiklat tämän artikkelin. I halua lukea vieläkin asioita
    siitä!
    On täydellinen aika tehdä joitakin suunnitelmia pitkällä aikavälillä ja se aika olla
    onnellinen. Olen oppia Tässä viesti ja jos en voi
    I halua Suosittelen et muutama mielenkiintoisia kysymyksiä tai neuvonta.
    Ehkä voit voi kirjoittaa seuraava artikkelit liittyvät tämän artikkelin. I halua lukea enemmän kysymyksistä noin se!

    Minulla on on selailu on-line suurempi kuin kolme tuntia tapahtumat,
    mutta I koskaan ei suinkaan löysi tahansa kiehtovaa artikkeli
    kuin sinun. On sievä hinnan tarpeeksi riittävä minulle.
    Henkilökohtaisesti, jos kaikki sivuston omistajat ja bloggaajat teki juuri oikea content kuin luultavasti teki, web ehkä paljon avulias kuin koskaan ennen.
    Ahaa, sen miellyttävä keskustelu Tietoa Tämän viesti
    tässä paikassa Tämän kotisivuilta, olen lukenut kaikki, niin tällä hetkellä minulle myös kommentoimalla tässä paikassa.

    Olen varma, että tämä pala kirjallisesti on koskettanut kaikkia internetin käyttäjää, sen todella todella mukavaa
    Edellä rakentamaan uusia kotisivuilta.
    Vau, tämä pala kirjallisesti on nirso, minun sisko analysoi tällaisia
    asioita, siksi Aion kertoa hänet.
    Tallennetut suosikkina, Pidän sivuston!
    Way cool! Jotkut hyvin päteviä! Minä arvostan teitä Raha
    tämä viesti ja loput sivusto erittäin hyvä.
    Hei, Uskon tämä on loistava sivuston. Olen stumbledupon se ;) aion palata jälleen koska olen tallennetaan suosikki se.
    Raha ja vapaus on paras tapa muuttaa, voi sinun olla rikas ja edelleen opas toiset.

    Woah! Olen todella kaivamaan malli / teemana sivustosta.
    Se on yksinkertainen, mutta tehokas. Monta kertaa se on haastavia saada, että
    “täydellinen tasapaino” käyttäjäystävällisyyttä ja ulkonäkö.
    Täytyy sanoa, olet tehnyt erittäin hyvä työtä tässä.
    Myös, blogi kuormat erittäin nopeasti minua varten Internet Explorer.
    Superb blogi!
    Nämä ovat todella loistava ideoita koskee bloggaaminen. Olet koskettanut joitakin miellyttävä asiat täällä.
    Mitenkään pysyä wrinting.
    Rakastan mitä te yleensä liian. Tällaiset taitava
    työn ja kattavuus! Jatkakaa suuri toimii kaverit Olen lisätty te kaverit meidän blogroll.

    Hei! Joku minun Facebook ryhmä jakoi tämän sivuston meille, niin tulin antaa
    sille näyttää. Olen ehdottomasti nauttia tietoja.
    Olen bookmarking ja se tweeting tämä minun seuraajia!
    Ihana blogin ja loistava design ja tyyli.
    pidän mitä te ovat liian. Tällainen taitava työn ja raportointi!

    Jatkakaa loistava toimii guys Minulla sisällytetty te kaverit oma
    blogroll.
    Hei voisitko jakamiseen joka blogi-alustalla olet käyttäen? Olen suunnittelu
    aloittaa oman blogin pian mutta minulla on kova aika päätöksentekoa välillä BlogEngine / WordPress/B2evolution ja Drupal.
    Syy Kysyn koska design ja tyyli näyttää eri sitten useimmat blogeja ja etsin jotain täysin ainutlaatuinen. PS
    Pahoitteluni varten saada off-topic, mutta minun piti kysyä!

    Hei Voisitko saan tietää mikä WebHost olet hyödyntämällä?
    Olen ladannut blogiisi 3 täysin eri selaimet ja
    täytyy sanoa tämän blogin lataa paljon nopeammin sitten suurin. Voitteko ehdottaa
    hyvä internet hosting tarjoajan kohtuullinen hinta?
    Kiitos, arvostan sitä!
    Pidän todella se kun ihmiset niskasta kiinni ja jakaa views.
    Suuri blogi, keep it up!
    Kiitos hyvä kirjailla. Se itse asiassa oli huvi
    huomioon se. Katsokaa eteni lisää lisätään miellyttävä teiltä!
    kuitenkin, kuinka voi me kommunikoida?
    Hei Halusin vain antaa sinulle nopean heads up. Text teidän viesti näyttävät pakoilu näytön IE.
    En ole varma, onko tämä muotoilut myöntämisen tai jotain tekemistä
    web-selain yhteensopivuutta mutta en ajattelin olisin lähettää kertoa.
    layout näyttää hyvältä vaikka! Toivottavasti saat
    ongelma kiinteät pian. Kippis
    Tämä on aihe joka on lähellä sydäntäni … Kippis!
    Jos ovat yhteystietosi vaikka?
    Se on hyvin helppoa selvittää mahdolliset asian on web verrattuna
    kirjat, koska löysin tämän article Tämän kotisivuilta.

    Onko verkkosivusto on yhteyttä sivun? Minulla on ongelmat paikallistamiseen sitä,
    mutta haluaisin ampua olet e-mail. Minulla on ideoita
    blogiisi saatat olla kiinnostunut kuulemaan. Joko niin, hyvä sivusto ja odotan näkeväni sen kehittää ajan.
    Hola! Olen käsittelyssä teidän verkkosivusto kohteelle nyt
    ja vihdoin rohkeutta mennä eteenpäin ja antaa sinulle huutaa pois
    Kingwood Tx! Halusin vain kertoa pysyä erinomainen työtä!

    Terveisiä Florida! Olen Bored to Death töissä joten päätin Selaa teidän verkkosivusto minun iPhone aikana lounastauko.
    I nauttia tiedot et nykyinen täällä ei voi odottaa katsomaan kun pääsen kotiin.
    Olen järkyttynyt kuinka nopea blogiisi ladattu minun mobiili ..
    En edes käyttää WiFi, vain 3G .. Anyways, erinomainen blog!

    Sen kuten sinulla lukenut Minun ajatuksia!
    Olet näytä tietää niin paljon noin tästä, kuten sinulla kirjoitti e-kirja siinä tai jotain. tunnen että et yksinkertaisesti voisi tehdä joidenkin pc ja teho viesti koti bit, mutta muuta kuin, että tämä on ihana blog.
    erinomainen lukea. Minä varmasti takaisin.
    Kävin useita verkkosivut paitsi kuitenkin äänen laatu audio
    kappaleita nykyisten tässä web-sivustojen on todella Superb.

    Moi, luin blogisi ajoittain ja minä omistan samanlaisen ja olin juuri utelias jos saat paljon roskapostia vastauksia?
    Jos niin miten voit vähentämiseksi sen, kaikki plugin tai jotain voi neuvoa?

    Saan niin paljon viime aikoina se tekee minut hulluksi joten kaikki tuki on erittäin tervetullutta.

    Tervehdys! Erittäin hyödyllinen neuvoja tässä nimenomaisessa
    article! On pikku muutoksia jotka tuottavat
    suurin muutoksia. Kiitokset jakamisesta!
    Olen ehdottomasti rakkautta blogiisi .. Iso värit ja teeman.
    Oletko kehittämiseksi sivustosta itsesi? Ole hyvä
    vastata takaisin, koska olen yrittävät luoda minun ikioma sivuston ja haluaisivat selville missä olet
    saanut tämän tai vain mitä teeman on nimetty. Kiitos!

    Hei! Tämä viesti voinut kirjoittaa yhtään paremmin! Lukeminen läpi Tässä article
    mieleeni edellinen kämppis! Hän jatkuvasti pidettävä puhumme tästä.
    minä eteenpäin nämä tiedot hänelle. Jokseenkin varma hän on erittäin hyvä lukea.
    Kiitos jakamisesta!
    Vau! Tämä blogi näyttää aivan kuin minun vanha! Se on kokonaan erilainen viestiketju mutta se on melko sama sivun ulkoasun ja
    suunnittelu. Erinomainen värivalikoima!
    On varmasti paljon tietää Tämän aihe. Rakastan kaikki pisteiden teit.

    Olet tehnyt joitakin ihmisarvoisen kohtia siellä. I Katsoin net lisätietoja tietoa
    asiasta ja totesi useimmat yksityishenkilöt menee yhdessä teidän mielipiteenne tällä sivustolla.

    Hi En tarkistaa teidän uutuudet kuten joka viikko.

    Sinun kirjoittaminen tyyli on mahtava, pitää
    hyvää työtä!
    I vain voinut lähtevät teidän sivusto ennen viittaa siihen, että olen hyvin nauttinut tavallista info yksittäisen tarjota apua vierasta?

    On tulee olla uudestaan Usein to tarkastaa uudet viestit
    tarvitsin kiittää teitä tästä hyvä lukea! I varmasti nautti välein hieman se.
    minulla olet kirja merkintä katsomaan uutta tavaraa post …

    Hei, halusi vain en En nauttinut Tässä viesti.
    Se oli avulias. Pidä lähettämistä!
    Hei Nautin käsittelyssä kaikki teidän viesti. I kuin halusi kirjoittaa pienen kommentin tukea teitä.

    I joka kerta vietin puoli tuntia lukea tämä
    verkkosivu ‘s artikkelit koko ajan sekä muki kahvia.

    I joka kerta lähetetään tämän kotisivuilta post sivu all my
    kaveria, vuodesta jos haluat lukea sitä sitten minun ystäviä
    myös.
    Oma kehittäjä yrittää suostutella minun siirtyä.
    Netto PHP. Olen aina pitänyt ajatusta koska kulut.
    Mutta hän tryiong kuitenkin. Olen käyttänyt liikkuvan tyyppi
    on eri verkkosivustoja noin vuoden ja olen huolissani vaihtamaan toiselle alustalle.
    Olen kuullut fantastisia asioita blogengine.net. Onko niin voin tuonti kaikki minun wordpress virkaa siihen? Kaikenlainen apu olisi todella arvostaa!

    Hei! Olisin voinut vannoa Olen vieraili tämä blogi ennen mutta sen jälkeen läpi moni viestit tajusin se on uutta minulle.
    Anyways Olen ehdottomasti onnellinen huomasin sen ja otan kirja -merkintä se ja tarkkailun takaisin usein!
    Kamalaa article! Eli sellaista tiedot että pitäisi
    jaettava poikki internet. Shame on Google kohteelle ei paikannus Tämän sietää
    korkeampi! Tule tänne ja kuulla minun sivusto.
    Kiitos =)
    Heya olen ensimmäistä kertaa täällä. I törmäsin tämän hallituksen ja pidän todella hyödyllinen ja se auttoi
    minua paljon. Toivon antaa jotain takaisin ja Tuen toiset kuin sinä
    auttoi minut.
    Moi, Uskon Uskon sivustosi ehkä ottaa selaimella
    yhteensopivuus tiedotteet. Kun tutustumaan blog Safarissa, se näyttää hyvältä mutta kun aukko in IE, se
    sai joitakin päällekkäisiä asioita. Olen vain Halusin antaa sinulle nopean heads up!
    Sen lisäksi, että, ihana sivuston!
    Joku olennaisesti auttamaan tehdä vakavasti artikkelit Saatan valtion .

    Eli ensimmäistä kerta kun suosimissa teidän sivuston sivulle ja tähän pisteeseen? I
    hämmästynyt kanssa analyysin teit luoda tässä julkaista uskomattomia.

    Erinomainen toiminta!
    Heya Olen on ensimmäistä aikaa täällä. I löytänyt tämän hallituksen enkä löytämisessä Se todella hyödyllinen & se auttoi minua paljon. Toivon esitellä jotain takaisin ja Apua toiset kuin sinä auttanut minut.

    Hei! en yksinkertaisesti haluaisi tarjota sinulle
    iso peukkua oman loistava tietoa olet täällä tähän tehtävään. palaavat sivustosi lisää pian.
    I käytetään lukea Edellä lehtiin, mutta nyt olen käyttäjä
    net ollen nyt olen käyttäen netin viestit, kiitos web.

    Sinun avulla selittämällä kaikki Tässä viesti on todella miellyttävä, kaikki kyettävä vaivattomasti olla tietoinen se , Kiitos
    paljon.
    Hei siellä, huomasin teidän kotisivuilta käyttämällä Google samaan aikaan kuin etsivät samanlainen viestiketju, sinun sivuston tänne tuli, se näyttää
    olevan kuin hyvä. Olen kirjanmerkiksi se minun google kirjanmerkit.

    Hei siellä, yksinkertaisesti on varuillaan teidän weblog thru Google, ja sijaitsevat että se todella informatiivinen. Olen menossa varoa Brysselissä.
    Aion arvostamaan niille, jotka jatkaa Tässä in tulevaisuuden. Monet
    muut ihmiset luultavasti hyötyneet teidän kirjallisesti.
    Kippis!
    Olen utelias kuulemaan, mitä blogi järjestelmä olet ollut
    työskennellyt? Olen ottaa jotkut vähäisiä turvallisuuteen kysymyksiä minun uusin blog ja olisin haluavat löytää jotain turvallinen. Onko teillä suosituksia?

    Olen äärimmäisen todella vaikuttunut kirjoittamista ja kanssa layout teidän blogi.
    Onko tämä maksettu teeman tai ette muokata itse? Joko niin pysyä erinomainen laatu
    kirjallisesti, on harvinaista nähdä mukava blogi kuten tämä näinä päivinä.

    Olen todella innoittamana yhdessä teidän kirjallisesti taidot
    ja kanssa rakenne teidän weblog. Onko tämä maksettu teema
    tai ette muokata se oman itsensä? Anyway pitämään up erinomainen laatu kirjallisesti, se harvinainen nähdä
    mukava weblog kuten tämä näinä päivinä ..

    Hei, Siisti postitse. On ongelma yhdessä kotisivuilta in netti tutkimusmatkailija,
    olisivat testi tämän? IE silti on markkinapaikka päällikkö ja valtava komponentti muut ihmiset tuottaa kulkemaan teidän ihana kirjallisesti
    takia tämän ongelman.
    en ole varma missä olet saada info, mutta loistava
    aihe. Olen tarvitsee viettää aikaa oppimiseen paljon tai
    ymmärrystä enemmän. Kiitos ihana info Etsin tätä info lähetystyöhön.
    Hi, luulen, että olen nähnyt olet käynyt minun blogi niin tulin “vastapalveluksen”.
    Olen yrittää löytää asioita tehostaa minun site! Oletan sen ok käyttää
    muutamia ideasi!!
    Hi, tunnen että i saha vierailitte weblog niin i tänne tuli to
    tuotto ?. olen yrittää löytää kysymyksiä to tehostaa
    minun verkkosivuilla Oletan sen ok käyttää muutaman annettu
    teidän oivallukset!!
    Hei siellä, vain tuli varuillaan blogiisi Googlen kautta,
    ja totesi, että se todella informatiivinen. Olen menossa varoa Brysselissä.

    Aion kiitollinen jos jatkat tätä tulevaisuudessa. Monet ihmistä on hyötynyt kirjoittamista.
    Kippis!
    Olen nyt ei varma jolloin olet saada info, kuitenkin loistava aihe.
    I on viettää taas selvittämällä enemmän tai treenata enemmän. Kiitos varten ihana tiedot
    Olin hakevat tätä tiedot lähetystyöhön.
    Hei minun perheenjäsenenä! I halua sanoa, että tämä
    post on uskomattomia, loistava kirjoitettu ja tulevat noin kaikki elintärkeää tietoja .

    olisin kuin katsomaan enemmän virkaa näin.
    Hi! Pidän todella kirjoituksesi niin paljon! osuus me pitää yhteyttä extra noin teidän viesti
    AOL? I need asiantuntija tässä alue ratkaisemiseksi minun ongelmani.
    Ehkä se sinua! Katse eteenpäin peer sinulle.
    Olen todella nauttien teema / suunnittelu teidän verkkosivusto.
    Oletteko koskaan joutunut mitään web-selain yhteensopivuus ongelmia?

    kourallinen blogissani lukijoita ovat valittaneet minun sivuston Ei toimivat oikein Explorerissa, mutta näyttää hyvältä in Firefox.
    Onko teillä suosituksia avulla korjata tämän ongelma?

    Suuri info. Lucky minulle Löysin äskettäin blogiisi vahingossa (stumbleupon).
    Olen teokseni kohdalla se myöhempää!
    Se on vaikuttava että saat ajatuksia tältä pala kirjallisesti sekä meidän väitettä valmistettu täällä.

    Jos haluaisi ja parantamiseksi kasvavat teidän tietoa yksinkertaisesti jatkuvasti käydä tätä
    kotisivuilta ja päivitetään Viimeisin juorut lähetetty tänne.

    Mitä Tapahtuu Olen uusi tässä, olen luiskahtanut tämän minulla on löydetty Se ehdottomasti avulias ja se on auttanut minua kuormia.
    ja antaa rahoitusosuus & Apua eri asiakkaat kuten sen auttanut minut.

    Iso työtä.
    Wow, että mitä olin tutustuen varten, mitä data!
    nykyisten täällä tähän verkkosivusto, kiitos admin Tämän site.

    Jos halu ja saada paljon tämän Edellä niin sinun täytyy hakea Näiden menetelmiä sinun wonia verkkosivusto.

    Se on uskomattomia Edellä hyväksi kaikki verkossa ihmiset; ne saada etuuden siitä olen varma.

    Olen lukenut jotkut hyvä tavaraa täällä. Ehdottomasti hinnan kirjanmerkillä
    uudelleenarvioimista. I ihme kuinka niin paljon vaivaa asetat ja tekevät tällaista fantastinen informatiivinen sivuston.
    Eli suuri tip varsinkin kuin uusia blogosphere.
    Lyhyt mutta erittäin tarkka info … Kiitokset jakaa tämän yhden. Täytyy lukea post!

    Olen tutkineet varten pikku mistään laadukkaan artikkeleita tai
    blogi viestejä tässä tavallaan alue. Exploring Yahoon I lopulta luiskahtanut
    tämän kotisivuilta. Lukeminen Tässä info Joten Olen iloinen ja välittää että Olen uskomattoman hyvä outo fiilis selville tarkalleen mitä tarvitsin. I niin paljon kiistatta tekee
    tiettyjä ja tehdä ei omit Tässä sivustosta ja tarjoaa se näyttää säännöllisesti.

    Luettuani tämän uskoin se oli pikemminkin valaiseva.

    ReplyReply
  233. 27 June 2014hack facebook 2014 says:

    I do accept as true with all of the concepts you have
    presented in your post. They’re very convincing and will certainly
    work. Still, the posts are very short for beginners.
    May you please prolong them a bit from subsequent time?
    Thanks for the post.

    ReplyReply
  234. 29 June 2014Maurice says:

    Very quickly this web page will be famous amid all blog viewers, due to it’s fastidious content

    ReplyReply
  235. 1 July 2014good mattress for sale says:

    I take pleasure in, result in I found exactly what I used to be looking
    for. You’ve ended my 4 day lengthy hunt! God Bless you man. Have a
    great day. Bye

    ReplyReply
  236. 1 July 2014Top Eleven Hack iOS says:

    In summary, your wedding is a serious moment for declaring your love and
    commitment to each other. However Top 10 Hack into Best 11
    sports boss Bridal party crack prime 14 hack power generator is usually a most liked topic of debate amongst monarchs, presidents
    and dictators, Prime 10 Crack Best 10 sports manager Bridal party chop
    best 11 hack generator is usually displaying increasingly more in the attitudes on the fresh as well as upwardly mobile.
    The dancing fountain water show in front of the property
    along the Strip is an absolute must – see attraction that is a
    huge draw and quite impressive, particularly at night.

    ReplyReply
  237. 2 July 2014coffee clubs says:

    A person necessarily help to make severely posts I might state.
    This is the first time I frequented your website page and so far?
    I surprised with the research you made to make this actual submit extraordinary.
    Great process!

    ReplyReply
  238. 2 July 2014Mansions 17749 collins ave Miami Beach says:

    I visited multiple sites however the audio feature for audio songs current at this website is actually superb.

    ReplyReply
  239. 3 July 2014cheap nike airmax says:

    Wow that was strange. I just wrote an very long comment but after I clicked submit my comment didn’t show up.
    Grrrr… well I’m not writing all that over
    again. Anyway, just wanted to say superb blog!

    ReplyReply
  240. 3 July 2014buy kamagra usa online says:

    Every weekend i used to go to see this web site, for the reason that
    i wish for enjoyment, since this this site conations in fact good
    funny stuff too.

    ReplyReply
  241. 4 July 2014Tangela says:

    Thanks for all this details, i lookup a very good smartphone for my father, i
    was pondering about the xperia Z2, i discovered it a a
    incredibly lower price on amazon http://amzn.to/1t1QBsL , what
    do you assume about it? Someone can share his critique?

    ReplyReply
  242. 8 July 2014Pool Live Tour Hack says:

    It’s a shame you don’t have a donate button!
    I’d without a doubt donate to this fantastic blog!
    I suppose for now i’ll settle for book-marking and adding your RSS feed to
    my Google account. I look forward to fresh updates and will talk about this site with my Facebook group.
    Chat soon!

    ReplyReply
  243. 8 July 2014https://www.google.com says:

    I will right away clutch your rss feed as I can not in finding your email subscription hyperlink or e-newsletter
    service. Do you have any? Please allow me understand in order that I could subscribe.
    Thanks.

    ReplyReply
  244. 8 July 2014opiate withdrawal symptoms says:

    Great items from you, man. I have take note your stuff prior to and you’re just
    too excellent. I actually like what you have bought here,
    certainly like what you are saying and the way through which
    you are saying it. You’re making it entertaining and you still care for to stay it smart.
    I cant wait to read far more from you. This is actually a wonderful website.

    ReplyReply
  245. 8 July 2014Adoption Network Law Center review says:

    Clearskincare Microdermabrasion cream with gylcolic is a revolutionary exfoliating cream for acne prone and
    sun damaged skins. 1) How many families does the agency have in its China Waiting Child program.
    As the popularity of adoption is growing every day, and the number of adoptive parents is increasing, the need for information on the adoption process and available adoption services has grown.

    ReplyReply
  246. 9 July 2014rc cars says:

    Nitro with a strong RC car suggests it runs on a combination of
    two things. Go ahead and fire it up, allowing the engine to run for a while and warm up.

    It scored a paltry 17 points out of a possible 100.

    ReplyReply
  247. 9 July 2014Toronto waterproofing a basement wall says:

    Interesting blog! Is your theme custom made or did
    you download it from somewhere? A theme like yours with
    a few simple adjustements would really make my blog
    stand out. Please let me know where you got your design. Thanks

    ReplyReply
  248. 9 July 2014http://gg.gg/2iyu8 says:

    Wow, fantastic blog layout! How long have you been blogging for?
    you made blogging look easy. The overall look of your site is magnificent,
    as well as the content!

    - cliquez ici
    - cliquez ici
    - cliquez ici
    - cliquez ici
    - cliquez ici
    - cliquez ici

    ReplyReply
  249. 9 July 2014Moving apt reviews says:

    You are going to be amazed how frequently he is going to be
    the person to approach you. Before you place your items innto the bin you should make sure to
    shake them out, and inspect for any roaches, taqke the time to look very carefully because baby ones are very tiny annd hard
    to see. You should have received att least 3 calls from every 100 cards, no matter if your presentation was
    a mess or not.

    ReplyReply
  250. 10 July 2014Bonati Institute webpage says:

    Pretty! This was an incredibly wonderful article. Many thanks
    for providing this info.

    ReplyReply
  251. 11 July 2014Socisynd Reviews says:

    Keep in mind that consistency is imperative in this new age of consolidation. Has social network
    marketing created hurdles in the ways we communicate.
    Also, utilize the various on line resources you may have.

    ReplyReply
  252. 16 July 2014Hatha joga says:

    We stumbled over here coming from a different page and thought I should check things out.
    I like what I see so now i’m following you. Look forward to
    looking over your web page repeatedly.

    ReplyReply
  253. 18 July 2014processors says:

    Nowadays, laptop or computer keep track of am there apportioned straight into CRT
    afterward LCD keep track of. CRT watch lives equipped
    with a CRT screen appear afterward finger reminiscent with the TELLY.

    Their primary difficulties include the load afterward dimensions.
    In recent years, stayed close to broke open out of your habit (except in some zastosowanimi which nonetheless am successful excel) in favor of
    LCD screen, and that is baptised for your fluid crystal panel, which often supplanted the realized CRT draw pipe.
    The value with the minor aspects on the crest is frequently reduce
    icon excellence.

    ReplyReply
  254. 19 July 2014singing classes for Kids says:

    It’s fantastic that you are getting ideas from this piece of writing as well as from our discussion made at this time.

    ReplyReply
  255. 20 July 2014Stardom Hollywood Hack says:

    As the admin of this web site is working, no question very soon it will be famous, due too its feature contents.

    ReplyReply
  256. 22 July 2014redsn0w download says:

    I like this article! Also, check out my RedSnow
    site here: http://www.redsn0w.us/

    ReplyReply
  257. 22 July 2014รถยนต์มือสอง says:

    May I simply just say what a comfort to discover someone
    that really knows what they’re talking about on the internet.
    You certainly understand how to bring an issue to light and make it important.

    A lot more people have to read this and understand this side of your story.
    I can’t believe you’re not more popular given that you most certainly
    possess the gift.

    ReplyReply
  258. 23 July 2014,,brazil football shirt says:

    Your style is very unique in comparison to other folks
    I have read stuff from. Thanks for posting when you’ve got the opportunity, Guess I will just
    book mark this site.

    ReplyReply
  259. 23 July 2014baju jumpsuit says:

    As a master hormone, HGH influences all parts of the body, playing a major role in the
    development of cells, muscles and organs. Here’s something you
    probably aren’t awsare of: Some of your best bets aren’t
    listed in the travel websites schedules. When you are able to strike
    a good posture, then it is also possible to obtain your maximum height.

    ReplyReply
  260. 23 July 2014Adoption Network Law Center says:

    Sometimes single mothers and couples may encounter such situations wherein childhood becomes impossible for
    them. As an individual, a nonprofit organization, or a company, you can truly make a difference.
    With time changes, Vietnam being one day ahead of the United States, it
    is very possible Nia was born on or around March 7th’.

    ReplyReply
  261. 23 July 2014outsourcing company says:

    This increases productivity and the overall quality.
    The consultants of Internet marketing help its clients in increasing thee web traffic over their internet sites.
    More and more companies have begun outsourcing eveen auditing and accounting firms to
    take responsibility over their financial transactions and deal with documents, papers and reports that needs
    to be filed and accomplished in order to get the most accurate status of the developments and flaws of their
    businesses.

    ReplyReply

Write a comment:

*