Switching between the web and touch interfaces when logging into Facebook using Omniauth and Rails 3

Situation:

Using Rails 3 and OmniAuth, I have an application that authenticates using the Facebook strategy. This application was created to work the same for web and mobile interfaces (ala Jquery-Mobile).

The challenge is to get OmniAuth to provide a mobile version of the Facebook login screen on mobile devices and a web version on desktop devices.

I hacked into a solution that I will put as an answer.

+7
source share
5 answers

In fact, since OmniAuth :: Strategies is already Rack middleware, it is even simpler. Just override the request_phase method and check the @env instance variable present in the strategy for mobile user_agent:

module OmniAuth module Strategies class Facebook < OAuth2 MOBILE_USER_AGENTS = 'webos|ipod|iphone|mobile' def request_phase options[:scope] ||= "email,offline_access" options[:display] = mobile_request? ? 'touch' : 'page' super end def mobile_request? ua = Rack::Request.new(@env).user_agent.to_s ua.downcase =~ Regexp.new(MOBILE_USER_AGENTS) end end end end 
+5
source

For modern / omniauth design (> = 1.0) use this in config / initializers / devise.rb:

 FACEBOOK_SETUP_PROC = lambda do |env| request = Rack::Request.new(env) mobile_device = request.user_agent =~ /Mobile|webOS/i request.env['omniauth.strategy'].options[:display] = mobile_device ? "touch" : "page" end config.omniauth :facebook, FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, :scope => 'email,offline_access', :setup => FACEBOOK_SETUP_PROC, :client_options => { :ssl => { :ca_file => Rails.root.join("config/ca-bundle.crt").to_s }} 
+3
source

I tried the first solution, but I could not get it to work. After a long search, I found out that Omniauth has an option:: setup => true, which allows you to dynamically configure arguments, such as the display option for Facebook OAuth.

First enable the: setup option.

 config.omniauth :facebook, APP_CONFIG["fb_app_id"], APP_CONFIG["fb_app_secret"], {:scope => 'email, offline_access', :setup => true} 

Then add the second route (installation route):

  devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru' get '/users/auth/:provider/setup' => 'users/omniauth_callbacks#setup' end 

Add this controller. You may already have this if you followed the development guide.

 class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def setup request.env['omniauth.strategy'].options[:display] = mobile_device? ? "touch" : "page" render :text => "Setup complete.", :status => 404 end end 

Add this method to your ApplicationController:

 def mobile_device? if session[:mobile_param] session[:mobile_param] == "1" else request.user_agent =~ /Mobile|webOS/ end end 

Done!

+1
source

The approved answer works, except that I had to change one line. For the current version of omniauth-facebook, I had to set the display option, for example:

 options[:authorize_params] = mobile_request? ? { :display => 'touch' } : { :display => 'page' } 

You can use "popup", "touch" or "page" from what I found.

+1
source

My solution is quite active and requires changing the OmniAuth Facebook strategy and adding Rack middleware.

First, I added a class attribute and changed the method in OmniAuth :: Strategies :: Facebook (I put this at the end of my omniauth.rb configuration file, but it belongs in the lib directory):

 module OmniAuth module Strategies class Facebook < OAuth2 cattr_accessor :display # new def request_phase options[:scope] ||= "email,offline_access" options[:display] = OmniAuth::Strategies::Facebook.display || nil # new super end end end end 

Secondly, I added a portion of the Rack middleware to determine if the request was sent from a mobile device, and then adjust the display accordingly:

 module Rack class FacebookMobileOmniauth def initialize(app) @app = app end MOBILE_USER_AGENTS = 'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' + 'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' + 'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' + 'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' + 'webos|amoi|novarra|cdm|alcatel|pocket|ipad|iphone|mobileexplorer|' + 'mobile' def call(env) request = Request.new(env) if request.user_agent.to_s.downcase =~ Regexp.new(MOBILE_USER_AGENTS) OmniAuth::Strategies::Facebook.display = 'touch' else OmniAuth::Strategies::Facebook.display = nil end return @app.call(env) end end end 

And finally, I added the Rack middleware to my config.ru:

  require ::File.expand_path('../config/environment', __FILE__) use Rack::FacebookMobileOmniauth # new run Mystupid::Application 
0
source

All Articles