我遇到了同样的问题,我找到了一个 hacky 但有趣的解决方案:-)
(我使用了所有 OAuth 逻辑devise
和omniauth-linkedin
gems。)
在我的应用程序中,您可以开始填写表格,您需要先登录才能保存。我需要一种在不丢失表单数据和不重新加载页面的情况下记录用户的方法。
当用户访问该页面时,他会获得一个唯一的 uuid 来识别他。此 uuid 用于启动 websocket 连接,因此我可以稍后将数据直接推送到此选项卡。
我使用 javascript 在新选项卡中打开 LinkedIn OAuth,window.open()
因此我可以使用window.close()
.
您可以将其他参数传递给 OAuth 身份验证,我传递了唯一的 uuid,因此我可以在身份验证成功时恢复它,并且使用此 uuid,我可以通过 websocket 发送消息来通知第一个选项卡(在我的应用程序中,我发送用户更新当前用户状态的信息)。
身份验证后,我将用户重定向到仅包含window.close()
.
在 Rails 中设置 LinkedIn OAuth
您将需要一个功能性的 Omniauth/Devise 身份验证工作。
omniauth_callback_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def linkedin
user = User.connect_to_linkedin(request.env["omniauth.auth"], current_user)
guest_guid = request.env["omniauth.params"]["guestGuid"]
if user.persisted?
ActionCable.server.broadcast("guest:#{guest_guid}", { user: UserSerializer.new(user).to_h })
sign_in(user)
redirect_to landing_home_index_path
end
end
end
用户.rb
def self.connect_to_linkedin(auth, signed_in_resource = nil)
user = User.where(provider: auth.provider, linkedin_uid: auth.uid).first
if user
return user
else
registered_user = User.where(email: auth.info.email).first
if registered_user
return registered_user
else
user = User.create(lastname: auth.info.last_name, firstname: auth.info.first_name,
provider: auth.provider, linkedin_uid: auth.uid, email: auth.info.email,
linkedin_token: auth.credentials.token, linkedin_secret: auth.credentials.secret,
linkedin_picture: auth.extra.raw_info.pictureUrl, password: Devise.friendly_token[0, 20])
end
end
end
路线.rb
devise_for :users, controllers: {
omniauth_callbacks: "omniauth_callbacks",
sessions: "users/sessions"
}
现在,如果您访问/users/auth/linkedin
,您将能够使用 LinkedIn OAuth 登录/创建用户。
Websocket 连接
create_job_offer_channel.rb
class CreateJobOfferChannel < ApplicationCable::Channel
def subscribed
stream_from "guest:#{params[:guest]}"
end
def unsubscribed
end
def receive(data)
ActionCable.server.broadcast("guest:#{params[:guest]}", data)
end
end
create_job_offer.js.coffee
class window.CreateJobOffer
constructor: (params) ->
self = @
@channel = App.cable.subscriptions.create {
channel: "CreateJobOfferChannel", guest: params["guest"]
}, self
@onReceive = params["onReceive"] || null
received: (data) =>
@onReceive(data) if @onReceive
反应前端
链接到 LinkedIn OAuth(带有设计和omniauth)
<div className="btn-linked-in">
<i className="fa fa-linkedin-square"></i>
<span onClick={() => open(`/users/auth/linkedin?guestGuid=${guestGuid}`)}>
Login with LinkedIn
</span>
</div>
希望这有帮助:)