Search code examples
ruby-on-railsdeviseruby-on-rails-5omniauthcoinbase-api

Omniauth2 Devise Coinbase strategy


I'm building an application with Google and CoinBase oauth2 strategies using Devise. I followed the Devise oauth instructions pretty much to a T, but I'm still having trouble authenticating with CoinBase. The error I'm getting on sign in is Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.. Authentication through Google is working perfectly in both development and production modes. Here are each of the applicable files:

config/initializers/devise.rb

config.omniauth :google_oauth2, ENV['google_id'], ENV['google_secret']
config.omniauth :coinbase, ENV['coinbase_id'], ENV['coinbase-secret']

OmniAuth.config.logger = Rails.logger if Rails.env.development?

controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def coinbase
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user
      set_flash_message(:notice, :success, :kind => "Coinbase") if is_navigational_format?
    else
      session["devise.coinbase_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def google_oauth2
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user
      set_flash_message(:notice, :success, :kind => "Google") if is_navigational_format?
    else
      session["devise.google_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :async,
     :recoverable, :rememberable, :trackable, :validatable, 
     :omniauthable, omniauth_providers: [:google_oauth2, :coinbase]

  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

  def self.new_with_session(params, session)
    super.tap do |user|
      if (data = session["devise.google_data"] && session["devise.google_data"]["extra"]["raw_info"]) || (data = session["devise.coinbase_data"] && session["devise.coinbase_data"]["extra"]["raw_info"])
        user.email = data["email"] if user.email.blank?
      end
    end
  end

I've been trying to figure out what might be triggering the failure and all I've come up with is that the omniauth-coinbase gem might not be supported anymore. Has anyone else run into difficulty using oauth2 with CoinBase?

edit: Log of the oauth request

Started GET "/users/auth/coinbase" for 127.0.0.1 at 2017-11-06 19:29:57 -0600 (coinbase) Request phase initiated. Started GET "/users/auth/coinbase" for 127.0.0.1 at 2017-11-06 19:29:57 -0600 (coinbase) Request phase initiated. Started GET "/users/auth/coinbase/callback?code=#{redacted_coinbase_client_id}&state={redacted_coinbase_secret}" for 127.0.0.1 at 2017-11-06 19:30:06 -0600 (coinbase) Callback phase initiated. (coinbase) Authentication failure! invalid_credentials: OAuth2::Error, invalid_client: Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method. {"error":"invalid_client","error_description":"Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."} Processing by Users::OmniauthCallbacksController#failure as HTML Parameters: {"code"=>redacted_coinbase_client_id, "state"=>redacted_coinbase_secret} Redirected to http://portalbase.dev/ Completed 302 Found in 1ms (ActiveRecord: 0.0ms)


Solution

  • I hit a dead end with this project, but I did figure out the source of the issue. Coinbase only allows you to redirect to https domains, which is a problem if you're using localhost.

    The solution would be to set up an SSL certificate for a local domain (which I don't have the expertise to do) or to use a service like ngrok.