Simple Single Sign-On for PHP
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.

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 / Rich internet application
-> Try it! <-
SSO and RIA applications often don’t go well together. With an RIA 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.
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.
18 Apr 2009 Arnold Daniels





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?
can be useful for someone willing to use SSO in his enterprise, for example between different intranet/extranet solutions.
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.
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.
Is it possible to just take and use (and modify) this solution, or you have some specific licence requirements on in?
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
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
Great tutorial! Thanxs
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.
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.
Hi !
I can’t setup server SSO. Server error. Can You send full source code and guide detail about SSO ?
Thanks
Hi,
Iam getting curl_init() error , when iam using download files of SSO are using in local system.
Please help me.
Ram, are you sure that you have the curl extension? If so, post the exact PHP error and we’ll have a look.
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.
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
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
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:
This really is all the support I’m willing to give on this matter. Otherwise please switch to a linux based system.
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
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 ?
A program should never crash, so that is not normal.
(I’ll talk to yancey and add comments if that is useful)
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.
Hi,
Thanks for this great article, very useful to me. I will try it and give feedback here.
Thanks again.
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:
That should give you a clue what’s going wrong.
Thanks Arnold’s
Thanks for your help
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
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
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
In that case you should save the client session id (line 132/133) as
David: Not attached means that PHP failed to create the symlink in function ‘attach()’ of server/sso.php.
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:
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?
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!
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.
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.
if (!file_exists($link)) $attached = symlink($targetDir, $file);, its nor working in my server. its always return null.
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.
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?
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:
Function ’symlink’ [28], is used on the SSO server. You don’t need [27] if you use [28].
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..
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.
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.
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
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.
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
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
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.
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
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.
Thank you very much Arnold, it looks working! Once more thanks
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.
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).
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?
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.
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
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.
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.
$_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.
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.
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,
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”:
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:
After that, you can completely remove links_path property and its initializing in __construct funnction.
Hope it helps
Thiet Doan: The script doesn’t return a 403 http response, so check the URLs and otherwise look at the apache error log.
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?
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?
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
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.
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
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).
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.
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.
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
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'].
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
Sriman: The url to the SSO server (in broker/sso.php on line 16) is not configured correctly.
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
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.
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
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
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.
Very informative article. This just made things quite clear. Specially i like the part when images have been explained using http response codes.
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
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.
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.
Thank you, it really works, We’ve implemented your code on program using CI framework. Still wondering if it can be used with Moodle.
Hi Arnorld,
it works fine on my localhost, nice share..
@nizar : it would be nice if you could share your implementation on CI application…
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.
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.
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.
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.
Hello Arnold,
As you are big programmer, i think you know the solution how to check and fix , could you please help me in finding out the firewall exits or not, and if exist then how to fix
Thanks in advance