doorkeeper-gem/doorkeeper-grants_assertion

Is there anyway to set the grant_type for the assertion?

hadees opened this issue · 13 comments

According to the specification it looks like you have to set the grant_type to a URI and I don't see anyway of setting that. From what it looks like the grant_type right now is just assertion?

grant_type
      REQUIRED.  The format of the assertion as defined by the
      authorization server.  The value MUST be an absolute URI.
tsov commented

Yes, you are right! The format for grant_type needs to follow urn:ietf:params:oauth:<value>.
Look at the example request

This would be the relevant document for implementing the proper URI scheme

Just ran into this problem as well. This will be a bit difficult to fix because of the way Doorkeeper is set up. Take a look in /lib/doorkeeper/request.rb in the Doorkeeper gem. You'll see this (as of version 1.4.1):

require 'doorkeeper/request/authorization_code'
require 'doorkeeper/request/client_credentials'
require 'doorkeeper/request/code'
require 'doorkeeper/request/password'
require 'doorkeeper/request/refresh_token'
require 'doorkeeper/request/token'

module Doorkeeper
  module Request
    module_function

    def authorization_strategy(strategy)
      get_strategy strategy, Doorkeeper.configuration.authorization_response_types
    rescue NameError
      raise Errors::InvalidAuthorizationStrategy
    end

    def token_strategy(strategy)
      get_strategy strategy, Doorkeeper.configuration.token_grant_types
    rescue NameError
      raise Errors::InvalidTokenStrategy
    end

    def get_strategy(strategy, available)
      fail Errors::MissingRequestStrategy unless strategy.present?
      fail NameError unless available.include?(strategy.to_s)
      "Doorkeeper::Request::#{strategy.to_s.camelize}".constantize
    end
  end
end

Here you can see how Doorkeeper is just taking the grant_type, checking it against a whitelist, and then camelizing and constantizing it to load the proper strategy.

You'd need to change this code to check for grant types of the form urn:ietf:params:oauth:<value> and pass them to Doorkeeper:::Request::Assertion.

I'm looking into patching this, but I'm not sure how we could take over the urn:ietf:params:oauth:grant-type:* (final paragraph of RFC 7521, section 4.1) namespace without potentially trampling other doorkeeper extensions.

The current "Doorkeeper::Request::#{strategy.to_s.camelize}".constantize obviously won't work with URN-based grant types or cases where multiple URNs might map to the same strategy (say, urn:ietf:params:oauth:grant-type:assertion:facebook — what a mouthful), so perhaps Doorkeeper could provide a strategy registration table of sorts? Then we could register against /^urn:ietf:params:oauth:grant-type:assertion:(.*)/ and then capture to find our exact assertion

/cc @tute since this will probably need some help from the Doorkeeper side

tute commented

/cc @tute since this will probably need some help from the Doorkeeper side

Let me know how in doorkeeper's issue tracker, when you get the hand of it. Thanks for stepping up here!

I just put up a PR on the Doorkeeper side that's a start towards strategy / grant type registration. Take a look and see if it's what you had in mind.

If that PR were to be accepted, this gem would be able to include registration in lib/doorkeeper/grants_assertion.rb like so:

Doorkeeper::GrantFlow.register(
  :assertion,
  grant_type_matches: /^urn:ietf:params:oauth:grant-type:assertion:(.*)/,
  grant_type_strategy: Doorkeeper::Request::Assertion
)
tute commented

Are you sure we need to add this? If you add in doorkeeper.rb configuration file:

grant_flows %w(authorization_code client_credentials assertion), won't it just work? That will make the token grant type available, on current doorkeeper.

The problem is that there isn't a single "token" grant type, you're expected to use the URN in the spec and denote provider via that URN. You can reread my previous comment above for a more detailed analysis of the spec

tute commented

I see, thanks for your comments. Then we will need @reidab's PR indeed.

A solution that works today, though perhaps a tad hacky:

# in routes
  post "oauth/token", to: 'doorkeeper/tokens#create', grant_type: 'assertion', provider: 'facebook', constraints: lambda {|request|
    request.headers["rack.request.form_hash"]["grant_type"] == "urn:ietf:params:oauth:facebook"
  }
use_doorkeeper # needs to come after

Essentially, it overrides grant_type param to be assertion and provider to be facebook but only if actual grant_type is urn:ietf:params:oauth:facebook

Well, it's not a problem to introduce some mapper or builder class that will handle the logic of transforming grant type value from the request into Doorkeeper class. Just let me know if we need it or introduce a PR for review into Doorkeeper core

pr is more than welcomed

Great work, @nbulaj!