I'm getting what seems to be a successful response from Twitter:
/auth/twitter/callback?oauth_token=somelongtoken&oauth_verifier=someverifier
But there's no oauth_token_secret there. Where do I get it?
DETAIL
routes.rb
get '/auth/:provider', to: 'authorisations#authorise', :as => :new_auth
get '/auth/:provider/callback', to: 'authorisations#callback'
authorisations_controller.rb
def authorise
session[:user_id] = current_user.id
#authorisation = Authorisation.new
#authorisation.user_id = current_user.id
if auth_hash.provider == "facebook"
#authorisation.provider = auth_hash.provider
#authorisation.oauth_token = auth_hash.credentials.token
#authorisation.oauth_expires_at = Time.at(auth_hash.credentials.expires_at)
elsif params[:provider] == "twitter"
#authorisation.provider = params[:provider]
#authorisation.oauth_token = params[:oauth_token]
#authorisation.oauth_token_secret = params[:oauth_token_secret]
#authorisation.access_token = params[:oauth_verifier]
end
#authorisation.save!
end
def callback
session[:user_id] = current_user.id
#authorisation = Authorisation.new
#authorisation.user_id = current_user.id
if auth_hash.provider == "facebook"
#authorisation.provider = auth_hash.provider
#authorisation.oauth_token = auth_hash.credentials.token
#authorisation.oauth_expires_at = Time.at(auth_hash.credentials.expires_at)
elsif params[:provider] == "twitter"
#authorisation.provider = params[:provider]
#authorisation.oauth_token = params[:oauth_token]
#authorisation.oauth_token_secret = params[:oauth_token_secret]
#authorisation.access_token = params[:oauth_verifier]
end
#authorisation.save!
redirect_to root_url, notice: "#{current_user.name} and #{params[:provider].titlecase} have been linked."
end
def auth_hash
request.env['omniauth.auth']
end
documents_controller.rb
def twitter
session[:return_to] = request.referer
#document = Document.find(params[:id])
if #document.template.name == "Image"
#document.process_social_media
twitter_user.update_with_media("#{#document.remove_html(#document.components.first.body[0..100])}...", "#{root_url}temporary#{#document.temp_file_name}.jpg")
else
twitter_user.update("#{#document.remove_html(#document.components.first.body[0..100])}... #{root_url.gsub(/\/$/, '')}#{share_path(#document.user.ftp, #document)}")
end
redirect_to session[:return_to], notice: "#{#document.title} has been posted to Twitter."
end
def twitter_user
user = Twitter.configure do |config|
config.consumer_key = ENV['TWITTER_CONSUMER_KEY']
config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET']
config.oauth_token = current_user.single_authorisation("twitter").oauth_token
config.oauth_token_secret = current_user.single_authorisation("twitter").oauth_token_secret
end
end
It has been a while since I did this, so maybe it has changed, but these are the parameters I pass in the authorization request:
oauth_consumer_key
oauth_nonce
oauth_signature
oauth_signature_method
oauth_timestamp
oauth_version
It's here for anyone hunting around:
def create
#authorisation.oauth_token_secret = auth_hash.credentials.secret
end
def auth_hash
request.env['omniauth.auth']
end
Cheers.
Related
I am using the omniauth-stripe-connect gem and get the following error when authenticating users:
NoMethodError in Users::OmniauthCallbacksController#stripe_connect
undefined method `persisted?' for nil:NilClass
My Callbacks Controller Action:
def stripe_connect
#user = UserProvider.find_for_stripe_oauth(request.env["omniauth.auth"])
if #user.persisted? # here is the issue !!!
sign_in #user, :event => :authentication
redirect_to root_path
end
end
And my User Method:
def self.find_for_stripe_oauth(auth)
user = UserProvider.where(:provider => auth.provider, :uid => auth.uid).first
unless user.nil?
user.user
else
registered_user = User.where(:email => auth.info.email).first
unless registered_user.nil?
user_provider = UserProvider.new
user_provider.provider = auth.provider
user_provider.uid = auth.uid
user_provider.user_id = registered_user.id
user_provider.save!
registered_user.stripe_access_code = auth.credentials.token
registered_user.stripe_publishable_key = auth.info.stripe_publishable_key
registered_user.stripe_id = auth.extra.raw_info.stripe_user_id
registered_user.skip_confirmation!
registered_user.save!
registered_user
end
end
end
What am I doing wrong?
find_for_stripe_oauth returns nil if registered_user is not exists. In this case unless registered_user.nil? returns false and inner block is not executed.
Move out registered_user, like this:
registered_user = User.where(:email => auth.info.email).first
unless registered_user.nil?
user_provider = UserProvider.new
user_provider.provider = auth.provider
user_provider.uid = auth.uid
user_provider.user_id = registered_user.id
user_provider.save!
registered_user.stripe_access_code = auth.credentials.token
registered_user.stripe_publishable_key = auth.info.stripe_publishable_key
registered_user.stripe_id = auth.extra.raw_info.stripe_user_id
registered_user.skip_confirmation!
registered_user.save!
end
registered_user
My twitter controller code is this
class TwitterController < ApplicationController
before_filter :authenticate_user!
def index
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
redirect_to "/twitter_profile"
end
end
def generate_twitter_oauth_url
oauth_callback = "http://#{request.host}:#{request.port}/oauth_account"
#consumer = OAuth::Consumer.new("n3yfOi9iEHwnyz5uEsyNotW6t","kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc", :site => "https://api.twitter.com")
#request_token = #consumer.get_request_token(:oauth_callback => oauth_callback)
session[:request_token] = #request_token
redirect_to #request_token.authorize_url(:oauth_callback => oauth_callback)
end
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
#request_token = session[:request_token]
#access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
def twitter_profile
#user_timeline = get_client.user_timeline
#home_timeline = get_client.home_timeline
end
private
def get_client
Twitter.configure do |config|
config.consumer_key = "n3yfOi9iEHwnyz5uEsyNotW6t"
config.consumer_secret = "kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc"
end
Twitter::Client.new(
:oauth_token => TwitterOauthSetting.find_by_user_id(current_user.id).atoken,
:oauth_token_secret => TwitterOauthSetting.find_by_user_id(current_user.id).asecret
)
end
def update_user_account
user_twitter_profile = get_client.user
current_user.update_attributes({
name: user_twitter_profile.name,
screen_name: user_twitter_profile.screen_name,
url: user_twitter_profile.url,
profile_image_url: user_twitter_profile.profile_image_url,
location: user_twitter_profile.location,
description: user_twitter_profile.description
})
end
end
On index page add your twitter account option is there. After clicking on that it will authorize app & After authorizaion process i am facing an error "undefined method `get_access_token' .i am facing error in this line " #access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])"
The solution of my problem:
What i did is I added a new method to prepare access token & in get client method used Twitter::REST::Client.new do |config| and also provided access_token & access_token_secret_key and now it is working properly.
class TwitterController < ApplicationController
before_filter :authenticate_user!
def index
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
redirect_to "/twitter_profile"
end
end
def generate_twitter_oauth_url
oauth_callback = "http://#{request.host}:#{request.port}/oauth_account"
#consumer = OAuth::Consumer.new("2K763Dgw9y6oAOOLsegegkHW7","pwXauJeR628SL8DhgwikStNYykGCKoabISHI4ZUnKIxt2eSmNY", :site => "https://api.twitter.com")
#request_token = #consumer.get_request_token(:oauth_callback => oauth_callback)
session[:request_token] = #request_token
redirect_to #request_token.authorize_url(:oauth_callback => oauth_callback)
end
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
#request_token = session[:request_token]
prepare_access_token(params[:oauth_token],params[:oauth_token_secret])
#consumer = OAuth::Consumer.new(params[:oauth_token],params[:oauth_token_secret], :site => "https://api.twitter.com")
#access_token = prepare_access_token(params[:oauth_token],params[:oauth_token_secret])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
def twitter_profile
#user_timeline = get_client.user_timeline
#home_timeline = get_client.home_timeline
end
private
def get_client
Twitter::REST::Client.new do |config|
config.consumer_key = "n3yfOi9iEHwnyz5uEsyNotW6t"
config.consumer_secret = "kqHFm5dRRX00dIQSwBcTEJKZNAzrWcuK0BOAyDVWY8liRI1cPc"
config.access_token = "access_token key"
config.access_token_secret = "access_token_secret key"
end
end
def update_user_account
user_twitter_profile = get_client.user
current_user.update_attributes({
name: user_twitter_profile.name,
screen_name: user_twitter_profile.screen_name,
url: user_twitter_profile.url,
profile_image_url: user_twitter_profile.profile_image_url,
location: user_twitter_profile.location,
description: user_twitter_profile.description
})
end
def prepare_access_token(oauth_token, oauth_token_secret)
#consumer = OAuth::Consumer.new("APIKey", "APISecret", { :site => "https://api.twitter.com", :scheme => :header })
#consumer = OAuth::Consumer.new("2K763Dgw9y6oAOOLsegegkHW7","pwXauJeR628SL8DhgwikStNYykGCKoabISHI4ZUnKIxt2eSmNY", { :site => "https://api.twitter.com", :scheme => :header })
# now create the access token object from passed values
token_hash = { :oauth_token => oauth_token, :oauth_token_secret => oauth_token_secret }
access_token = OAuth::AccessToken.from_hash(#consumer, token_hash )
return access_token
end
end
Your #request_token is apparently a string, which is why the get_access_token method is undefined.
Replace the oauth_account method with the one below to recreate the #request_token because #request_token = session[:request_token] will create a string instead and the get_access_token method is hence undefined.
def oauth_account
if TwitterOauthSetting.find_by_user_id(current_user.id).nil?
# Re-create the request token
#consumer = OAuth::Consumer.new(ENV["consumer_key"], ENV["consumer_secret"], :site => "https://api.twitter.com")
#request_token = OAuth::RequestToken.new(#consumer, session[:request_token], session[:request_secret])
#access_token = #request_token.get_access_token(:oauth_verifier => params["oauth_verifier"])
TwitterOauthSetting.create(atoken: #access_token.token, asecret: #access_token.secret, user_id: current_user.id)
update_user_account()
end
redirect_to "/twitter_profile"
end
Replace the get_client method with the one below to access the user's token and its access which are stored in the session.
def get_client
Twitter::REST::Client.new do |config|
config.consumer_key = ENV["consumer_key"]
config.consumer_secret = ENV["consumer_secret"]
unless TwitterOauthSetting.find_by_user_id(current_user.id).nil?
config.oauth_token = TwitterOauthSetting.find_by_user_id(current_user.id).atoken
config.oauth_token_secret = TwitterOauthSetting.find_by_user_id(current_user.id).asecret
end
end
end
Check using logger the value of #acces_token. Maybe it is not getting the required value or datatype.
In my application, I have a twitter and facebook login, however I need to prompt a password and email after they first register with twitter or facebook. I am using omniauth gems and my controller/user model looks like this:
//socials_controller.rb
def create
#render text: request.env['omniauth.auth'].to_yaml and return
#user = User.from_omniauth(request.env['omniauth.auth'])
if(#user.email == nil)
redirect_to patient_login_entry_url(#user)
elsif #user.confirmed
log_in #user
redirect_to #user
else
flash[:danger] = "Bir hata olustu."
redirect_to root_url
end
end
def login_entry
#patient = Patient.find(params[:id])
end
def update_social
#patient = Patient.find(params[:id])
if #patient.update_attributes(user_params)
SendVerificationEmailJob.perform_later #patient
flash[:success] = "Aktivasyon için #{#patient.email} adresinizi kontrol ediniz."
redirect_to root_url
else
flash[:danger] = "Bilgilerinizi kontrol edip tekrar deneyiniz."
redirect_to patient_login_entry_url(#patient)
end
end
and my from_omniauth method is:
//user.rb
has_secure_password
class << self
def from_omniauth(auth_hash)
if exists?(uid: auth_hash['uid'])
user = find_by(uid: auth_hash['uid'])
else
user = find_or_create_by(uid: auth_hash['uid'], provider: auth_hash['provider'], type: 'Patient')
user.location = get_social_location_for user.provider, auth_hash['info']['location']
if auth_hash.provider == 'facebook'
user.avatar = User.process_uri(auth_hash['info']['image'])
user.name = auth_hash['extra']['raw_info']['first_name']
user.surname = auth_hash['extra']['raw_info']['last_name']
user.email = auth_hash['extra']['raw_info']['email']
user.gender = auth_hash['extra']['raw_info']['gender']
elsif auth_hash.provider == 'twitter'
user.avatar = auth_hash['info']['image']
user.name = auth_hash['info']['name']
end
user.url = get_social_url_for user.provider, auth_hash['info']['urls']
user.save!
end
user
end
At the login_entry page, I simply prompt the email and password, and POSTing them to the update_social method.
However, as expected, my app throws the error "Password can't be blank", because has_secure_password validates its presence by default. So, I need to persist it between the requests since I can not save it without a password. How can I achieve this?
I tried to store the created object in session by using to_json method, and turning it into a hash between requests, however this time the profile picture I got from twitter/facebook did not persist (I'm using AWS S3 + Paperclip, the URL persists but there is no such image when I check it from the S3 console) so I think that solution was not good.
I have a landing page controller that looks like this ;
class LandingController < ApplicationController
def index
#user = current_user
#name = #user.name.titleize
#balance = "#{#user.currency} #{#user.balance}"
#last_login = #user.last_sign_in_at
api_key = ApiKey.find_by_user_id( #user.id)
#access_token = api_key.access_token
end
def check_mail
end
end
However, in a controller method shown below, when i make the redirect i get an error.
Controller method;
def success
transaction = Transaction.find_by_token(params[:token])
transaction.payer_id = params[:payer_id]
transaction.save
#current_user = user = User.find(transaction.user_id)
username = "xxxxxxxxxxxxxxxxxxxx"
password = "7xxxxxxxxxxxxxxx"
signature = "xxxxxxxxxxxxxxx"
version = 98
#amount = Currency.convert(user.currency, "USD", transaction.amount.to_f).to_f.round(2)
url = "https://api-3t.paypal.com/nvp?USER=#{username}&PWD=#{password}&SIGNATURE=#{signature}&VERSION=#{version}&METHOD=DoExpressCheckoutPayment&TOKEN=#{transaction.token}&PAYERID=#{transaction.payer_id}&PAYMENTREQUEST_0_PAYMENTACTION=SALE&PAYMENTREQUEST_0_AMT=#{#amount}&PAYMENTREQUEST_0_CURRENCYCODE=USD"
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
res = http.request(request)
response = res.body
transaction.save
user.balance = (user.balance+transaction.amount)
user.save()
transaction.status ="Completed"
transaction.save()
flash[:notice] = 'Payment Transaction Completed. Thank you for using skyline SMS'
redirect_to user_home_path(#current_user)
end
i get the error below;
undefined method `name' for nil:NilClass
with the trace;
app/controllers/landing_controller.rb:4:in `index'
How can i go about it?
The problem is that the #user variable in LandingController don't have a value (it's nil), that's why you're getting undefined method name for nil:class, try this: put the redirect like this
#stuff...
redirect_to user_home_path(:current_user => #current_user)
end
and in LandingController index put this
def index
#user = params[:current_user]
#name = #user.name.titleize
#...rest of the method...
when I am call in spec, the get :authenticate_linkedin_login method of controller getting error the oauth:problem permission unknown.
*spec file.*
describe LinkedinProfileController do
include LinkedinStubs
before(:each) do
#temp = Factory(:worker)
controller.stub(:authenticate_user!)
controller.stub!(:current_user).and_return(#temp)
WebMock.allow_net_connect!(:net_http_connect_on_start => true)
end
describe "/login" do
it "should redirect to linkedin authorization url" do
stub_oauth_request_token!
get :linkedin_login
session[:rtoken].should == 't'
session[:rsecret].should == 's'
response.location.should =~ /www.linkedin.com/
response.should be_redirect #request authorize url
end
end
describe "/authenticate_linkedin_login" do
it "should be authorize_from_request" do
get :authenticate_linkedin_login,:oauth_verifier=>'12345'
*Controller*
class LinkedinProfileController < ApplicationController
before_filter :authenticate_worker!
def linkedin_login
client = LinkedIn::Client.new('lrkf3ol8f91k','OGJbzX3lKNSOxNwT')
request_token = client.request_token(:oauth_callback => "http://#{request.host_with_port}/authenticate_linkedin_login")
session[:rtoken] = request_token.token
session[:rsecret] = request_token.secret
redirect_to client.request_token.authorize_url
end
def authenticate_linkedin_login
client = LinkedIn::Client.new('lrkf3ol8f91k','OGJbzX3lKNSOxNwT')
if session[:atoken].nil?
pin = params[:oauth_verifier]
atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
session[:atoken] = atoken
session[:asecret] = asecret
else
client.authorize_from_access(session[:atoken], session[:asecret])
end