1

I've searched everywhere for a solution. Any help is greatly, greatly appreciated. I've set up linkedin oauth in my rails 5 app along with devise, and sometimes it works (1 out of 50 times), sometimes it doesn't using the exact same workflow. Though, I do get the same "error" in my log each time. It's crazy, and it's making me crazy.

My Code:

Gemfile

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.7'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
# gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem 'bootstrap', '~> 4.3.1'
gem 'jquery-rails'
gem 'devise'
gem 'figaro'
gem 'simple_form'
gem "font-awesome-rails"
gem 'carrierwave', '~> 1.0'
gem "fog-aws"
gem 'searchkick'
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
gem 'stripe', :git => 'https://github.com/stripe/stripe-ruby'
gem 'will_paginate', '~> 3.1.0'
gem 'local_time'
gem 'oauth2'
gem 'paypal-checkout-sdk'
gem 'paypal-sdk-rest'
gem "chartkick"
gem 'groupdate'
gem 'omniauth-linkedin-oauth2'




group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
    gem 'dotenv', '~> 2.2.1'

end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

routes.rb

Rails.application.routes.draw do
  devise_for :users, :controllers => {
    :omniauth_callbacks => "users/omniauth_callbacks" 
  }
  resources :users
  root 'static_pages#landing'
end

users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def linkedin
    # 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?
      puts "user persisted"
      sign_in_and_redirect @user #this will throw if @user is not activated
      set_flash_message(:notice, :success, kind: "Linkedin") if is_navigational_format?
    else
      puts "user not persisted"
      session["devise.linkedin_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end
  def failure
    puts 'uh oh'
    redirect_to root_path, notice: "That didn't work..."
  end
end

user.rb

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: [:linkedin]
  has_many :ratingreports
  has_many :ratings

  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0, 20]
    end
  end
end

devise.rb

  config.omniauth :linkedin, ENV['LINKEDIN_CLIENT_ID'], ENV['LINKEDIN_CLIENT_SECRET']

devise/registrations/new.html.erb

  <a href="/users/auth/linkedin"">
    <img src="/assets/signinlinkedin.png">
  </a>

My errors:

This is where it's weird. I'm going to include an example of when it works for me AND when it doesn't. You'll see both have an error, but when it works, i'm logged in and 'validated' from linkedin. I'm having a hard time understanding, it almost looks like it's making two callbacks in both cases.

So, when it works:

Started GET "/users/sign_up" for ::1 at 2019-08-12 10:35:03 -0400
   (0.7ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by Devise::RegistrationsController#new as HTML
  Rendering devise/registrations/new.html.erb within layouts/application
  Rendered devise/shared/_error_messages.html.erb (0.7ms)
  Rendered devise/shared/_links.html.erb (1.2ms)
  Rendered devise/registrations/new.html.erb within layouts/application (43.2ms)
Completed 200 OK in 1093ms (Views: 1068.5ms | ActiveRecord: 5.0ms)


Started GET "/users/auth/linkedin" for ::1 at 2019-08-12 10:35:06 -0400
I, [2019-08-12T10:35:06.775178 #93645]  INFO -- omniauth: (linkedin) Request phase initiated.
Started GET "/users/auth/linkedin/callback?code=AQTF0qDslWsgBEc-AaobJCh0bFd9xfa8eY_s0OKS60Ff7JqQcHOjza18pI1dl4nHnX5x8Rz-66_GvEo6g9Rlz5lJNAhEiTJfb0i4mGM-iSMq7b0-GYHpAn4u6WTRBwv-5duOCZ4kYyvnuyvShtGjef-j96ga-x3OgUlJT4gQpvZ4RcOwnBsLIZ4vGDkr9w&state=c7fcd6e5d44f832708fbddb0f9e47379d28eb2c98f52da5a" for ::1 at 2019-08-12 10:35:12 -0400
I, [2019-08-12T10:35:12.644665 #93645]  INFO -- omniauth: (linkedin) Callback phase initiated.
Started GET "/users/auth/linkedin/callback?code=AQTF0qDslWsgBEc-AaobJCh0bFd9xfa8eY_s0OKS60Ff7JqQcHOjza18pI1dl4nHnX5x8Rz-66_GvEo6g9Rlz5lJNAhEiTJfb0i4mGM-iSMq7b0-GYHpAn4u6WTRBwv-5duOCZ4kYyvnuyvShtGjef-j96ga-x3OgUlJT4gQpvZ4RcOwnBsLIZ4vGDkr9w&state=c7fcd6e5d44f832708fbddb0f9e47379d28eb2c98f52da5a" for ::1 at 2019-08-12 10:35:13 -0400
I, [2019-08-12T10:35:13.154745 #93645]  INFO -- omniauth: (linkedin) Callback phase initiated.
E, [2019-08-12T10:35:13.991533 #93645] ERROR -- omniauth: (linkedin) Authentication failure! invalid_credentials: OAuth2::Error, invalid_request: Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists
{"error":"invalid_request","error_description":"Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists"}
Processing by Users::OmniauthCallbacksController#failure as HTML
Processing by Users::OmniauthCallbacksController#linkedin as HTML
  Parameters: {"code"=>"AQTF0qDslWsgBEc-AaobJCh0bFd9xfa8eY_s0OKS60Ff7JqQcHOjza18pI1dl4nHnX5x8Rz-66_GvEo6g9Rlz5lJNAhEiTJfb0i4mGM-iSMq7b0-GYHpAn4u6WTRBwv-5duOCZ4kYyvnuyvShtGjef-j96ga-x3OgUlJT4gQpvZ4RcOwnBsLIZ4vGDkr9w", "state"=>"c7fcd6e5d44f832708fbddb0f9e47379d28eb2c98f52da5a"}
  Parameters: {"code"=>"AQTF0qDslWsgBEc-AaobJCh0bFd9xfa8eY_s0OKS60Ff7JqQcHOjza18pI1dl4nHnX5x8Rz-66_GvEo6g9Rlz5lJNAhEiTJfb0i4mGM-iSMq7b0-GYHpAn4u6WTRBwv-5duOCZ4kYyvnuyvShtGjef-j96ga-x3OgUlJT4gQpvZ4RcOwnBsLIZ4vGDkr9w", "state"=>"c7fcd6e5d44f832708fbddb0f9e47379d28eb2c98f52da5a"}
uh oh
Redirected to http://localhost:3000/
Completed 302 Found in 2ms (ActiveRecord: 0.0ms)


  User Load (2.1ms)  SELECT  "users".* FROM "users" WHERE "users"."provider" = $1 AND "users"."uid" = $2 ORDER BY "users"."id" ASC LIMIT $3  [["provider", "linkedin"], ["uid", "jFN3hz7u4N"], ["LIMIT", 1]]
user persisted
Redirected to http://localhost:3000/
Completed 302 Found in 5011ms (ActiveRecord: 2.1ms)


Started GET "/" for ::1 at 2019-08-12 10:35:19 -0400
Processing by StaticPagesController#landing as HTML
  Rendering static_pages/landing.html.erb within layouts/application
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 35], ["LIMIT", 1]]
  Rendered static_pages/landing.html.erb within layouts/application (81.6ms)
Completed 200 OK in 208ms (Views: 203.0ms | ActiveRecord: 0.4ms)

And, when it doesn't work:

Started GET "/users/sign_up" for ::1 at 2019-08-12 10:42:19 -0400
Processing by Devise::RegistrationsController#new as HTML
  Rendering devise/registrations/new.html.erb within layouts/application
  Rendered devise/shared/_error_messages.html.erb (1.7ms)
  Rendered devise/shared/_links.html.erb (2.9ms)
  Rendered devise/registrations/new.html.erb within layouts/application (17.4ms)
Completed 200 OK in 170ms (Views: 168.8ms | ActiveRecord: 0.0ms)


Started GET "/users/auth/linkedin" for ::1 at 2019-08-12 10:42:21 -0400
I, [2019-08-12T10:42:21.111399 #93645]  INFO -- omniauth: (linkedin) Request phase initiated.
Started GET "/users/auth/linkedin/callback?code=AQRQShkIhL925IkTcbRPqcoWMeBJEDawTj2US3tWsIjGQSXUES_wQmkQvqxGdL7POZ6kaYkrzX9cxDsrcZIVxX7vqLTcsa_XwaaNkR5sAna4IcrZlWtHzO4IgF0NJxi3RhqStUN0cyolcLq0Wqrq5Oqj7oKUFTHDyo8ONpxHr8WowXKoBuKlOyL9681MCg&state=fb78fdf65c4e2e4209aef98253f88734c45b7dd081459dbc" for ::1 at 2019-08-12 10:42:25 -0400
I, [2019-08-12T10:42:25.111858 #93645]  INFO -- omniauth: (linkedin) Callback phase initiated.
Started GET "/users/auth/linkedin/callback?code=AQRQShkIhL925IkTcbRPqcoWMeBJEDawTj2US3tWsIjGQSXUES_wQmkQvqxGdL7POZ6kaYkrzX9cxDsrcZIVxX7vqLTcsa_XwaaNkR5sAna4IcrZlWtHzO4IgF0NJxi3RhqStUN0cyolcLq0Wqrq5Oqj7oKUFTHDyo8ONpxHr8WowXKoBuKlOyL9681MCg&state=fb78fdf65c4e2e4209aef98253f88734c45b7dd081459dbc" for ::1 at 2019-08-12 10:42:25 -0400
I, [2019-08-12T10:42:25.627869 #93645]  INFO -- omniauth: (linkedin) Callback phase initiated.
Processing by Users::OmniauthCallbacksController#linkedin as HTML
  Parameters: {"code"=>"AQRQShkIhL925IkTcbRPqcoWMeBJEDawTj2US3tWsIjGQSXUES_wQmkQvqxGdL7POZ6kaYkrzX9cxDsrcZIVxX7vqLTcsa_XwaaNkR5sAna4IcrZlWtHzO4IgF0NJxi3RhqStUN0cyolcLq0Wqrq5Oqj7oKUFTHDyo8ONpxHr8WowXKoBuKlOyL9681MCg", "state"=>"fb78fdf65c4e2e4209aef98253f88734c45b7dd081459dbc"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."provider" = $1 AND "users"."uid" = $2 ORDER BY "users"."id" ASC LIMIT $3  [["provider", "linkedin"], ["uid", "jFN3hz7u4N"], ["LIMIT", 1]]
E, [2019-08-12T10:42:25.975711 #93645] ERROR -- omniauth: (linkedin) Authentication failure! invalid_credentials: OAuth2::Error, invalid_request: Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists
{"error":"invalid_request","error_description":"Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists"}
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>"AQRQShkIhL925IkTcbRPqcoWMeBJEDawTj2US3tWsIjGQSXUES_wQmkQvqxGdL7POZ6kaYkrzX9cxDsrcZIVxX7vqLTcsa_XwaaNkR5sAna4IcrZlWtHzO4IgF0NJxi3RhqStUN0cyolcLq0Wqrq5Oqj7oKUFTHDyo8ONpxHr8WowXKoBuKlOyL9681MCg", "state"=>"fb78fdf65c4e2e4209aef98253f88734c45b7dd081459dbc"}
uh oh
Redirected to http://localhost:3000/
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)


Started GET "/" for ::1 at 2019-08-12 10:42:25 -0400
Processing by StaticPagesController#landing as HTML
  Rendering static_pages/landing.html.erb within layouts/application
  Rendered static_pages/landing.html.erb within layouts/application (6.4ms)
Completed 200 OK in 114ms (Views: 111.8ms | ActiveRecord: 0.0ms)


user persisted
Redirected to http://localhost:3000/
Completed 302 Found in 5009ms (ActiveRecord: 0.5ms)

Anyone who helps me out, of course you'll get a virtual high five..

bwatson30
  • 263
  • 1
  • 3
  • 12

1 Answers1

0

Looks like your redirect URL is called twice after user authentication on LinkedIn.

First time everything is working because the authorization code is valid ; second time it's not because the authorization code has already been used. In both cases, an user is created in database: "User persisted" is displayed in both cases.

Can you fix your "devise/registrations/new.html.erb" file by removing the extra quotes?

<a href="/users/auth/linkedin">
<img src="/assets/signinlinkedin.png">
</a>
sgraton
  • 96
  • 4