Rails Google Oauth - Works for some users and not others - ruby-on-rails

I am building rails and google oauth for a project. Right now, it is a very straight forward set up
# gemfile
gem 'rails', '~> 5.2.3'
gem 'administrate'
gem 'devise', github: 'heartcombo/devise', branch: 'ca-omniauth-2'
gem 'omniauth-google-oauth2'
gem 'dotenv-rails', groups: [:development, :test]
gem 'google-api-client', require: 'google/apis/calendar_v3'
gem 'omniauth-rails_csrf_protection'
# devise.rb
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], {
access_type: "offline",
prompt: "consent",
select_account: true,
scope: 'userinfo.email, calendar, openid',
provider_ignores_state: true
}
and then I have my code working for auth'ing with Google and logging users into devise.
I am using google calendar for a scope, which is now as of 2021 considered a sensitive scope, and because of that I have to add test users to the google project to get it to work. Currently in my google set up, I have 2 users white-listed as allowed users to use the app.
Right now, 1 user is able to log into the app just fine. They go to the page, auth with google, accept permissions, and google logs them in.
For 1 other user, google does not work. They go to the page, attempt to auth with google, and get a page back that says
SOMETHING WENT WRONG
sorry, something went wrong there. Try again.
and then are redirected to the google error page that says
400. That's an error
The server cannot process the request because it is malformed. It should not be retried.
That's all we know.
I'm not able to figure this out, because it is working perfectly for 1 user and not for the other. The only thing I can think of is looking in the heroku logs. I was able to find requests for both users.
Here are the logs for a successful login
2021-01-26T19:15:49.316985+00:00 app[web.1]: I, [2021-01-26T19:15:49.316862 #4] INFO -- : [c8194f6f-6cc9-4d1c-8ea2-9439d4a3f758] Started POST "/admin_users/auth/google_oauth2" for 108.80.197.86 at 2021-01-26 19:15:49 +0000
2021-01-26T19:15:49.317524+00:00 app[web.1]: D, [2021-01-26T19:15:49.317454 #4] DEBUG -- omniauth: (google_oauth2) Request phase initiated.
2021-01-26T19:15:49.331305+00:00 heroku[router]: at=info method=POST path="/admin_users/auth/google_oauth2" host=<host> request_id=c8194f6f-6cc9-4d1c-8ea2-9439d4a3f758 fwd="108.80.197.86" dyno=web.1 connect=1ms service=16ms status=302 bytes=1662 protocol=https
2021-01-26T19:15:59.988809+00:00 app[web.1]: I, [2021-01-26T19:15:59.988635 #4] INFO -- : [cb1c461a-de2d-47cf-97d7-c5c594dcedc2] Started GET "/admin_users/auth/google_oauth2/callback?state=<state>&code=<code>&scope=email%20https://www.googleapis.com/auth/calendar%20https://www.googleapis.com/auth/userinfo.email%20openid&authuser=0&prompt=consent" for 108.80.197.86 at 2021-01-26 19:15:59 +0000
2021-01-26T19:15:59.989574+00:00 app[web.1]: D, [2021-01-26T19:15:59.989451 #4] DEBUG -- omniauth: (google_oauth2) Callback phase initiated.
2021-01-26T19:16:00.159852+00:00 app[web.1]: I, [2021-01-26T19:16:00.159697 #4] INFO -- : [cb1c461a-de2d-47cf-97d7-c5c594dcedc2] Processing by AdminUsers::OmniauthCallbacksController#google_oauth2 as HTML
2021-01-26T19:16:00.159977+00:00 app[web.1]: I, [2021-01-26T19:16:00.159863 #4] INFO -- : [cb1c461a-de2d-47cf-97d7-c5c594dcedc2] Parameters: {"state"=>"<state>", "code"=>"<code>", "scope"=>"email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email openid", "authuser"=>"0", "prompt"=>"consent"}
Here are the logs for an unsuccessful login
2021-01-26T14:16:32.326486+00:00 app[web.1]: I, [2021-01-26T14:16:32.326382 #4] INFO -- : [545e059b-7f9b-4687-8b0e-b9f7479625e2] Started POST "/admin_users/auth/google_oauth2" for 107.203.102.116 at 2021-01-26 14:16:32 +0000
2021-01-26T14:16:32.326882+00:00 app[web.1]: D, [2021-01-26T14:16:32.326810 #4] DEBUG -- omniauth: (google_oauth2) Request phase initiated.
2021-01-26T14:16:32.331603+00:00 heroku[router]: at=info method=POST path="/admin_users/auth/google_oauth2" host=<host> request_id=545e059b-7f9b-4687-8b0e-b9f7479625e2 fwd="107.203.102.116" dyno=web.1 connect=0ms service=9ms status=302 bytes=1674 protocol=https
So in looking at the logs, the unsuccessful request just stops after the user hits the google button and google seems like it's not calling back the request.
Why would it be working for 1 user, and not working for another?
Any help is much appreciated

This was resolved. the problem was the other user was using a google provided email that was not a gmail i.e. a email#domain.com email address. even though it is controlled by google, it seems like you need a gmail to auth. we switched to a gmail email and it worked fine.

Related

ClassLink Devise OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected

I've looked through various similar issues and responses but to no avail. Sorry if this is obvious but OAuth is not my area of expertise.
I'm running Rails 5.2 with Ruby 2.74 and Devise. I have SSO set up with Facebook and it works fine. I'm trying to get it working with ClassLink, but I'm stuck. When clicking on our ClassLink dashboard icon (ClassLink website), it opens a new browser window to our site, as it should, but fails to log in as that user. A user with the same email is set up on both ends. The server error is
15:14:51 web.1 | D, [2022-09-01T15:14:51.715485 #1139413] DEBUG -- omniauth: (classlink) Callback phase initiated.
15:14:51 web.1 | E, [2022-09-01T15:14:51.720435 #1139413] ERROR -- omniauth: (classlink) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
The Omniauth-Classlink Gem calls for a devise.rb entry of
config.omniauth :class_link,
'your-classlink-access-key',
'your-classlink-secret',
strategy_class: 'OmniAuth::Strategies::ClassLink'
but with that last parameter (strategy_class), the server won't start and exits with an error:
NoMethodError: undefined method `new' for "OmniAuth::Strategies::ClassLink":String
so I'm leaving that off since it wasn't required for my working Facebook SSO.
On the failed login I'm getting the following log entry:
Processing by Users::OmniauthCallbacksController#failure as HTML
Parameters: {"code"=>"c166206446884317a72fa1c03772a2b622c9135c526e7a", "response_type"=>"code"}
Redirected to https://dtest.pagekite.me/?locale=en
Filter chain halted as :authorize rendered or redirected
Completed 302 Found in 8ms (ActiveRecord: 0.0ms)
The domain registered on ClassLink matches our server and the callback url is correct. The permissions, routes, callback function, etc. all look OK to me (again, pretty much identical to Facebook). Any suggestions on where I might look next?
Thanks.
It sounds like you have a few different problems going on here.
15:14:51 web.1 | D, [2022-09-01T15:14:51.715485 #1139413] DEBUG -- omniauth: (classlink) Callback phase initiated. 15:14:51 web.1 | E, [2022-09-01T15:14:51.720435 #1139413] ERROR -- omniauth: (classlink) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
In the request phase, you receive a state parameter with a random value. The omniauth-oauth2 strategy (from which the omniauth-classlink strategy is subclassed) stores this value in the session. In the callback phase, you again receive a state parameter and it must match the one received in the request phase. This error almost always means there is something wrong with your session
NoMethodError: undefined method `new' for "OmniAuth::Strategies::ClassLink":String
The value of the strategy_class option should be the class name constant. Removing the quotes should fix it.
Processing by Users::OmniauthCallbacksController#failure as HTML Parameters: {"code"=>"c166206446884317a72fa1c03772a2b622c9135c526e7a", "response_type"=>"code"} Redirected to https://dtest.pagekite.me/?locale=en Filter chain halted as :authorize rendered or redirected Completed 302 Found in 8ms (ActiveRecord: 0.0ms)
This is Devise trying to authorize the callback request when it should not be. Is your Users::OmniauthCallbacksController calling authenticate_user! in a before action or inheriting that behavior from a parent class?

When a user logs into my Ruby app on Heroku, it seems to get stuck in a loop. This does not happen for guest users. Can anyone advise?

So, long story short - I'm comfortable with HTML, CSS, SQL a bit of Javascript etc as a hobby, but am far from a 'proper' developer. Recently a friend paid a developer to build a web app for them (the friend have no IT skills at all). The developer (who is no longer on the scene) left them with a working demo in Heroku and a GitHub repo which I have now cloned. My friend wanted some of the cosmetic bits changing, which I offered to help with, but in order to do this, I had to create my own version of the app on Heroku from my forked repo.
I couldn't get this to work, kept getting an error message when trying to deploy the app, despite the code being completely unchanged from the parent. I should mention now that the app has been written in Ruby, with which I have zero experience. But I thought I'd have a go anyway...
After much Googling, I managed to get the app to successfully deploy by changing the version of #rails/webpacker in the package.json file. I then changed any references to originalApp.herokuapps.com to myNewVersion.herokuapps.com.
After this, I had to set some Config Vars in Heroku (relating to gmail and stripe) to get things up and running. This all seemed to work ok...
So I'm now at the point where a user can sign up on the app and subscribe to the service using Stripe (test) and is successfully sent a confirmation email.
However, once a user is logged in, anytime they try to go to any other page, for example the 'About Us' or 'Contact Us' page, it immediately redirects (or stays) on the same page. There's no other pages the logged-in user can access. However, if I log out, then the 'guest' user can navigate to the other pages freely.
Example:
If I'm logged in, the URL shows https://myproject.herokuapp.com/start and the contents of the page are what the user was presented with after signing up and paying the Stripe fee.
If they then click on, for example, the 'About Us' link, the log shows this (I've edited the URLs to show myproject instead of the real project name):
2022-01-05T22:16:29.805824+00:00 app[web.1]: I, [2022-01-05T22:16:29.805699 #4] INFO -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] Started GET "/about-us" for 90.197.167.151 at 2022-01-05 22:16:29 +0000
2022-01-05T22:16:29.806538+00:00 app[web.1]: I, [2022-01-05T22:16:29.806485 #4] INFO -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] Processing by PagesController#about_us as HTML
2022-01-05T22:16:29.809496+00:00 app[web.1]: D, [2022-01-05T22:16:29.809430 #4] DEBUG -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] [1m[36mUser Load (0.7ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2[0m [["id", 1], ["LIMIT", 1]]
2022-01-05T22:16:29.810151+00:00 app[web.1]: I, [2022-01-05T22:16:29.810102 #4] INFO -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] Redirected to https://myproject.herokuapp.com/start
2022-01-05T22:16:29.810227+00:00 app[web.1]: I, [2022-01-05T22:16:29.810201 #4] INFO -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] Filter chain halted as :check_subscription rendered or redirected
2022-01-05T22:16:29.810322+00:00 app[web.1]: I, [2022-01-05T22:16:29.810300 #4] INFO -- : [0efc978f-35cf-4d11-ae66-edbdb5b26ec4] Completed 302 Found in 4ms (ActiveRecord: 0.7ms | Allocations: 964)
2022-01-05T22:16:29.835064+00:00 app[web.1]: I, [2022-01-05T22:16:29.834991 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Started GET "/start" for 90.197.167.151 at 2022-01-05 22:16:29 +0000
2022-01-05T22:16:29.835712+00:00 app[web.1]: I, [2022-01-05T22:16:29.835663 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Processing by CheckoutsController#start as HTML
2022-01-05T22:16:29.836943+00:00 app[web.1]: I, [2022-01-05T22:16:29.836887 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Rendering checkouts/start.html.erb within layouts/application
2022-01-05T22:16:29.839055+00:00 app[web.1]: D, [2022-01-05T22:16:29.838940 #4] DEBUG -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] [1m[36mUser Load (0.7ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2[0m [["id", 1], ["LIMIT", 1]]
2022-01-05T22:16:29.839685+00:00 app[web.1]: I, [2022-01-05T22:16:29.839609 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Rendered checkouts/start.html.erb within layouts/application (Duration: 2.6ms | Allocations: 401)
2022-01-05T22:16:29.841324+00:00 app[web.1]: I, [2022-01-05T22:16:29.841270 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Rendered shared/_navbar.html.erb (Duration: 0.9ms | Allocations: 905)
2022-01-05T22:16:29.841552+00:00 app[web.1]: I, [2022-01-05T22:16:29.841516 #4] INFO -- : [a7c07664-645b-449c-a9a8-a50a2c060f3b] Completed 200 OK in 6ms (Views: 4.1ms | ActiveRecord: 0.7ms | Allocations: 2433)
2022-01-05T22:16:29.816017+00:00 heroku[router]: at=info method=GET path="/about-us" host=myproject.herokuapp.com request_id=0efc978f-35cf-4d11-ae66-edbdb5b26ec4 fwd="90.197.167.151" dyno=web.1 connect=0ms service=6ms status=302 bytes=1393 protocol=https
As said, I'm not familiar with Ruby at all, but I suspect it's something to do with the lines that mention:
Redirected to https://myproject.herokuapp.com/start
Filter chain halted as :check_subscription rendered or redirected
You can see it's trying to go to the /about-us page but it remains on /start.
I believe the app uses something called 'Devise' for the user registration process.
Given the code is the same as the parent repo that I forked from, I'm guessing the issue is either a setting within Heroku or some kind of variable that I'm missing or have not updated. If anyone can advise me on next steps with regards to research or a solution, I'd be very grateful. I appreciate I'm no expert, but I'm just trying to do a friend a favour after they've been left hanging by another dev. Many Thanks.
Update:
application_controller.rb
before_action :authenticate_user!, :halt_if_mobile
before_action :check_subscription, except: %i[ home start ]
def halt_if_mobile
if browser.device.mobile?
render inline: "Mobile access is currently disabled"
return
end
end
def check_subscription
return unless current_user
return if controller_path =~ /devise/ || controller_path =~ /registrations/
if !current_user.active
redirect_to start_path, notice: 'Please update your payment settings'
return
end
end
end

iOS HTTPS request to Rails Heroku debugging 401 error

I am attempting to adapt this wenderlich tutorial to Swift 3 syntax to create an iOS frontned with rails backend hosted on Heroku.
Let me know if there is any other code that would be good to share, but it seems like an auth issue. Here's where the authorization header is set for the request:
let basicAuthString = "\(HTTPHelper.API_AUTH_NAME):\(HTTPHelper.API_AUTH_PASSWORD)"
let utf8str = basicAuthString.data(using: String.Encoding.utf8)
let base64EncodedString = utf8str?.base64EncodedString(options: Data.Base64EncodingOptions())
request.addValue("Basic \(base64EncodedString)", forHTTPHeaderField: "Authorization")
I am having trouble telling how to debug these requests to begin with. If I step through the code in the debugger, the request object seems pretty flat, and if I print the request I just see the URL.
The request to the heroku server (also built from that tutorial) returns a 401, and it doesn't seem to be entering any of the rails methods. It just returns a 401 unauthorized:
2017-03-24T20:13:47.022176+00:00 heroku[router]: at=info method=POST path="/api/signin" host=young-retreat-61850.herokuapp.com request_id=9d58e8f4-ee9f-4c73-babd-2a2ee5c82a4f fwd="73.83.200.10" dyno=web.1 connect=1ms service=13ms status=401 bytes=499 protocol=https
2017-03-24T20:13:47.014605+00:00 app[web.1]: Started POST "/api/signin" for 73.83.200.10 at 2017-03-24 20:13:47 +0000
2017-03-24T20:13:47.020239+00:00 app[web.1]: Processing by ApiController#signin as */*
2017-03-24T20:13:47.020279+00:00 app[web.1]: Parameters: {"email"=>"dsadsadsa", "password"=>"[FILTERED]", "api"=>{"email"=>"dsadsadsa", "password"=>"[FILTERED]"}}
2017-03-24T20:13:47.020671+00:00 app[web.1]: Filter chain halted as #<Proc:0x007f6ae4d6f140#/app/vendor/bundle/ruby/2.1.0/gems/actionpack-4.1.5/lib/action_controller/metal/http_authentication.rb:71> rendered or redirected
2017-03-24T20:13:47.020791+00:00 app[web.1]: Completed 401 Unauthorized in 0ms (ActiveRecord: 0.0ms)
2017-03-24T20:13:47.142925+00:00 app[web.1]: Started POST "/api/signin" for 73.83.200.10 at 2017-03-24 20:13:47 +0000
2017-03-24T20:13:47.148098+00:00 app[web.1]: Processing by ApiController#signin as */*
2017-03-24T20:13:47.148134+00:00 app[web.1]: Parameters: {"email"=>"dsadsadsa", "password"=>"[FILTERED]", "api"=>{"email"=>"dsadsadsa", "password"=>"[FILTERED]"}}
2017-03-24T20:13:47.156450+00:00 app[web.1]: Filter chain halted as #<Proc:0x007f6ae4d6f140#/app/vendor/bundle/ruby/2.1.0/gems/actionpack-4.1.5/lib/action_controller/metal/http_authentication.rb:71> rendered or redirected
2017-03-24T20:13:47.156647+00:00 app[web.1]: Completed 401 Unauthorized in 8ms (ActiveRecord: 0.0ms)
2017-03-24T20:13:47.157852+00:00 heroku[router]: at=info method=POST path="/api/signin" host=young-retreat-61850.herokuapp.com request_id=bc270aa1-aeed-40b8-b9a0-3c09a68dec8d fwd="73.83.200.10" dyno=web.1 connect=2ms service=24ms status=401 bytes=458 protocol=https
Should it seem strange that the nested "api" key has the same params? I am unclear on which direction to take for debugging these requests. I can't use a service like Charles because they are https right?
Feel like a fool...
the base64EncodedString was an optional.
fix:
request.addValue("Basic \(base64EncodedString!)", forHTTPHeaderField: "Authorization")
I was able to get more details about the request with this URLRequest method:
print("request header:\(request.allHTTPHeaderFields)")

Facebook app public but only accessible to developers

My FB app is public (green dot) and is working perfectly fine for admins and developers. However, authentication fails when a non user tries to login.
FB app screenshot: http://imgur.com/r25vyjH
Interestingly, non-developer users are able to reach the permissions screen, but are not able to login using FB. I am using only the approved permissions:
scope: 'email, public_profile, user_friends, user_birthday'
I am on rails + devise + omniauth + omniauth-facebook.
In code, it redirects to OmniauthCallbacksController#failure. I tried creating failure action to see what's happening, but it is not giving me any message. Not sure how to debug this.
I am using following:
gem 'devise', '3.4.1'
gem 'omniauth', '1.2.2'
gem 'omniauth-facebook', '2.0.0'
Here is what I see in production.log:
I, [2015-05-01T17:55:39.141944 #2341] INFO -- : Started GET "/users/auth/facebook" for 122.167.223.121 at 2015-05-01 17:55:39 +0000
I, [2015-05-01T17:55:39.706464 #2341] INFO -- : Started GET "/users/auth/facebook/callback?code=AQC5ypphUjqzOquyD4HMWFvaCZjvMfahg5Y_...fljWMCh&state=0857ab97a79206c582b2b7b5391d99cda7b5d4e5ba2f730e" for 122.167.223.121 at 2015-05-01 17:55:39 +0000
I, [2015-05-01T17:55:41.231336 #2341] INFO -- : Processing by OmniauthCallbacksController#failure as HTML
I, [2015-05-01T17:55:41.231394 #2341] INFO -- : Parameters: {"code"=>"AQC5ypphUjqzOquyD4HMWFvaCZjvMfahg5Y...MCh", "state"=>"0857ab97a79206c582b2b7b5391d99cda7b5d4e5ba2f730e"}
I, [2015-05-01T17:55:41.232699 #2341] INFO -- : Redirected to http://www.oyelife.com/
I, [2015-05-01T17:55:41.232832 #2341] INFO -- : Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Help appreciated.
Figured this out myself after more tinkering.
Seems like callback URL must also be listed in Settings > Advanced > OAuth Settings > Valid OAuth redirect URIs. It works without it for developers, but is required for public.
Would be better if Facebook mentions this somewhere.

Could not authenticate you from Foursquare because "Csrf detected"

I'm using Devise + Omniauth (actually omniauth-foursquare, the foursquare OAuth2 strategy) in my Rails app.
Upon signing in, I keep being redirected to my app (/users/sign_in#=) with the following error:
Could not authenticate you from Foursquare because "Csrf detected"
Any insights?
This is what I see last in the console:
I, [2014-10-19T19:43:38.947771 #2] INFO -- omniauth: (foursquare) Request phase initiated.
Started GET "/users/auth/foursquare" for 142.255.113... at 2014-10-19 19:43:38 +0000
Parameters: {"code"=>"2MZGM413...", "state"=>"1ba1cec3beb4..."}
Processing by Devise::SessionsController#new as HTML
Started GET "/users/auth/foursquare/callback?code=2MZGM413...&state=1ba1cec3beb4..." for 142.255.113... at 2014-10
I, [2014-10-19T19:43:39.378477 #2] INFO -- omniauth: (foursquare) Callback phase initiated.
E, [2014-10-19T19:43:39.378660 #2] ERROR -- omniauth: (foursquare) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
As far as I can tell, my troubles started when I received a "cookie overflow" erorr and switched to session_storing: (session_store.rb)
Rails.application.config.session_store :active_record_store, key: '_APPNAME_session', domain: 'DOMAIN.com'
Thanks!
If you inspect the source for your app, you'll see that the generated HTML includes the CSRF meta tags in the HEAD element (i.e. csrf-token and csrf-param). Most likely, one of your layouts/views is calling the csrf_meta_tags method. Try removing it to see if it works, and then consider creating a separate layout without it for forms that won't need it. Other people with more experience on frontend rails could chime in here with best practices.

Resources