SE... what? A novice webmaster's view of guest blogging
What makes people share
Custom Integration of OpenID into Symfony2.
17 Nov 2012
As all of our staff have their email accounts hosted by a certain well-known web company, and that particular company supports the OpenID protocol, we decided to use OpenID as a way to authenticate their login to all our new web tools.
As all of our staff have their email accounts hosted by a certain well-known web company, and that particular company supports the OpenID protocol, we decided to use OpenID as a way to authenticate their login to all our new web tools. This is a very efficient way to manage users because we should never have to worry about resetting a user's password, and they will be using the same password for all of our applications which will make their lives simpler too. We decided to marry this idea with our own centralised user database and allow all our web applications to become clients to this database via a web service. Thus, a user can authenticate into any app using a single username/password and that app then gets all its user data from our central database. What Is OpenID? OpenID is simply a means of allowing users to authenticate themselves using an account from a trusted third party (e.g. Facebook or Google). So, for example, a user logs into your web app using their chosen OpenID provider (whoever they happen to have an account with, say Google). Your login page redirects the user's browser to Google's login form. Once Google has authenticated the user, and the user's browser has been redirected back to your web app, Google's server is contacted directly by your web server to check the user authenticated ok and to get any extra requested details about the user for use in your web app. For example: their forename. Our new web apps are written using Symfony2 Framework and as such it seemed like a good idea to see if there was already a Symfony2 OpenID bundle that we could plug in with minimum development effort. As it turns out, there is a bundle known as the FpOpenIdBundle which seemed at first like it would be perfect for the job. However, the bundle and its documentation are geared towards using Doctrine ORM to store and retrieve the user details. As we wanted to use a central user database that provided a web service for our client applications, we didn't want to use a database to store and retrieve users. We wanted the bundle to retrieve users via our web service. We found it very difficult to use the bundle without this Doctrine/ORM dependency and didn't really want to hack it to pieces. In the end, we opted to create our own bundle. What we did We created a separate Symfony2 bundle for use in all our client applications. We then created our own LoginListener component and simply overrode Symfony's standard component like follows: Change the login listener in the main config file: security.authentication.listener.form.class: Epiphany\<ClientBundleName>\Security\LoginListener The LoginListener needs to extend Symfony's UsernamePasswordFormAuthenticationListener and make use of the LightOpenID service that can be found for PHP to authenticate a user. LightOpenID will need to be included in the composer configuration file. The other major change was to implement our own User and UserProvider classes and specify their use in the application security and service configuration files. Our UserProvider class implemented the UserProviderInterface and called the Web Service to our central user repository, it then returns an object of our own User type (assuming one could be found that matched our OpenID user). The User class needed to implement Symfony's UserInterface to make it work with Symfony's security system. There are some good tutorials on the Symfony2 website to explain how to write a custom user and user provider if you're thinking of doing this yourself. In short, this is how we did it. If you have any questions about the detail, give us a shout.