Single Sign-on With Rails, Wordpress and Oauth2

Implementing Single Sign-on Using Rails, Oauth2 and Wordpress as an Oauth Provider.

Object Partners

In this post I will explain how to configure Rails to perform single sign-on authentication using Oauth2 and your hosted Wordpress site as an authentication provider.

I’ve worked on a few projects lately where there was a need to integrate a Rails site with an existing Wordpress site in a Single Sign On fashion but without authenticating against a central auth store or use of an SSO appliance.  It is very easy to turn an existing Wordpress installation into an OAuth provider and skip the hassle of maintaining a central authentication store or a conversion effort for users already using your Wordpress blog.

Turning Wordpress into an Oauth2 Provider

In order to turn our existing wordpress installation into an Oauth2 provider we first have to install the Wordpress Oauth2 Complete plugin.  The official plugin in the Wordpress plugins repository is missing some recent enhancements so I recommend installing from the 1.0.4 release on github: https://github.com/justingreerbbi/wordpress-oauth/archive/1.0.4.zip

General Installation Steps:

  1. Upload ouath2-complete to the /wp-content/plugins/ directory or use the built in plugin install by WordPress
  2. Activate the plugin through the ‘Plugins’ menu in WordPress
  3. Click ‘Settings’ and then ‘permalinks’. Then simply click ‘Save Changes’ to flush the rewrite rules so that OAuth2 Provider permalinks are generated for the site.
  4. Last you must configure an Oauth2 client but we will come back to this after we get our rails app ready to authenticate against our Wordpress site.

Authenticating Rails Against Wordpress Oauth Provider

1. Create new rails app.

rails new omniauth-wordpress-oauth2-plugin-example . --database=sqlite3 -T

2. Add devise / omniauth gems to configuration file.

#authentication framework
gem 'devise'
#oauth2 integration
gem 'omniauth'
#wordpress oauth strategy
gem 'omniauth-wordpress-oauth2-plugin', github: 'jwickard/omniauth-wordpress-oauth2-plugin'  

3. Run bundle install

bundle install

4. Run devise install / follow installation instructions post generator.

rails g devise:install

5. Generate devise user & run migrations

rails g devise user
rails db:migrate

6. Configure Your Wordpress Provider installation

Install Oauth2 provider plugin for your wordpress site:

https://github.com/jwickard/wordpress-oauth

Create client entry for your rails app with the callback key set to: http://your-rails-site.com/users/auth/wordpress_oauth2/callback wp config panel

Save the generated key & secret for next step

7. Configure Devise / Omniauth provider information

Add provider to devise initializer config/initializers/devise.rb

config.omniauth :wordpress_oauth2, ENV['APP_ID'], ENV['APP_SECRET'],
                  strategy_class: OmniAuth::Strategies::WordpressOauth2Plugin,
                  client_options: { site: 'http://yourcustomwordpress.com' }

8. Add routes configuration

Update routes config/routes.rb to add omniauth_callbacks controller

devise_for :users, controllers: { omniauth_callbacks: 'omniauth_callbacks' }

9. Create Callbacks Controller

Easiest to just create the class app/controllers/omniauth_callbacks_controller.rb instead of running generator.

class OmniauthCallbacksController < ApplicationController

  def wordpress_oauth2
    #You need to implement the method below in your model (e.g. app/models/user.rb)
    @user = User.find_for_wordpress_oauth2(request.env["omniauth.auth"], current_user)

    if @user.persisted?
      flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Wordpress Oauth2"
      sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
    else
      session["devise.wordpress_oauth2_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

end

10. Update User Model

Update user to be omniauthable

devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable

Update User model to find users by oauth provider data:

def self.find_for_wordpress_oauth2(oauth, signed_in_user=nil)

    #if the user was already signed in / but they navigated through the authorization with wordpress
    if signed_in_user

      #update / synch any information you want from the authentication service.
      if signed_in_user.email.nil? or signed_in_user.email.empty?
        signed_in_user.update_attributes(email: oauth['info']['email'])
      end

      return signed_in_user
    else
      #find user by id and provider.
      user = User.find_by_provider_and_uid(oauth['provider'], oauth['uid'])

      #if user isn't in our database yet, create it!
      if user.nil?
        user = User.create!(email: oauth['info']['email'], uid: oauth['uid'], provider: oauth['provider'],
                            nickname: oauth['extra']['user_login'], website: oauth['info']['urls']['Website'],
                            display_name: oauth['extra']['display_name'])
      end

      user
    end

  end

Wrapping Up

Now when an authenticated resource is requested on your rails site, the user will be redirected to the wordpress auth provider to login.  When the user has authenticated, they will be redirected back to your rails application and your app will receive a hash of user data passed from the authentication source:

--- !ruby/hash:OmniAuth::AuthHash
provider: wordpress_oauth2
uid: '2'
info: !ruby/hash:OmniAuth::AuthHash::InfoHash
  name: Joe Sandstone
  email: jsandstone@example.com
  nickname: jsand
  urls: !ruby/hash:OmniAuth::AuthHash
    Website: http://example.com
credentials: !ruby/hash:OmniAuth::AuthHash
  token: 4070b5be481b1a4110797763ac27359c1d1da3bb
  refresh_token: 212597ee673d630cfb95a77a69900c7ead1d3e19
  expires_at: 1387912450
  expires: true
extra: !ruby/hash:OmniAuth::AuthHash
  ID: '2'
  user_login: jsand
  user_nicename: jsand
  user_email: jsandstone@example.com
  user_url: http://example.com
  user_registered: '2013-12-12 15:29:34'
  user_status: '0'
  display_name: Joe Sandstone

More Information

Demo Application: https://github.com/jwickard/omniauth-wordpress-oauth2-plugin-example

That’s it!  Thanks!

Share this Post

Related Blog Posts

Unknown

Recovering a commit from Githubs Reflog

February 11th, 2014

Gits reflog is a powerful feature that allows a user to recover from almost any error. Github doesnt offer direct access to the reflog of the backing repository but using a couple of Githubs APIs, we can recover a commit from the remote reflog.

Object Partners
Unknown

Getting started with git svn

February 4th, 2014

Getting started with git svn

Object Partners
Unknown

The Creatives on Agile and QA teams

January 10th, 2014

Agile and QA teams both have their compliment of Creatives who don’t fit the mold yet provide tremendous value to the team through the very traits that set them apart.

Object Partners

About the author