Trust Google and Yahoo to return valid email addresses
authorKai Krueger <kakrueger@gmail.com>
Sat, 13 Oct 2012 06:26:04 +0000 (00:26 -0600)
committerTom Hughes <tom@compton.nu>
Tue, 30 Oct 2012 19:14:45 +0000 (19:14 +0000)
Both Google and Yahoo guarantee that the email address they return
during the OpenID authentication are emails that they have already
verified:

  http://stackoverflow.com/q/5639419

Therefore special case these OpenID providers and automatically
activate the new users account without requiring a separate email
verification step.

This therefore reduces the signup procedure by one step and makes
it easier for new users of these OpenID providers, which cover the
majority of users.

app/controllers/user_controller.rb
app/models/notifier.rb
app/views/notifier/signup_confirm.html.erb
app/views/notifier/signup_confirm.text.erb
config/locales/en.yml

index b61579d92b50bb44cd4963e3987567e8d1e90bfa..3fd1365543cad0585e18f3d51c157176ced340f8 100644 (file)
@@ -128,12 +128,26 @@ class UserController < ApplicationController
       @user.terms_seen = true
       @user.openid_url = nil if @user.openid_url and @user.openid_url.empty?
 
+      if (session[:openid_verified])
+        openid_verified = session.delete(:openid_verified)
+        if (openid_verified[:identity_url]) and (openid_verified[:identity_url] == @user.openid_url) and (openid_verified[:email]) and (openid_verified[:email] ==  @user.email)
+          # if we have an email from an OpenID provider that we trust to have verified the email for us, then activate the account directly
+          # without doing our own email verification.
+          @user.status = "active"
+        end
+      end
+
       if @user.save
         flash[:piwik_goal] = PIWIK_SIGNUP_GOAL if defined?(PIWIK_SIGNUP_GOAL)
         flash[:notice] = t 'user.new.flash create success message', :email => @user.email
-        Notifier.signup_confirm(@user, @user.tokens.create(:referer => session.delete(:referer))).deliver
-        session[:token] = @user.tokens.create.token
-        redirect_to :action => 'login', :referer => params[:referer]
+        if @user.status == "active"
+          Notifier.signup_confirm(@user, nil).deliver
+          successful_login(@user)
+        else
+          Notifier.signup_confirm(@user, @user.tokens.create(:referer => session.delete(:referer))).deliver
+          session[:token] = @user.tokens.create.token
+          redirect_to :action => 'login', :referer => params[:referer]
+        end
       else
         render :action => 'new', :referer => params[:referer]
       end
@@ -551,6 +565,9 @@ private
           # the simple registration protocol.
           nickname = sreg["nickname"] || ax["http://axschema.org/namePerson/friendly"].first
           email = sreg["email"] || ax["http://axschema.org/contact/email"].first
+
+          # Check if the openID is from a "trusted" OpenID provider and thus provides a verified email address
+          session[:openid_verified] = openid_email_verified(identity_url, email)
           redirect_to :controller => 'user', :action => 'new', :nickname => nickname, :email => email, :openid => identity_url
         end
       elsif result.missing?
@@ -605,6 +622,20 @@ private
     end
   end
 
+  def openid_email_verified(openid_url, email)
+    # OpenID providers Google and Yahoo are guaranteed to return (if at all) an email address that has been verified by
+    # them already. So we can trust the email addresses to be valid and own by the user without having to verify them our
+    # selves.
+    # Store the email in the session to compare agains the user set email address during account creation.
+    openid_verified = Hash.new
+    openid_verified[:identity_url] = openid_url
+    if openid_url.match(/https:\/\/www.google.com\/accounts\/o8\/id?(.*)/) or openid_url.match(/https:\/\/me.yahoo.com\/(.*)/)
+        openid_verified[:email] = email
+    end
+    return openid_verified
+    
+  end
+
   ##
   # process a successful login
   def successful_login(user)
index 343c3db2292fd9fd7625abe9b87889671e6d6f50..2a5bb15bc96e003693c3f5e27da794eecb425353 100644 (file)
@@ -6,11 +6,20 @@ class Notifier < ActionMailer::Base
 
   def signup_confirm(user, token)
     @locale = user.preferred_language_from(I18n.available_locales)
-    @url = url_for(:host => SERVER_URL,
-                   :controller => "user", :action => "confirm",
-                   :display_name => user.display_name,
-                   :confirm_string => token.token)
-
+    
+    # If we are passed an email address verification token, create
+    # the confirumation URL for account activation.
+    #
+    # Otherwise the email has already been verified e.g. through
+    # a trusted openID provider and the account is active and a
+    # confirmation URL is not needed.
+    if token
+      @url = url_for(:host => SERVER_URL,
+                     :controller => "user", :action => "confirm",
+                     :display_name => user.display_name,
+                     :confirm_string => token.token)
+    end
+      
     mail :to => user.email,
          :subject => I18n.t('notifier.signup_confirm.subject', :locale => @locale)
   end
index 5b7566fba9730d3482dcccb6ab5c9b087228512d..74aae6af14a86ce8f23914c0dd773d7ab6bcb61d 100644 (file)
@@ -1,11 +1,17 @@
 <p><%= t'notifier.signup_confirm_html.greeting' %></p>
 
+<% if @url %>
 <p><%= t'notifier.signup_confirm_html.hopefully_you' %>
    <%= SERVER_URL %>.</p>
 
 <p><%= t'notifier.signup_confirm_html.click_the_link' %></p>
 
 <p><%= raw(link_to @url, @url) %></p>
+<% else %>
+<p><%= t'notifier.signup_confirm_html.created_account' %>
+    <%= SERVER_URL %>.</p>
+<p><%= t'notifier.signup_confirm_html.welcome' %></p>
+<% end %>
 
 <p><%= raw(t'notifier.signup_confirm_html.introductory_video', :introductory_video_link => link_to(t('notifier.signup_confirm_html.video_to_openstreetmap'), "http://showmedo.com/videos/video?name=1800000&fromSeriesID=180")) %>
    <%= raw(t'notifier.signup_confirm_html.more_videos', :more_videos_link => link_to(t('notifier.signup_confirm_html.more_videos_here'), "http://showmedo.com/videos/series?name=mS2P1ZqS6")) %></p>
index a53f27dda99e8c0ba5dffaee7b3de640e7eb92fb..274d9f52fd199f1c96d120adb1a92a6ff93ff038 100644 (file)
@@ -1,12 +1,22 @@
 <%= t'notifier.signup_confirm_plain.greeting' %>
 
+<% if @url %>
 <%= t'notifier.signup_confirm_plain.hopefully_you' %>
+
 <%= SERVER_URL %>
 
 <%= t'notifier.signup_confirm_plain.click_the_link_1' %>
 <%= t'notifier.signup_confirm_plain.click_the_link_2' %>
 
 <%= @url %>
+<% else %>
+<%= t'notifier.signup_confirm_plain.created_account' %>
+
+<%= SERVER_URL %>
+
+<%= t'notifier.signup_confirm_plain.welcome_1' %>
+<%= t'notifier.signup_confirm_plain.welcome_2' %>
+<% end %>
 
 <%= t'notifier.signup_confirm_plain.introductory_video' %>
 
index bc43ab4bfbdff626782e1f5b222fb8c030c38510..07b9a9d4e619490a4505c337034aea276c671416 100644 (file)
@@ -1144,14 +1144,18 @@ en:
         subject: "[OpenStreetMap] GPX Import success"
         loaded_successfully: loaded successfully with %{trace_points} out of a possible %{possible_points} points.
     signup_confirm:
-      subject: "[OpenStreetMap] Confirm your email address"
+      subject: "[OpenStreetMap] Welcome to OpenStreetMap"
     signup_confirm_plain:
       greeting: "Hi there!"
       hopefully_you: "Someone (hopefully you) would like to create an account over at"
+      created_account: "You have just created a new account over at"
       # next two translations run-on : please word wrap appropriately
       click_the_link_1: "If this is you, welcome! Please click the link below to confirm your"
       click_the_link_2: "account and read on for more information about OpenStreetMap."
-      introductory_video: "You can watch an introductory video to OpenStreetMap here:"
+      # next two translations run-on : please word wrap appropriately
+      welcome_1: "We would like to welcome you and provide you with some additional information"
+      welcome_2: "to get you started."
+      introductory_video: "You can watch an introductory video to OpenStreetMap here:"      
       more_videos: "There are more videos here:"
       the_wiki: "Get reading about OpenStreetMap on the wiki:"
       the_wiki_url: "http://wiki.openstreetmap.org/wiki/Beginners%27_Guide"
@@ -1168,7 +1172,9 @@ en:
     signup_confirm_html:
       greeting: "Hi there!"
       hopefully_you: "Someone (hopefully you) would like to create an account over at"
+      created_account: "You have just created a new account over at"
       click_the_link: "If this is you, welcome! Please click the link below to confirm that account and read on for more information about OpenStreetMap"
+      welcome: "We would like to welcome you and provide you with some additional information to get you started."
       introductory_video: "You can watch an %{introductory_video_link}."
       video_to_openstreetmap: "introductory video to OpenStreetMap"
       more_videos: "There are %{more_videos_link}."