Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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":"[email protected]","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. 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.

Does anyone know how to return the AccessToken, including the access token itself, as json?

like image 511
AndyRyan Avatar asked Dec 25 '22 08:12

AndyRyan


1 Answers

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
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.

like image 197
Jakob Cvetko Avatar answered Jan 10 '23 22:01

Jakob Cvetko