This is a documentation page for the OpenID Connect Single Sign-on module.

The openid_connect_sso module provides a single sign-on solution based on OpenID Connect.

The OpenID Connect server (central place of login) is a Drupal site running oauth2_server.
The clients are Drupal sites running openid_connect.

After the user's login on the server or logout on any of the network sites, the module starts a redirect chain that visits the SSO script of each site in the network. The SSO script then sets a cookie notifying the parent site of the pending login or logout. When the user visits the actual site, the cookie is read, and the user logged in or out automatically.

This is the same approach used by Google Accounts.

The point of the redirects is to give each site a chance to set a cookie valid for its domain, thus going around the same-origin policy that forbids a site from setting a cookie for another domain. The redirects are fast and unnoticeable, since the SSO script is standalone (no Drupal bootstrap) and only sets the cookie.

Example

Let's say we have four sites:

  • The server: server.com
  • Client A: clienta.com
  • Client B: shop.clientb.com
  • Client C: clientc.com

The SSO script is placed in a directory mapped to a subdomain of each site (a.servera.com, a.clienta.com, a.shop.clientb.com, a.clientc.com).

Login flow

  1. User clicks "Login" on clienta.com.
  2. The site redirects the user to server.com's login page. The user logs in and is redirected back to clienta.com where the login is completed.
  3. clienta.com redirects the user to a.clienta.com which begins the login redirect chain. Each site in the chain sets a cookie, noting that the user is logged in via the SSO server.
    1. a.clienta.com redirects to a.shop.clientb.com.
    2. a.shop.clienb.com redirects to a.clientc.com
    3. a.clientc.com returns the user to a.clienta.com
  4. When the user first visits any other SSO site for the first time, it will detect the cookie set by the SSO script, perform the login flow: redirect to server.com, redirect back to the visited site with an authorization code, and then finally logging the user in.

Logout flow

  1. User goes to shop.clientb.com, clicks logout.
  2. That site (shop.clientb.com) logs the user out and redirects to a.shop.clientb.com. This begins the logout redirect chain. Each site sets a logout cookie and then forwards to the next site in the chain.
    1. a.shop.clientb.com redirects to a.server.com.
    2. a.server.com redirects to a.clienta.com.
    3. a.clienta.com redirects to a.clientc.com.
  3. When the user visits any of the sites in the network (server.com, clienta.com, clientc.com), the logout cookie is detected and logout is performed.

Server setup

  1. Download and install oauth2_server 7.x-1.x-dev, use the "develop" branch of the required library.
  2. Make sure that authenticated users have the Use OAuth2 Server permission.
  3. Go to admin/structure/oauth2-servers and create a server:
    1. Select the "Use OpenID Connect" checkbox.
    2. Under "Enabled grant types" select the "Authorization code" checkbox.
  4. Click the "clients" link for your server, and create a client for each of the client sites:
    1. Select a client_id and client_secret, you will enter them on the client site.
    2. As the redirect url enter the url of your site followed by "/openid-connect/generic".
    3. Select the "Automatically authorize this client" checkbox.
  5. Enable openid_connect_sso.
  6. Setup the SSO script.

Note that openid_connect provides OpenID clients, does nothing when enabled on the server. openid_connect_sso_client redirects to the server, and must not be enabled on the server: it causes redirect loops. It is possible to include the server in the chain of sites which are visited on logout, and to do so, go to admin/config/services/openid-connect-sso and enable SSO and add the first script's redirect path, as you do for the client.

Client setup

  1. Download and install openid_connect (7.x-1.0-beta1 or newer).
  2. Go to admin/config/services/openid-connect. Enable the Generic client and modify the endpoint urls by replacing example.com with the url of your server.
  3. Enable openid_connect_sso and openid_connect_sso_client.
  4. Setup the SSO script (see 'SSO Script Setup' below.
  5. Add the cache exception to settings.php (see 'Caching' below)
  6. Go to admin/config/services/openid-connect-sso to setup the SSO process.
    1. Enable SSO should be checked.
    2. SSO script URL should point to the location of the sso.php script for the first site that you setup earlier in your $network array (for example, either http://a.firstsite.example.com or https://firstsite.example.com/sso.php). This starts the SSO redirection chain which sets login and logout cookies.
    3. Cookie domain should almost always be the normal domain of the client site (clientb.example.com). If you have multiple subdomains which serve the same site (for example, a multilingual site with fr.example.com, de.example.com, and es.example.com), you would want to set the cookie domain on each one to the same thing (example.com). A leading dot for the cookie domain can be used, but is not required.
    4. OpenID Connect client is used to select from the clients that you defined earlier. (usually set to Generic)

SSO Script Setup

You can choose to either have the SSO script in the same directory as your Drupal site (http://yoursite.com/sso.php) or on a subdomain (http://a.yoursite.com).

The subdomain approach allows you to use the same sso.php script for all sites in the network (by mapping all subdomains to the same script on the server). Otherwise the sso.php script needs to be copied to each network site, and the $network array needs to be kept in sync and up to date.

Copy the sso.php script located within the sso directory of the module and edit the $network array as instructed. The $network array can be in any order, in theory.

If you have two different sites sharing the same base domain (for example, site1.example.com and site2.example.com, or subdomain.example.com and example.com), then you should uncomment and enable the $cookie_name_strict = true; setting.

The variable $cookie_name_strict adds the domain name to the cookie name. For example, instead of a cookie named Drupal.visitor.SSOLogout=1, the cookie name will be Drupal.visitor.SSOLogout_www.example.com=1. This ensures that one site (at site.example.com) will not act on the cookie information for another site (at example.com).

Same directory as your Drupal site

Go to admin/config/services/openid-connect-sso and set SSO script URL to, for example, https://clienta.example.com/sso.php.

Copy the sso.php script to your Drupal directory (next to your index.php) file.
Edit the sso.php script and change the $network array as instructed.

Subdomain

Go to admin/config/services/openid-connect-sso and set SSO script URL to, for example, http://a.clienta.example.com.

Copy the sso directory outside of the Drupal modules directory.
Create a subdomain pointing to the sso directory, and set sso.php as the index. Check that your SSO script is available and working at all of the addresses listed in the $network array.

Sample nginx configuration (/etc/nginx/sites-enabled/clienta-sso):

server {
    listen  80;
    include  /etc/nginx/errors.conf;

    server_name http://a.clienta.com;

    root        /data/clienta/docroot/sso;
    access_log  /data/clienta/logs/access-sso.log;

    location / {
        index sso.php;
    }

    # We might not need this?
    location ~ \.php$ {
        fastcgi_pass  unix:/var/run/php5.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  HTTPS $php_https;
        include        fastcgi_params;
        ssi on;
    }

    location ~ /\.ht {
        deny  all;
    }
}

Edit the sso.php script and change the $network array as instructed.

On Apache with cPanel, an .htaccess file can be created in the same directory as the sso.php script with, for example:
DirectoryIndex sso.php

Caching

If your client sites have Drupal page caching enabled, you will have to either add these lines to your settings.php:

// Disable the page cache if an SSO login cookie is set.
if (!empty($_COOKIE['Drupal_visitor_SSOLogin'])) {
  $conf['cache'] = FALSE;
}

or (preferably) apply this core patch: https://www.drupal.org/project/drupal/issues/322104#comment-9855189

If you use Varnish or another caching solution, you will need to implement similar logic to forward the SSO login/logout cookies and to make sure the page isn't cached if the login cookie is set.

Comments

k_zoltan’s picture

Please share the sso.php script too.
It's the last missing part from the puzzle.

bojanz’s picture

It's included in the archive / repository:

http://cgit.drupalcode.org/openid_connect_sso/tree/sso/sso.php

anujsaini’s picture

Hello,

I want to implement OpenID Connect SSO on 2 different sites like http://www.site1.com & http://www.site2.com. I follow exactly the same instruction as mentioned above. But when I open the login page using the URL http://www.site2.com/user it redirect me to the http://www.site1.com and shows the Access Denied error.

Now I'm clueless and need help for further.

Thanks,

Anuj

sonofkrish’s picture

I too got same error. Please help me.

atul4drupal’s picture

Using Salesforce as auth. provider for single signon:
(enable all the Openid Connect & Openid Connect SSO modules :-) )

1) Create a connected app. on salesforce (dont forget to enable API "Enable OAuth Settings").
1.1 Creating connected app (Steps may vary as per your permission level, this is what I followed).
a) click on 'setup' on top right side menu, then on the left side scroll to find 'Develop'
b) Click develop to open sub menu
c) Click 'Remote Access' this will open list of all apps available
d) Under "Connected Apps" click 'New' to create one for you.

1.2 After you created the app. you will get 'Consumer Key' & 'Consumer Secret'. (you need these while configuring openID Connect in drupal, and while creating Auth Provider on salesforce).

1.3 Specify following as call back URL for your connected app. "https://example.com/openid-connect/generic" (replacing example.com with your domain name).

2) Create 'Auth. Provider'
2.1) In the Quick Find search for 'auth'
2.2) From the result click on 'Auth. Providers'
2.3) Add details for the Auth Provider
2.3.1) under Consumer Key - put consumer key from step 1.2
2.3.2) under consumer secret - put consumer secret from step 1.2
2.3.3) Endpoint url's - you can google them
2.3.4) Registration Handler - Auto create this

3) In you drupal setup goto openID connect configuration page (admin/config/services/openid-connect)
3.1) Under 'Enabled OpenID Connect clients' select 'Generic'
3.2) Client ID - put consumer key from step 1.2
3.3) Client Secret - put consumer secret from step 1.2
3.4) endpoints - same from step 2.3.3
3.5) do other settings as per requirement and save.

4) Enable SSO in Drupal by going to 'admin/config/services/openid-connect-sso'
4.1) check Enable SSO checkbox
4.2) under SSO script URL - give path to your sso.php script (Ref. https://www.drupal.org/node/2274367#sso-script-setup)
4.3) under 'OpenID Connect client' select Generic (as this is what we configured) and save.

Once you are done with these example.com/user/login will take you to salecforce for authentication and then direct you back to your portal.

drupalBricks’s picture

I integrated the same as explained above. After login, server redirects to the client site, client1.com. But the login block still shows as previous. When I check the cookies in the browser url bar, it shows a cookie created with client domain name. How to resolve this issues? How to link user and cookie created? any additional modules required?

HansKuiters’s picture

In Server Setup it says: 'Make sure that authenticated users have the Use OAuth2 Server permission.". If I do just that on connecting from client to server I get an access denied on the server. I also need Anonymous users to have the Use OAuth2 Server permission. Might there be something wrong in my settings or has this guide a glitch?

sarath.rajan’s picture

When the user first visits any other SSO site for the first time, it will detect the cookie set by the SSO script, perform the login flow: redirect to server.com, redirect back to the visited site with an authorization code, and then finally logging the user in.

Step 4 : Redirects to the server while visiting the second client is not working. But its logging in once we visit the client2/user/login

Am I missing anything?

Thanks for all your help..

zkent’s picture

We have nearly 100 D7 sites using subdomains of a single domain. Maintaining a sso.php for each site that contains the URL of each site seems odd. Does the script really redirect to every site? Granted, most sites are info only and a user would not need to log in so that eliminates some of them but even if there were 2 dozen sites with logins, are all of those redirects necessary?

bojanz’s picture

Yes. That's how Google's SSO works as well. It's either that or iframe&js trickery ala StackOverflow. Choose your poison.

zkent’s picture

Should the auth server URL be added to the list of servers in sso.php? I am not having good luck with logging in/out. When logging out of a single site, it seems to work but since I remain logged in at the auth site, clicking Log In with Generic logs me back into client site without ever asking for credentials again.

sonofkrish’s picture

It shows access denied. After redirected from site 2 to site 1

Drupal-i-like’s picture

after reading the introduction of this module and the comments above,i was confused that does this module only works for the drupal-sites,but does there anyone who knows how to complete SSO on drupal sites and non-drupal sites.I would be very appreciate recieving your answer.

thanks
Dave Smith

Covfefe’s picture

This is without doubt the most convoluted and confusing process I've ever encountered in Drupal -- matched only by "simple"SAML.

3 different modules , 6 pages of config, and PHP script? And this has to be done on each site?

The documentation, too, is confusing: 'As the redirect url enter the url of your site followed by "/openid-connect/generic".'

"your site"??? which one?

HansKuiters’s picture

It is confusing, but it works fine.

Since you just became a member of the Drupal platform and this is your first post, you might not know what the Drupal Community is about. Drupal is an open source community, projects are developed and maintained mostly in someones spare time. I guess the maintenance team of this project is willing to accept any of your contribution to make it less confusing. Take the challenge and become a contributor!

Covfefe’s picture

So I can expect this to be fixed by the end of the day?

HansKuiters’s picture

You might, if you find someone to do this for you as a paid service. Take a look at https://www.drupal.org/community to see how the community works and how to get involved. Key to an open source community is that you can't just place an order to be fixed. You have three options: get involved yourself, pay someone to do it for you of create an issue and wait for the project maintainers to fix it (if it's a bug or feature request).

Covfefe’s picture

If I ever manage to get this working I'll post some more thorough doco. I'm afraid that's all I'm capable of at the moment.