Implementing SSO with Vanilla forums
Good Afternoon.
I am building a community site that comprises of various third party technologies and custom code. We want the user experience to be seamless across these technologies and are looking to implement SSO. I have done this already with Magento and it was pretty straight forward however I'm struggling to understand how this is best achieved with Vanilla.
My requirements:
- The solution is not dependent on JavaScript.
- We extend Vanilla in a way that allows us to maintain and patch the software.
- The login functionality of Vanilla is disabled so the only way to log in would be through the single sign on service.
- Users would never log directly into Vanilla.
- Links to login would re-direct back to the SSO page
I've managed to achieve this in Magento as follows:
- Create an observer for the controller_front_init_before event in Magento (this happens sufficiently early enough in the code flow that Magento is initialised however no controller has yet been loaded to facilitate the request)
Check the shared $_SESSION for a 'Logged-in User' object
- If one exists then the user has authenticated themselves.
- We then use the details in $_SESSION to log the user in automatically
If a user exists in the shared $_SESSION but no Magento user is found then we create a new user in Magento and log that user in.
Ideally I'd need to be able to so something similar to this in Vanilla (ie load / create accounts and automatically log a user in)
After some research, I'm not confident this is something that can be easily achieved with Vanilla and wondered if anyone else had been able to achieve this or if anyone is able to point me in the right direction?
Also, apologies if this is in the wrong place, I attempted to post to the developer list but I do not have the correct permission.
Cheers
Rob.
Comments
If I can't do this via JS, and I want it to be completely seamless, I would create a new authenticator that uses the
$_SESSION
super global. Copy the/library/core/authenticators/class.passwordauthenticator.php
file and start hacking away.Search first
Check out the Documentation! We are always looking for new content and pull requests.
Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.
Garden Sessions do not use $_SESSION
grep is your friend.
Hi thanks for your replies.
@hgtonight - Thanks - I'm looking at this class now - so far I have written a plugin that hooks into the
AppStartup
event. This is able to load my Authentication Service which checks to see if a user is logged in - (a user object exists in the current user's $_SESSION) - so from here are you suggesting I overwrite the Gdn_PasswordAuthenticator::authenticate() method and then call that from my plugin? - If so is there a 'correct' way to do this - I am reluctant to 'start hacking away.' - I started looking at Vanilla yesterday and wondered if I'm missing some obvious resources - for example, I can't find much information about the Garden framework apart from a series of blog articles from the creator - which while interesting are not particularly insightful...@x00 Thanks for the heads up - so assuming that session data is stored in the database and not on the webserver itself - I don;t suppose it's possible to move the session over to something like Memcache??
Cheers for the help guys I'm really keen to use Vanilla - but am struggling with the lack of proper documentation - am I missing something or is this everything: http://docs.vanillaforums.com/developers/
Thanks for your time,
Rob.
First the data passed between request is linked to a special cookie which has nothing to do with the authentication related cookie. That data is only stored when needed in the
GDN_Session
table. This is used quite sparingly however. Don't confuse it with validating sessions.The main authentication uses HMAC, which is means it doesn't need to be "stored" on the server at all. Storing authentication sessions on the server make it vulnerable to certain attacks.
HTTP is stateless the session status is purely abstract construct. There is no "Logged On".
What you need to check the session is valid is the hmac algo, which is now native to PHP, plugging in the data the comes with the cookie, plus the cookie salt to create a hash which you compare with the hash that comes with the cookie. You also need to a timing attack proof comparison as if you use the normal equals operator you will be vulnerable to timing attack (think similar to listening for clicks on a dial safe)
grep is your friend.
But anyway, you don't actually need to check vanilla sessions it does that for you, what you want is to initiate the session. There is a standalone gist for creating the cookie.
But what you really need to cover is the user creation.
grep is your friend.
@x00 - thanks for the reply struggling with some of this:
While I appreciate HTTP is a stateless protocol - I'm not quite following what you are describing.
Is there a way to programmatically log a user in to Vanilla for the duration of the request (I have the user stored in the PHP global session so can re-authenticate on each page request to Vanilla no issue)
Is there a way to programmatically create a new user in Vanilla?
There is no logged in. If the cookie can be validated then the session is valid. This is per request.
grep is your friend.
Basically if the cookie is not there create it.
grep is your friend.
Interesting - thanks for your time.
You can force load vanilla, to create a user. Just don't force load all the time, just when needed.
You can also implement a connect method like jsConnect works but server to server.
There is and API application that would also work, but as I understand it is for 2.2 which is not stable.
grep is your friend.
Creating your own authenticator solves this issue. Parse the
$_SESSION
variable. Look for a vanilla user with the same id, if it doesn't exist insert a new user via the user model. If it does, pass that id back to the system and let it handle the session normally (via the HMAC cookie).Search first
Check out the Documentation! We are always looking for new content and pull requests.
Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.
What hgtonight said except wrap that in a very basic cookie detection, so you only do this when there is no cookie present.
grep is your friend.
Once again, thanks for your help - plenty to be looking into! Cheers, Rob.
Right - I've come back to this today - in principle I understand what you have said and have also found an article someone had posted attempting to do something similar with Vanilla and Code Igniter.
https://ellislab.com/forums/viewthread/134946/
I've been playing about with this but have a few questions about the $Configuration settings in
conf\config.php
- The article suggest you can do the following:But in Vanilla 2.1 these don't seem to change anything - also, all of the configuration for Vanilla 2.1 looks different - instead of being uppercase keys - there are multidimensional keys and these are lowercase.
I'm starting to feel a bit of frustration - It's not the lack of support I've received here - more like the lack of documentation and the number of broken links you encounter trying to piece together bits of the puzzle. Telling users that Vanilla is built on top of a powerful framework is one thing - but trying to work with it is something else.
What am I missing..?
I found this page: http://docs.vanillaforums.com/developers/configuration/using/
But is there a list of all the possible configuration settings and what they do?
(I'm aware of the
config-defaults.php
file - have some config options been removed in later versions of Vanilla - if so, how do you safely replace classes?)Rob.
These are not garden or vanilla config values, atleast not since 2.0
The configuration will not help you much here.
I would suggest you take a look how the jsconnect plugin implements SSO:
https://github.com/vanilla/addons/blob/master/plugins/jsconnect/class.jsconnect.plugin.php
There is a "Connect" function in the entrycontroller
https://github.com/vanilla/vanilla/blob/master/applications/dashboard/controllers/class.entrycontroller.php#L391
On line 409 the Event "ConnectData" is fired
Plugins can hook into that event to connect a user with vanilla.
Take a look at how the facebook, openid or twitter sign in plugin does it. They should be a good start.
My themes: pure | minusbaseline - My plugins: CSSedit | HTMLedit | InfiniteScroll | BirthdayModule | [all] - PM me about customizations
VanillaSkins.com - Plugins, Themes and Graphics for Vanillaforums OS
@slRobertS the example you seeing is to do with Vanilla 1 a completely different software.
grep is your friend.
Yes - I had my suspicions it wasn't the version I'm using. It's just a shame there is an absence of solid and concise development resources for the latest version of Vanilla - I've done some more reading around - is it true the Community version is several versions behind the SaaS version?
The OS version is 1 version release (not update) behind the SaaS, as odd numbers are for OS, and even for the SaaS. I think that is fair, becuase it will only be stable on that platform.
Here is a hacky way you can do it.
Alternatively to you could recreate the cookie creation, and only force load when you need to create a user.
You will still need to tie up loose ends such as the entry hardening on vanilla side.
grep is your friend.
I worry about the word 'hack' id much prefer to do this by extending Vanilla and hooking into the plugin system.
I've written a plugin that hooks into the AppStartup event. I believe this is fired after Vanilla has bootstrapped itself but before any controller action is called. This is called every time a user access the forum. So, all good so far.
After here - I'm not quite sure what I should be doing. I've looked at the various SSO plugins but they all depend on the user initiaiting the login event and then responding to that. In my application - the login has already happened.
I'm not sure if I'm thinking in Vanilla terms - but im expecting to do the following:
@ If I can retrieve the internal id Vanilla uses to identify users then I can authenticate a user using this line
Great! - similarly I would also be able to create a user - I'd expect to use the UserModel here but there is no method for creating a user - so again, I appear to be looking in the wrong place.
I was planning on doing this by removing links in the template and then overriding the handlers for the login event. Is it possible in Vanilla 2.1 to extend classes (like it appears to be in the example from version 1)
In all honesty - I've spent quite a bit of my week getting nowhere with Vanilla. I'm disappointed. No reflection on the community - you've all been great - but I'm asking rudimentary questions about things because there is very little documentation - for someone without any previous exposure to the development of Vanillla, from version 1 to version 2.1 some of the things you talk about are not obvious or particularly developer friendly.
I'm quite comfortable looking at code and solving problems, but I find the structure and composition of the Garden framework unintuitive especially compared to other PHP frameworks.
Are the docs here: http://vanillaforums.org/docs relevant for version 2.1.1?
Edit
I see that page was last edited in 2012? - so assuming this is the latest: http://docs.vanillaforums.com/
Depending on which page you are on the Documentation link goes to two separate places...
http://docs.vanillaforums.com/ is the most up to date official documentation.
The source code is the best documentation.
There is also a community wiki at http://vanillawiki.homebrewforums.net/index.php/Main_Page
I still think creating a new authenticator is the best approach for you.
Search first
Check out the Documentation! We are always looking for new content and pull requests.
Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.