Unable to login with Google plus using omniauth-google-oauth2 - ruby

I am using gem "omniauth-google-oauth2" in my application built on spree(ruby-on-rails) to integrate Google plus login on to our site.I am getting a very strange error here,It's working fine in development(localhost),
but in production I am getting this error
"auth/google_oauth2/callback?state=35ad3c2e3f8327a5b96df7ce7e2439a77b90dfebc41f8463&code=4/p5l-nug7FU3P8lfnSHNF8Uy_tYXcLyqc0bnABoGo0EI#".
For integrating Google plus ,I have done following
a.) I created a WebApplication App in google developers console by adding necessary javascript origin and redirect url's
b.) I have added client id, secret in my coonfig file
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, 'my cient id', 'secret'
end
c.) I have added a route 'auth/google_oauth2/callback'
I am really struck here for quiet some time.

I have done google-omniauth-oauth2 for quite a few apps.
Based on my experience I am giving you some hints.
Some of the possible reasons could be
You have added ur production url to google console, but may have missed out on callback url for production.
Check for routes and see if you have added a callback route. Normally it should point to method 'sessions#create' in your SessionsController.
Try the following in omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET
{
:access_type => 'offline',
:prompt => 'consent'
}
Here is my sessions#create method for your reference
def create
auth = request.env['omniauth.auth']
#user = User.find_by_email(auth.info.email) || User.create_with_omniauth(auth)
if !#user.country
#user.country = request.location.country
end
#user.update_tokens auth
reset_session
session[:user_id] = #user.id
redirect_to new_video_path, :notice => 'Signed In!'
end
For more help check this link.

Related

OAuth request to Google succeeds locally, but fails with "invalid_grant" on Heroku

I'm using a Google service account to make API calls for my Dashing dashboard to Analytics. I'm using the Legato gem to get Analytics data, and authenticating using the gem's wiki's instructions for service accounts.
I've put my Google username and private key into ENV (after base 64-encoding it), and am using dotenv to synchronize these settings between local and Heroku (heroku config confirms that everything is set correctly). So, my authentication code looks like this:
class GoogleAnalyticsAccount
attr_accessor :user, :profile
# Thanks to the "Service Accounts" section at
# https://github.com/tpitale/legato/wiki/OAuth2-and-Google
def initialize scope="https://www.googleapis.com/auth/analytics.readonly"
client = Google::APIClient.new application_name: '[App name]',
application_version: '1.0'
key = Google::APIClient::PKCS12.load_key(Base64.decode64(ENV['GOOGLE_PRIVATE_KEY_BASE64']), "notasecret")
service_account = Google::APIClient::JWTAsserter.new(ENV['GOOGLE_USER'], scope, key)
client.authorization = service_account.authorize
oauth_client = OAuth2::Client.new("", "", {
:authorize_url => 'https://accounts.google.com/o/oauth2/auth',
:token_url => 'https://accounts.google.com/o/oauth2/token'
})
token = OAuth2::AccessToken.new(oauth_client, client.authorization.access_token)
#user = Legato::User.new(token)
end
def profile
#user.profiles.first
end
end
Locally, this code works just fine. On Heroku, I get the following response from Google:
{
"error": "invalid_grant"
}
No more detail than that. Based on extensive Googling, I've found that the two most likely reasons for this are A) I've hit my request limit (but it can't be that, because the same credentials work locally), and B) the server clock isn't synced with NTP. I've set the timezone on Heroku to America/Chicago (same as my local machine), but no dice.
Any ideas? Thanks!
Huh. I was using dotenv and heroku-config to push my settings up to Heroku. Turns out, putting my GOOGLE_USER and GOOGLE_PRIVATE_KEY_BASE64 inside quote marks in my .env file was taken literally by heroku-config, and it was pushing those settings with quote marks to my Heroku config. Thus, the username/key were invalid—hence invalid_grant.
And to think I've been working on this problem for days...

Testing expectations on doubles in Sinatra app using spec

I want to verify that a method was called on a service I want to inject into a Sinatra application using rspec but I can't find an example of how this is done. Here is my spec...
RSpec.configure do |config|
config.include Rack::Test::Methods
end
def app
App
end
describe 'Login' do
context 'when the user is logged out' do
describe 'POST on /signup' do
it 'invokes signup on the user service with the correct parameters' do
service = double('user_service').as_null_object
service.should_receive(:signup).with(:username => 'RobA2345')
post '/signup'
end
end
end
end
Here the App is a modular Sinatra app. I come from a .NET background and I'd use constructor injection here to solve this problem but I know this isn't the ruby way to do it.
Help, as always, is appreciated.
Assuming that you're expecting to receive the message on a new instance of UserService, there are a couple of ways to do this. If you are using a recent version of rspec, this should work:
it 'invokes signup on the user service with the correct parameters' do
UserService.any_instance.should_receive(:signup).with(:username => 'RobA2345')
post '/signup'
end
Alternatively, this should work in just about any version of rspec:
it 'invokes signup on the user service with the correct parameters' do
service = double('user_service').as_null_object
UserService.stub(:new).and_return(service)
service.should_receive(:signup).with(:username => 'RobA2345')
post '/signup'
end

How do I use Devise to secure the delayed_job_web interface?

I'm using the delayed_job_web gem to monitor delayed jobs. https://github.com/ejschmitt/delayed_job_web
It is accessible using this line in my routes.rb:
match "/delayed_job" => DelayedJobWeb, :anchor => false
Every other area of my site requires a login using the Devise gem. How do I make this require a login too?
In the readme, they suggest adding the following to the config.rb:
if Rails.env.production?
DelayedJobWeb.use Rack::Auth::Basic do |username, password|
username == 'username'
password == 'password'
end
end
But that just uses plain text browser authentication.
UPDATE:
I tried something similar to the railscast on resque, and I think it's on the verge of working but giving me a redirect loop now:
authenticate :admin do
mount DelayedJobWeb, :at => "/delayed_job"
end
Any thoughts on why would it be giving a redirect loop?
Thanks,
Use authenticated instead of authenticate as described here: http://excid3.com/blog/rails-tip-5-authenticated-root-and-dashboard-routes-with-devise/
Works for me!
You could do something like this define this inside config/routes.rb file
authenticate_user = lambda do |request|
request.env['warden'].authenticate?
end
constraints authenticate_user do
mount DelayedJobWeb, :at => "/delayed_job"
end
Alternately if you have cancan for any other role management library you could do it something like this
I have used both of this in my applications to control access to resque-web depending on the needs of the application
Hope this help
Now it's 2017 I tried the other solutions and they didn't work, but the following admin check does work:
authenticated :user, -> user { user.admin? } do
mount DelayedJobWeb, at: "/delayed_job"
end

Using Cucumber to test controller without a view in Rails

I'm a ruby/rails newbie and the application I'm developing starts with a HTTP post from another website which passes in some data and then displays some data capture screens before calling a web service.
I want to start this project using an outside in approach using Cucumber for integration tests and rspec for functional/unit testing.
Using Cucumber how do I simulate the post from the external website so that I can test the flows with the application.
It doesn't really matter to the application where the call originated; only that the parameters supplied match the expected ones from the referring page. If you depend on a specific HTTP_REFERER being set, check out this answer on how to set a header in Cucumber.
add_headers({'HTTP_REFERER' => 'http://referringsite.com'})
Since you already know which query parameters/headers your app expects from the referring site you can create a setup block that will set these appropriately for each cuke.
If you are using Cucumber with Capybara you can do a HTTP POST like this.
When /^I sign in$/ do
#user = Factory(:user)
get "/login"
page.driver.post sessions_path, :username => #user.username, :password => #user.password
end
Alternatively if you have a view it would be something like this.
When /^I sign in$/ do
#user = Factory(:user)
visit "/login"
fill_in "Username", :with => #user.username
fill_in "Password", :with => #user.password
click_button "Log in"
end

401 error with Ruby OAuth for Twitter

xI've been working for days to get Twitter to authenticate with Ruby, but I'm not having any luck.
My first attempt was something like this:
class TwitterController < ApplicationController
def index
#callback_url = "http://dev.twipler.com:3000/twitter/auth"
#auth= TwitterOAuth::Client.new( :consumer_key => "xxx", :consumer_secret => "xxxxxxxxxxxxxxxxx" )
#rtoken = #auth.request_token :oauth_callback => #callback_url
#token = #rtoken.token
#secret = #rtoken.secret
#link = #rtoken.authorize_url
session['token' ] = #token
session['secret'] = #secret
redirect_to #link
end
def auth
#auth.authorize_from_request(session[:rtoken], session[:rsecret], params[:oauth_verifier])
end
end
And a very similar way but with the Twitter gem, and the same with the OAuth gem directly. No matter what OAuth::Consumer::token_request dies with a 401 error.
So, out of desperation I attempted to git clone Snitter, add my Twitter creds, and try it, but it too dies with a 401.
I've tried using localhost:300/twitter/auth, http://dev.twipler.com:3000/twitter/auth, and a bit.ly for each of the former 2. Nothing works.
Any help?
EDIT: Of course I would forget to do the most logical thing to do and delete my secrets. (They've been changed ;)).
You may want to edit your consumer secret out. With that, anyone can make requests on behalf of your app.
That said, make sure your system time is synced to an ntp server. If your system time has drifted fast or slow, OAuth requests will fail, since their include a timestamp and relatively short TTL. I had this exact problem a while back.
Failing that, you can crack open the oauth gem and turn on HTTP debugging, which will show you the full HTTP transaction including any error message returned.

Resources