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 / 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.


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?
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.
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
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.
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.
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.
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.
hi arnold, thnx for your sso source code..but i want to connect user name to database(mysql),can you halp me?thnx before..:)
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
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
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
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.
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
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
In both cases make sure that the path is not accessible for your website visitors.
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).
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
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.
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!
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.
Some more info:
I am not using the jaml thingy, it wouldnt work, so i made a simple login form and ajax script instead.
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..
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.
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 !
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.
Great tip! Thanks!
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!
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.
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)
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.
Thank you very much. Very appreciate your works, and I learned a lot from it. Thanks again. :/
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
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
On login page, How can access to $_SESSION['username']?
williamjlp Please read the previous comments. There is no session on the brokers. You need to request the username from the SSO server.
@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..
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
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
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
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
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).
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
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.
Thanks Arnold. Some how, i’m on the track now.
Regards
@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
Good solution, thanks for sharing.
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
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.
thank you very much @arnold,…
sorry, what you mean to 307 and 200 in that picture?
ar_raudy Those are HTTP status codes: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
i Want to implement this on codeigniter with tank auth