现在我已经寻找两天以上的解决方案来解决以下问题。我有一个EmberJS客户端JavaScript应用程序,它使用我的服务器端Rail RESTful API。授权是通过访问令牌完成的。
现在我想让用户也能使用Google、Twitter等OAuth2登录。Discourse使用OmniAuth进行第三方登录,但OmniAuth需要服务器端会话。因为我构建了一个RESTful和无状态API,所以我不想在服务器上使用会话。因此,我决定自己构建它,并借助Google+ Sign-In for server-side apps的帮助,但那里的示例也使用了会话。
是否有人对类似问题有解决方案或解决我的问题的提示? 编辑1 因为OmniAuth在我的设置中不适用,所以我开始创建一个自己的第三方OAuth2登录实现,参照Google的帮助。目前一切都运行良好。但是我没有实现Google网站上提到的标题
现在我想让用户也能使用Google、Twitter等OAuth2登录。Discourse使用OmniAuth进行第三方登录,但OmniAuth需要服务器端会话。因为我构建了一个RESTful和无状态API,所以我不想在服务器上使用会话。因此,我决定自己构建它,并借助Google+ Sign-In for server-side apps的帮助,但那里的示例也使用了会话。
是否有人对类似问题有解决方案或解决我的问题的提示? 编辑1 因为OmniAuth在我的设置中不适用,所以我开始创建一个自己的第三方OAuth2登录实现,参照Google的帮助。目前一切都运行良好。但是我没有实现Google网站上提到的标题
1. 创建一个反伪造状态令牌
下解释的CSRF保护。我的问题是,如何在不使用会话的情况下存储此CSRF令牌。将其存储在数据库中并在稍后从Google的回调请求中查找是否足够?
编辑2
我按照这个railscast。如果用户想要使用外部oauth提供者进行登录,则有三种可能的情况:
- 用户已经使用外部oauth进行注册,然后获得了Doorkeeper访问令牌。
- 用户已经有一个账户,但是之前没有使用外部提供商进行登录。在oauth流程之后,我们只需要为这个用户创建一个新的身份验证。
- 用户没有账户,现在尝试使用外部提供商进行登录。在这里,我们必须将用户重定向到注册页面,我们也可以使用oauth提供者的信息预填写注册表单,但在用户点击注册按钮之前,我们必须保存身份验证。
我的问题是,如何在REST API中保存这些信息(身份验证、oauth2 csrf-token)的最佳实践,而不使用会话。我必须将这些信息保存在服务器上,因为用户不应该有在客户端上操纵它们的可能性。
也许我还应该为令牌和会话身份验证与Ember应用程序的优缺点以及可能的解决方案创建一个新问题?
这是我的身份验证控制器:
class Api::V1::AuthenticationsController < ApplicationController
def oauth
# redirect to google/twitter/...
login_at(params[:provider])
end
def callback
# callback from provider
provider = params[:provider]
if @user = login_from(provider)
doorkeepter_token = Doorkeeper::AccessToken.create!(:resource_owner_id => @user.id)
@data = {
access_token: doorkeepter_token.token,
user: @user
}
render 'oauth/complete'
else
# user has no account, create a new one
@user = User.new
@user.email = @user_hash[:user_info]['email']
@user.authentications.build(:uid => @user_hash[:uid], :provider => params[:provider])
@user.oauth_pending!
if @user.save
doorkeepter_token = Doorkeeper::AccessToken.create!(:resource_owner_id => @user.id)
@data = {
access_token: doorkeepter_token.token,
user: @user,
errors: @user.errors
}
render 'oauth/complete'
else
render 'oauth/error'
end
end
end
end