如何返回门卫访问令牌json



我正在尝试创建一个iOS应用程序的登录系统与rails后端由设计和门管理员供电。

我想限制网络请求的数量,所以不想从凭据中获取令牌,然后作为单独的请求获取用户详细信息。

这是我当前的尝试:

token = Doorkeeper::AccessToken.create!(application_id: @application_id,
    resource_owner_id: current_user.id, :expires_in => 168.hours)
puts token.token
render :json => {:user => current_user, :token => token.as_json(:include=> token)}, 
    status: :ok, location: :users

但是返回的是:

{"user":{"id":2,"email":"user3@test.com","created_at":"2014-06-12T17:25:12.000Z",
"updated_at":"2014-06-13T12:20:18.536Z",
"firstName":"user","lastName":"test","subscription":null},
"token":{"resource_owner_id":2,"scopes":[],"expires_in_seconds":604800,
"application":{"uid":"[Filtered]"}}}

因此,实际的access_token密钥没有被传递回来,以允许我进行未来的调用。我可以看到在DoorKeeper::AccessToken.as_json中没有返回令牌本身,但是token.as_json(:include=> token)仍然没有返回它。

是否有人知道如何返回AccessToken,包括访问令牌本身,作为json?

我处理这个问题的方法是创建一个自定义令牌控制器并覆盖令牌请求操作。我可以在response.

中添加自定义内容。
# app/controllers/custom_tokens_controller.rb
class CustomTokensController < Doorkeeper::TokensController
  # Overriding create action
  # POST /oauth/token
  def create
    response = strategy.authorize
    body = response.body
    if response.status == :ok
      # User the resource_owner_id from token to identify the user
      user = User.find(response.token.resource_owner_id) rescue nil
      unless user.nil?
        ### If you want to render user with template
        ### create an ActionController to render out the user
        # ac = ActionController::Base.new()
        # user_json = ac.render_to_string( template: 'api/users/me', locals: { user: user})
        # body[:user] = Oj.load(user_json)
        ### Or if you want to just append user using 'as_json'
        body[:user] = user.as_json
      end
    end
    self.headers.merge! response.headers
    self.response_body = body.to_json
    self.status        = response.status
  rescue Doorkeeper::Errors::DoorkeeperError => e
    handle_token_exception e
  end
end

确保在routes.rb

中指向这个控制器
# routes.rb
Rails.application.routes.draw do
  # Doorkeeper
  use_doorkeeper do
    controllers :tokens => 'custom_tokens'
  end
  # Your other routes here...
end

这是测试和它的工作,我在我的项目中使用它

我设法解决这个问题的方法是创建我自己的AccessToken类,重载as_json方法以包含我想要的字段。

class AccessToken < Doorkeeper::AccessToken
   def as_json(options={})
      {
        :token => self.token,
        #:resource_owner_id => self.resource_owner_id,
        #:scopes => self.scopes,
        :created_at => self.created_at,
        :expires_in_seconds => self.expires_in_seconds,
        #:application => { :uid => self.application.uid }
      }
   end
end

如果有人有更好的解决方案,我洗耳恭听

我知道这已经解决了一段时间了。我最近想在我的API上实现相同的行为,我依靠模型关联来实现它:

class User < ActiveRecord::Base
  has_one :token, -> { order 'created_at DESC' }, class: Doorkeeper::AccessToken, foreign_key: :resource_owner_id
end

然后使用序列化器:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :email
  has_one :token, serializer: AccessTokenSerializer
end
class AccessTokenSerializer < ActiveModel::Serializer
  attributes :token, :expires_in_seconds
end

您可以简单地将数据返回为:

class DummyController < ApplicationController
  def dummy
    respond_with current_user, status: :ok
  end
end

将输出如下JSON:

{
    "id": 17,
    "name": "Chuck Norris",
    "email": "chuck@norr.is",
    "token": {
        "token": "c62af258f2d1ac816f65606a2a8413b8e0c2ad5b4434f9c75b56765f54ee627b",
        "expires_in_seconds": "5427"
    }
}

实际上我们可以使用:

doorkeeper_token.token

你可以把它包含在json响应中,这样你就不需要在doorkeeper本身里面编辑任何东西。
但是,不要忘记在json响应中包含它之前添加一些条件,因为总是在响应中显示它似乎不太好。

轻松!您不需要继承Doorkeeper::TokensController,但如果它更适合您的情况,您可以:

class CustomController < ApplicationController
  def create
    ...
    access_token = Doorkeeper::AccessToken.create!(application_id: @application_id, resource_owner_id: current_user.id, :expires_in => 168.hours)
    render json: Doorkeeper::OAuth::TokenResponse.new(access_token).body
  end
end

最新更新