Search code examples
ruby-on-railsherokuoauthdoorkeeper

Overriding Doorkeepers AccessToken Controller does not seem to work in Heroku


The responsible code is not environment specific yet it works locally but not in production:

POST request to my app's /oauth/token should redirect to a controller overriding default Doorkeeper Token response as shown in the first route

routes.rb

require 'api_constraints'

Rails.application.routes.draw do
  use_doorkeeper do
    controllers :tokens => 'access_token'
  end
  # Other routes
end

The above works fine on a local server however in production[Heroku] this seems to be ignored and is instead routed to default doorkeeper class for no apparent reason. Therefore the response with the token does not contain the user id.

REQUEST TO "https://myapp.herokuapp.com/oauth/token"

POST /oauth/token HTTP/1.1
Host: myapp.herokuapp.com
Cache-Control: no-cache
Postman-Token: xxxxxxxx
Content-Type: application/x-www-form-urlencoded

grant_type=password&email=john%40gmail.com&password=password

THIS RETURNS JSON RESPONSE:

{
"access_token": "XXXXXX",
"token_type": "bearer",
"created_at": 1466340696
}

The same request to "http://localhost:3000/oauth/token" returns

{
"access_token": "XXXXXX",
"token_type": "bearer",
"created_at": 1466341435,
"id": 1
}

with the correctly included user_id. I'm not sure if there is some kind of a cache issue which makes my production server use the old routes file. I've tried restarting dynos and push further changes to to heroku master however this did not resolve the issue.

access_token_controller

class AccessTokenController < 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.where(response.token.resource_owner_id).first 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[:id] = response.token.resource_owner_id
      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

Apologies for any confusion and thank you in advance for any assistance with this.


Solution

  • Got it to work at last.

    For reasons unknown to me Postgres was not finding the user causing it to be nil and the subsequent if statement unless user.nil? was not executed, hence why the resource_owner_id was not attaching. However locally with SQLite3 this was not an issue. I'm sure there is something very basic I'm missing here with development on Heroku or PG in general. I would appreciate any advise, if I find anything myself I'll post it here also.

    Working version of the access token controller

    class AccessTokenController < Doorkeeper::TokensController
    
      # Overriding create action
      # POST /oauth/token
      def create
        response = strategy.authorize
        body = response.body
    
        if response.status == :ok
          # Return user id
          body[:id] = response.token.resource_owner_id unless nil
        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