Ruby on Rails 中的 Linkedin Oauth 并不是每隔几次就登录一次

问题描述 投票:0回答:1

我一直在开发一个使用新的 Linkedin OpenID 登录功能的应用程序。问题是它确实有效,但大多数时候它都有效。每隔几次(3-10次,相当随机)它不会让您登录,而是将您带回到根路径。我已经阅读了所有可能的情况并骚扰了 ChatGPT,但一无所获。我还尝试向控制器添加 cookie 清除机制,但没有效果。代码如下所示:

omniauth_callbacks_controller.rb:

# frozen_string_literal: true

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  before_action :retries

  def linkedin
    # flash[:notice] = I18n.t('omniauth_callbacks.notice.linkedin_callback_initiated')
    login
  end

  def failure
    if @retries < 1
      @retries += 1
      login # Retry the authentication
    else
      redirect_to root_path
    end
  end

  def login
    if auth_hash.nil?
      # puts "Authentication data not received from provider."
      redirect_to root_path
      return
    end
    # flash[:notice] = I18n.t('omniauth_callbacks.notice.processing_linkedin_login', uid: auth_hash[:uid])
    existing_user = User.find_by(uid: auth_hash[:uid])

    if existing_user.present?
      # flash[:notice] = I18n.t('omniauth_callbacks.notice.existing_user_found', uid: auth_hash[:uid])
      sign_in_existing_user(existing_user)
    else
      # flash[:notice] = I18n.t('omniauth_callbacks.notice.no_existing_user')
      create_or_sign_in_user
    end
  end

  private

  def retries
    @retries ||= 0
  end

  def auth_hash
    request.env['omniauth.auth'].tap do |auth|
      # flash[:notice] = I18n.t('omniauth_callbacks.notice.auth_hash_received', auth: auth.inspect)
    end
  end

  def sign_in_existing_user(user)
    if user.provider == auth_hash[:provider]
      # flash[:notice] = I18n.t('omniauth_callbacks.notice.signing_in_existing_user', email: user.email)
      sign_in_and_redirect(user)
    else
      flash[:alert] = I18n.t('omniauth_callbacks.alert.user_exists_different_provider', email: user.email)
      redirect_to root_path
    end
  end

  def create_or_sign_in_user
    user = User.from_omniauth(auth_hash).tap do |new_user|
      # flash[:notice] = I18n.t('omniauth_callbacks.notice.user_persisted', email: new_user.email)
    end

    if user.persisted?
      handle_persisted_user(user)
    else
      handle_nonpersisted_user(user)
    end
  end

  def handle_persisted_user(user)
    # flash[:notice] = I18n.t('omniauth_callbacks.notice.user_persisted', email: user.email)
    sign_in_and_redirect(user)
    # set_flash_message(:notice, :success, kind: 'LinkedIn') if is_navigational_format?
  end

  def handle_nonpersisted_user(user)
    flash[:alert] = I18n.t('omniauth_callbacks.alert.unable_to_sign_in', errors: user.errors.full_messages.join(', '))
    redirect_to root_path
  end
end

Devise.rb 设置:

config.skip_session_storage = [:http_auth, :linkedin]
config.omniauth :linkedin, ENV.fetch('LINKEDIN_CLIENT_ID', nil) || Rails.application.credentials[:linkedin_id], ENV.fetch('LINKEDIN_CLIENT_SECRET', nil) || Rails.application.credentials[:linkedin_key], :scope => 'openid profile email'

宝石档案:

gem 'oauth2', '~> 2.0', '>= 2.0.9'
gem "omniauth", "~> 2.1.2"
gem 'omniauth-linkedin-openid', '~> 1.0.1'
gem 'omniauth-oauth2', '~> 1.8'
gem "omniauth-rails_csrf_protection", '~> 1.0.1'

未登录时的错误日志:

web-1            | D, [2024-07-02T07:59:54.367153 #1] DEBUG -- omniauth: (linkedin) Callback phase initiated.
web-1            | OAuth2::AccessToken.from_hash: `hash` contained more than one 'token' key (["access_token", "id_token"]); using "access_token".
web-1            | E, [2024-07-02T07:59:55.736180 #1] ERROR -- omniauth: (linkedin) Authentication failure! invalid_credentials: OAuth2::Error, {"status":401,"serviceErrorCode":65601,"code":"REVOKED_ACCESS_TOKEN","message":"The token used in the request has been revoked by the user"}
web-1            | Processing by OmniauthCallbacksController#failure as HTML
web-1            |   Parameters: {"code"=>"AQS0fi3gwHvC1Dw-VkfwyZd9wXRzPx0fQVVkyFOua4AYQsOu7MhwvwIxWTlpWFG4XExwCVYt9NOky1USrmkQrfwlWea6xETgzcJmyvkK438UM8NHGfQNkkLSPeUQi_7WgZA_O0MKQVXB01LkcfXg28QHEJ02VBNT02MYbDY_R7IhSsaCOpg2pHJfZr2yalPWt14BZhGgJNgl4YkIlUE", "state"=>"e5756e8c7515f899c8f3adeb3a3e504fbbcb08ff9ddc75c0"}
web-1            | Redirected to http://127.0.0.1:3000/

我从哪里开始跟踪问题?

ruby-on-rails ruby linkedin-api openid omniauth
1个回答
0
投票

我发布这个问题已经有一段时间了,但一段时间后,我在 Golang 中找到了一个代码片段,它帮助我解决了这个问题,并且它起作用了。事实证明,对于 OpenID LinkedIN 身份验证功能,我们需要显式指定端点和身份验证方案,但任何地方都没有有关它的信息。

这是完成这项工作的代码:

config/initializers/devise.rb

  config.omniauth :linkedin, ENV.fetch('LINKEDIN_CLIENT_ID', nil) || Rails.application.credentials[:linkedin_id], ENV.fetch('LINKEDIN_CLIENT_SECRET', nil) || Rails.application.credentials[:linkedin_key], :scope => 'openid profile email', client_options: {
site: 'https://api.linkedin.com',
authorize_url: 'https://www.linkedin.com/oauth/v2/authorization',
token_url: 'https://www.linkedin.com/oauth/v2/accessToken',
auth_scheme: :request_body # This is the equivalent to oauth2.AuthStyleInParams in Go }

此后再也没有出现过任何问题。

© www.soinside.com 2019 - 2024. All rights reserved.