From eeb9866d50e35b8f8b75e59aed582caba533778f Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Sat, 28 Feb 2015 15:56:41 +0000 Subject: [PATCH 1/1] Add support for Google OAuth2 authentication This replaces OpenID authentication, which is going away soon, but provides an upgrade path where we can migrate users that already have a Google OpenID setup to the new system transparently. --- Gemfile | 1 + Gemfile.lock | 11 +++++++++++ app/controllers/user_controller.rb | 23 ++++++++++++++++------- app/helpers/user_helper.rb | 2 +- app/views/user/account.html.erb | 2 +- app/views/user/login.html.erb | 4 +++- app/views/user/new.html.erb | 2 +- config/example.application.yml | 4 ++++ config/initializers/omniauth.rb | 10 +++++++++- lib/auth.rb | 4 ++++ 10 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 lib/auth.rb diff --git a/Gemfile b/Gemfile index 5db975f81..7c916b011 100644 --- a/Gemfile +++ b/Gemfile @@ -57,6 +57,7 @@ gem "actionpack-page_caching" # Omniauth for authentication gem "omniauth" gem "omniauth-openid" +gem "openstreetmap-omniauth-google-oauth2", ">= 0.2.6.1", :require => "omniauth-google-oauth2" # Markdown formatting support gem "redcarpet" diff --git a/Gemfile.lock b/Gemfile.lock index aa53ba8ba..8940c1fdf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -150,11 +150,21 @@ GEM omniauth (1.2.2) hashie (>= 1.2, < 4) rack (~> 1.0) + omniauth-oauth2 (1.2.0) + faraday (>= 0.8, < 0.10) + multi_json (~> 1.3) + oauth2 (~> 1.0) + omniauth (~> 1.2) omniauth-openid (1.0.1) omniauth (~> 1.0) rack-openid (~> 1.3.1) openstreetmap-i18n-js (3.0.0.rc5.3) i18n + openstreetmap-omniauth-google-oauth2 (0.2.6.1) + jwt (~> 1.0) + multi_json (~> 1.3) + omniauth (>= 1.1.1) + omniauth-oauth2 (>= 1.1.1) paperclip (4.2.1) activemodel (>= 3.0.0) activesupport (>= 3.0.0) @@ -305,6 +315,7 @@ DEPENDENCIES omniauth omniauth-openid openstreetmap-i18n-js (>= 3.0.0.rc5.3) + openstreetmap-omniauth-google-oauth2 (>= 0.2.6.1) paperclip (~> 4.0) pg poltergeist diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 367c0471d..c7e44dab6 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -227,7 +227,7 @@ class UserController < ApplicationController @user.status = "pending" - if @user.auth_provider.present? && @user.auth_uid.present? && @user.pass_crypt.empty? + if @user.auth_provider.present? && @user.pass_crypt.empty? # We are creating an account with external authentication and # no password was specified so create a random one @user.pass_crypt = SecureRandom.base64(16) @@ -237,7 +237,7 @@ class UserController < ApplicationController if @user.invalid? # Something is wrong with a new user, so rerender the form render :action => "new" - elsif @user.auth_provider.present? && @user.auth_uid.present? + elsif @user.auth_provider.present? # Verify external authenticator before moving on session[:new_user] = @user redirect_to auth_url(@user.auth_provider, @user.auth_uid) @@ -250,9 +250,9 @@ class UserController < ApplicationController end def login - if params[:username] || params[:openid_url] - session[:referer] ||= params[:referer] + session[:referer] = params[:referer] if params[:referer] + if params[:username] || params[:openid_url] if params[:openid_url].present? session[:remember_me] ||= params[:remember_me_openid] redirect_to auth_url("openid", params[:openid_url]) @@ -496,11 +496,21 @@ class UserController < ApplicationController when "openid" email_verified = uid.match(%r{https://www.google.com/accounts/o8/id?(.*)}) || uid.match(%r{https://me.yahoo.com/(.*)}) + when "google" + email_verified = true else email_verified = false end - if user = User.find_by_auth_provider_and_auth_uid(provider, uid) + user = User.find_by_auth_provider_and_auth_uid(provider, uid) + + if user.nil? && provider == "google" + openid_url = auth_info[:extra][:id_info]["openid_id"] + user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url + user.update(:auth_provider => provider, :auth_uid => uid) if user + end + + if user case user.status when "pending" then unconfirmed_login(user) @@ -668,8 +678,7 @@ class UserController < ApplicationController user.preferred_editor = params[:user][:preferred_editor] end - if params[:user][:auth_provider].nil? || params[:user][:auth_provider].blank? || - params[:user][:auth_uid].nil? || params[:user][:auth_uid].blank? + if params[:user][:auth_provider].nil? || params[:user][:auth_provider].blank? user.auth_provider = nil user.auth_uid = nil end diff --git a/app/helpers/user_helper.rb b/app/helpers/user_helper.rb index dd4c343d8..6043edf5f 100644 --- a/app/helpers/user_helper.rb +++ b/app/helpers/user_helper.rb @@ -48,7 +48,7 @@ module UserHelper image_tag "openid_small.png", :alt => t("user.login.openid_logo_alt"), :class => "openid_logo" end - def auth_button(name, provider, options) + def auth_button(name, provider, options = {}) link_to( image_tag("#{name}.png", :alt => t("user.login.auth_providers.#{name}.alt")), auth_path(options.merge(:provider => provider)), diff --git a/app/views/user/account.html.erb b/app/views/user/account.html.erb index 93ee79cb6..47a84e99b 100644 --- a/app/views/user/account.html.erb +++ b/app/views/user/account.html.erb @@ -48,7 +48,7 @@
- <%= f.select :auth_provider, { "None" => "", "OpenID" => "openid" } %> + <%= f.select :auth_provider, Auth::PROVIDERS %> <%= f.text_field :auth_uid %> (<%= t 'user.account.openid.link text' %>)
diff --git a/app/views/user/login.html.erb b/app/views/user/login.html.erb index 8e2c3c336..99d7c0c34 100644 --- a/app/views/user/login.html.erb +++ b/app/views/user/login.html.erb @@ -42,7 +42,9 @@