简体   繁体   English

如何将门卫访问令牌作为json返回

[英]How to return Doorkeeper access token as json

I am trying to create a log in system for an iOS app with a rails back end powered by devise and door keeper. 我正在尝试为iOS应用程序创建一个登录系统,其中导轨后端由设备和门卫提供支持。

I want to limit the number of network requests so don't want to have to get the token from credentials then get the user details as a separate request. 我想限制网络请求的数量,因此不希望必须从凭证中获取令牌,然后将用户详细信息作为单独的请求获取。

Here is my current attempt: 这是我目前的尝试:

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

However what is being returned is: 然而,返回的是:

{"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]"}}}

So the actual access_token key isn't being passed back to allow me to make future calls. 因此,实际的access_token键不会被传回以允许我进行将来的调用。 I can see that the token itself isn't returned in DoorKeeper::AccessToken.as_json , but token.as_json(:include=> token) still doesn't return it. 我可以看到在DoorKeeper::AccessToken.as_json没有返回令牌本身,但token.as_json(:include=> token)仍然没有返回它。

Does anyone know how to return the AccessToken, including the access token itself, as json? 有谁知道如何返回AccessToken,包括访问令牌本身,如json?

The way I handled this was to create a custom tokens controller and overriding the token request action. 我处理这个问题的方法是创建一个自定义令牌控制器并覆盖令牌请求操作。 There I could append custom stuff to 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

Just make sure that you point to this controller in routes.rb 只需确保在routes.rb指向此控制器routes.rb

# routes.rb
Rails.application.routes.draw do

  # Doorkeeper
  use_doorkeeper do
    controllers :tokens => 'custom_tokens'
  end

  # Your other routes here...

end

This is tested and it works, I am using it in my projects. 这是经过测试的,它可以工作,我在我的项目中使用它。

The way I managed to solve this was to create my own AccessToken class that overloads the as_json method to include the fields I wanted. 我设法解决这个问题的方法是创建我自己的AccessToken类,它重载as_json方法以包含我想要的字段。

eg 例如

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

If anyone has a better solution I'm all ears 如果有人有更好的解决方案,我会全力以赴

I know it's been a while this has been solved. 我知道这已经解决了一段时间了。 I recently wanted to implement the same behavior on my API and I relied on model association in order to achieve it : 我最近想在我的API上实现相同的行为,我依靠模型关联来实现它:

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

Then using serializers : 然后使用序列化器:

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

class AccessTokenSerializer < ActiveModel::Serializer
  attributes :token, :expires_in_seconds
end

You could simply return your data as : 您只需将数据返回为:

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

which will output a JSON that looks like : 这将输出一个看起来像这样的JSON:

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

Actually we can get access token with: 实际上我们可以获得访问令牌:

doorkeeper_token.token

you can include it in the json response so you don't need to edit anything inside doorkeeper itself. 你可以把它包含在json响应中,这样你就不需要在门卫本身内编辑任何东西了。
However, don't forget to add some conditionals before including it in the json response as it doesn't seem so good to always show it in the response. 但是,在将它包含在json响应中之前不要忘记添加一些条件,因为在响应中总是显示它似乎不太好。

Easy! 简单! you don't need to inherit from Doorkeeper::TokensController but you can if it suits better to your case: 你不需要从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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM