rails oAuth failing, session invalid - ruby-on-rails-4

Rails application - I am trying to authenticate with google using oAuth using the gem omniauth. I have tried to follow the steps in the link sitepoint but after signing in successfully with Google in the backend, application says that authentication has failed in the sessions_controller.rb.
I have narrowed down the error to this line in the sessions_controller.rb
session[:user_id] = #user.id
Now if I try to dump session, I get the following error
Completed 500 Internal Server Error in 107ms (ActiveRecord: 3.1ms)
TypeError (can't dump anonymous module: #<Module:0xa5a8b38>):
app/controllers/sessions_controller.rb:7:in `create'
Why is the session invalid? How to rectify this?
Here is the sessions_controller.rb 'create' action code
begin
#user = User.from_omniauth(request.env['omniauth.auth'])
session[:user_id] = #user.id
flash[:success] = "Welcome, #{#user.name}!"
rescue
logger.debug "Well, authentication failed?"
flash[:warning] = "There was an error while trying to authenticate you"
end

Related

I am Trying to to do Oauth with twitter in python using flask and getting request page is invalid

I am getting the following error
Whoa there!
The request token for this page is invalid. It may have already been used, or expired because it is too old. Please go back to the site or application that sent you here and try again; it was probably just a mistake
1) The following method in which we are calling the twitter credentials to your Api
2)The callback function is static
3) i am using Oauth 1 and using google cloud for hosting
4)I have already cleared the cache 2 times still no use
.def _twitter(self):
# Get the access token supplied
oauth_token = self.test_credentials.get('oauth_token')
oauth_token_secret = self.test_credentials.get('oauth_token_secret')
if not oauth_token or not oauth_token_secret:
raise AuthenticationException('Invalid request format.', 400)
auth = tweepy.OAuthHandler(current_app.config['TWITTER_CONSUMER_KEY'], current_app.config['TWITTER_CONSUMER_SECRET'])
auth.set_access_token(oauth_token, oauth_token_secret)
api = tweepy.API(auth)
user = api.verify_credentials()
if not user:
raise AuthenticationException('Unable to verify credentials with remote server.', 500)
# Save the user
auth_string = self._auth_string(unicode(user.id_str))
stored_user = User.query(User.auth_ids == auth_string).get()
if not stored_user:
return User(name=user.name)
if stored_user and not stored_user.name:
stored_user.name = user.name
stored_user.put()
return stored_user
I forgot to add my callback function in the twitter api callbacks (these resolved my error)

Getting Facebook callback error even after enabling 'Embedded browser OAuth Login' and specifying the callback url

I have a rails(4.2.0) application that uses Facebook login functionality. The main gems are devise(3.4.0) and omniauth-facebook(2.0.0). I have registered the application on Facebook and have been using its test app for development. The Facebook login functionality works in the development env.
When trying to use the facebook login feature on the production server, I get error as "Given URL is not allowed by the Application configuration: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains."
The details for settings for test app being used in the dev env are as -
Settings:
Basic:
App Domains: 'localhost'
Website:
Site URL: 'http://localhost:3000'
Advanced:
OAuth Settings:
Embedded browser OAuth Login: Yes
Valid OAuth redirect URIs: "http://localhost:3000/users/auth/facebook/callback"
The details for settings for registered app being used in the production env are as -
Settings:
Basic:
App Domains: 'www.mysite.co'
Website:
Site URL: 'http://www.mysite.co'
Advanced:
OAuth Settings:
Embedded browser OAuth Login: Yes
Valid OAuth redirect URIs: "http://www.mysite.co/users/auth/facebook/callback"
I have specified the following in my secrets.yml
development:
secret_key_base: some_secret_key
facebook:
app_id: test_app_id
app_secret: test_app_secret
production:
secret_key_base: some_secret_key
facebook:
app_id: registered_app_id
app_secret: registered_app_secret
And have been using the creds from secrets.yml in the devise initialiser as
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
require 'omniauth-facebook'
config.omniauth :facebook, Rails.application.secrets.facebook['app_id'], Rails.application.secrets.facebook['app_secret'], scope: ['user_photos', 'email', 'public_profile']
The actual domain name(blackened) has no typos anywhere and is same wherever it is used.
Contains of routes.rb related to omniauth are as
cat config/routes.rb
Rails.application.routes.draw do
root 'home#index'
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
# routes related to other controllers
end
The routes are as below
bundle exec rake routes | grep user
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_omniauth_authorize GET|POST /users/auth/:provider(.:format) users/omniauth_callbacks#passthru {:provider=>/facebook/}
user_omniauth_callback GET|POST /users/auth/:action/callback(.:format) users/omniauth_callbacks#:action
The only code related to omniauth in the entire app is as
$ cat app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, event: :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Upon further digging the problem, it was observed that the error didnt occur when 'www.example.com' was specified in the url and hence, the callback worked. When 'example.com' was specified in the address bar and facebook login tried, the login crashed with the above error.
So, I fixed the above issue by making some changes to the settings in for the facebook app. I donno if this is the right approach but it worked out. Just making the change as in point 2 didnt solve the problem.
Changes are:
1) Specified the 'App Domains' with 'example.com' and 'www.example.com'
2) Enabled 'Client OAuth Login' to 'Yes'
3) Specified 'Valid OAuth redirect URIs' with 'http://example.com/users/auth/facebook/callback' and 'http://www.example.com/users/auth/facebook/callback'
Ok, so I assume that you have a web app NOT running on Facebook that simply uses the Facebook OAuth flow for login functionality, correct? If so, you must enable "Client OAuth Login" in your application settings for the production environment. If you don't, then the web OAuth flow will not work. See this article: https://developers.facebook.com/docs/facebook-login/security

cucumber test in rails application does not seem to be submitting a form to log a user in

I am trying to test my rails app using cucumber and webrat. I'm trying to get the test to login as a user who is already created and stored in the database, and I'm getting the following error:
Then I see a login error message # features/step_definitions/user_steps.rb:16
expected the following element's content to include "Welcome admin":
Csa
Welcome Guest
Forgot password?
or
Register
HomeJobs
English
Cymraeg
Welcome to CS-Alumni News
The is where the home page text will go.
(RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/user_steps.rb:18:in `/^I see a login error message$/'
features/users/login.feature:9:in `Then I see a login error message'
I changed the code to get it to login a user instead of failing to log in a user due to invalid details, as that wasn't working, and I wasn't sure if it was because it didn't pick up the flash message or not.
Here is the step_definitions file (user_steps.rb)
require 'webrat'
Given /^I do not have an account$/ do
#user = FactoryGirl.create(:user)
#user ||= User.where(:email >= #user[:email]).first
#user.destroy unless #user.nil?
end
When /^I attempt to login with my details$/ do
visit new_session_path
fill_in "login-input", :with => "admin"
fill_in "password", :with => "taliesin"
clicks_button "Login"
end
Then /^I see a login error message$/ do
visit home_path
response.should contain("Welcome admin")
end
And /^I should not be logged in$/ do
#response.should_not contain("Welcome admin")
end
Here is the login.feature file:
Feature: Login
In order to access my account
As a user
I want to be able to login
Scenario: User does not have an account
Given I do not have an account
When I attempt to login with my details
Then I see a login error message
And I should not be logged in
Scenario: User enters incorrect Login
Given I have an account
And I am not logged in
When I enter an incorrect Login
Then I see a login error message
And I should not be logged in
Scenario: User enters incorrect password
Given I have an account
And I am not logged in
When I enter an incorrect password
Then I see a login error message
And I should not be logged in
Scenario: User logs in successfully
Given I have an account
And I am not logged in
When I enter my correct login
And I enter my correct password
Then I see a successful login message
When I return to the application
Then I should still be logged in
Here is the env.rb file;
require 'cucumber/rails'
require 'webrat'
require 'cucumber/rails/world'
require 'webrat/core/matchers'
Webrat.configure do |config|
config.mode = :rack
config.open_error_files = false
end
World(Webrat::Methods)
World(Webrat::Matchers)
ActionController::Base.allow_rescue = false
begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
Cucumber::Rails::World.use_transactional_fixtures = false
class ActiveSupport::TestCase
setup do |session|
session.host! "localhost:3001"
end
end
rails/blob/master/features/choose_javascript_database_strategy.feature
Cucumber::Rails::Database.javascript_strategy = :truncation
Here is the gemfile:
# Use jquery as the JavaScript library
gem "jquery-rails", "~> 2.3.0"
gem 'jquery-ui-rails', '4.1.2'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.2'
group :doc do
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', require: false
end
group :development, :test do
gem 'rspec-rails', '~> 3.0.0'
gem 'cucumber-rails', require: false
gem "webrat"
gem 'factory_girl_rails'
gem 'selenium-client'
gem 'capybara'
gem 'database_cleaner'
end
Ok, so your step is this:
Then /^I see a login error message$/ do
visit home_path
response.should contain("Welcome admin")
end
And the error you're getting is: RSpec::Expectations::ExpectationNotMetError
I think it's just a case of you're expectation is wrong, but is at least a bit misleading. We should actually see an error (something like "Cannot login") but we are looking for "Welcome admin" which seems more like a welcome message.
We can debug this by placing puts response.body before the expectation to see what is being rendered.
It may also be that the cucumber isn't waiting for the request to finish. We could try adding find('#some-element') which will wait for a few seconds before failing if it cannot find an element.
Edit: Also, I just noticed the feature that you were running isn't the one you included (login.feature) so you're trying to see an error message without attempting an incorrect login.

Correct login with Doorkeeper/Bcrypt for Rails API

I have a created and API using rails 4 and at the moment I'm trying to figure out how to do the login. Since the API will be used for an iPhone app we decided to go with token authentication and Doorkeeper/OAuth2 gem.
So far I created a signin controller to take care of authenticating the user (I'm using bcrypt to hash passwords).
def create
#user = User.find_by(email: params[:username])
dbPasswordHash = BCrypt::Password.new(#user.password_digest)
if #user == nil
render json: 'noUser', status: :unprocessable_entity
else
if dbPasswordHash == params[:password]
client = OAuth2::Client.new(app_id, secret, :site => "http://localhost:3000/")
access_token = client.password.get_token(#user.email, dbPasswordHash)
render json: access_token.to_json, status: :ok, location: #user
else
render json: {status:'ERROR',status_info:'Wrong username/password'}, status: :unprocessable_entity
end
end
end
The problem I'm having with the above code is that Faraday timesout. The issue lies with the access_token call. Since a POST request was made to /signin the second one (access_token), which goes to Doorkeeper to authenticate, will have to wait until the first is done.
I'm not sure if I'm over complicating the process but what I want to achieve is for a request to be made from the front-end, the user is authenticated and token's returned to the front-end for future use.
Another approach I tried is to POST to /oauth/token with:
{
"grant_type" : "password",
"username" : "test#gmail.com",
"password" : "$2a$10$igmaaZkrSviHc.8Glm3hcuRdqzeT5YQwYaKFN9eUbpfcmCqA3PBiO",
"client_id" : "f5cbc8d91f6e007c003e17baf3f45cb83cede4313c381afa99e456f59b08e3f8",
"client_secret" : "f827f84548b33ebd8042cfbaa7aff944f5844aad7962623ed68d83963bc62bb5"
}
This approach works fine but the password is already hashed and when I try to use
dbPasswordHash = BCrypt::Password.new(params[:password])
in doorkeeper.rb I get an error about BCrypt (I did try "require 'bcrypt'").
Any suggestions would be welcomed.

Can't Authenticate through Facebook PHP SDK

I currently force users to authenticate through Facebook each time they start a new session with my site. This means I force users to hit the url obtained through $facebook->getLoginURL() each time the browser is restarted.
When a user completes the login process, they are redirected to my login script:
{checks for CSRF token and error status...}
$facebook = new Facebook(array(
'appId' => '{my app id}',
'secret' => '{my app secret}',
'cookie' => true
));
//Get user info
$user = $facebook->getUser();
if($user)
echo 'user found';
else
echo 'no user!';
$user always results in 0; I am getting the expected 'state' variable and no errors in the API response. Also, I see that the relevant App permissions exist on my profile. However, $facebook->getUser() still returns 0. Is there some intermediate step that I'm missing (am I expected to do anything with the user's auth token?)
I know there are many threads on this problem but haven't found any resolutions. Also, I think this is a very basic example so I'm hoping the answer here will be more useful for future users dealing with the problem. Thanks!