Giter VIP home page Giter VIP logo

doorkeeper-jwt's People

Contributors

bekicot avatar christopherhein avatar chriswarren avatar dependabot-preview[bot] avatar jdoconnor avatar jpickwell avatar markmurphy avatar nbulaj avatar nickstanish avatar pacop avatar sinsoku avatar travisofthenorth avatar uxtronaut avatar wahlg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

doorkeeper-jwt's Issues

upgrade version of jwt requirement

Currently targeted version of jwt gem is too old. This causes incompatibility with my other gems. I'm sure many others will do soon. or already.

Can we upgrade so we can use it with v2.1.x branch of JWT? Currently I tested against 2.1.0 and it just works.

Implement #valid_doorkeeper_token? to support #doorkeeper_authorize!

In a doorkeeper-protected application, a controller could look like this:

class Api::V1::MyController < ApplicationController
  before_action :doorkeeper_authorize!, only: %i[show create destroy]
  ...
end

However, when using Doorkeeper::JWT to generate access tokens this commonly used pattern breaks since a Doorkeeper::JWT token is just a string...

The before_action :doorkeeper_authorize! way of authenticating calls breaks here, because it expects a doorkeeper_token to implement the acceptable? method:
https://github.com/doorkeeper-gem/doorkeeper/blob/4dc432c74a424c85e141b131939faafa98a916fc/lib/doorkeeper/rails/helpers.rb#L16

I have only just started my sideproject and Doorkeeper is relatively new to me, but would it work if Doorkeeper::JWT tokens extend the token mixin?
https://github.com/doorkeeper-gem/doorkeeper/blob/v5.2.1/lib/doorkeeper/models/access_token_mixin.rb#L275

Is it possible to use multiple encryption methods?

I see in the that the encryption_method takes a single string to tell doorkeeper what encryption to use on the JWT. Is there a way I can handle multiple encryption methods? Having an RS and a HS encryption?

Default token_payload doesn't return a random hex value

The README indicates that if the token_payload is left unset, then it:

Defaults to a randomly generated token in a hash: { token: "RANDOM-TOKEN" }

However, that is not this library's current behavior.

The following is what is actually generated if you fail to set a token_payload:

{
  "token": "#<Method: SecureRandom.hex>"
}

The token payload's default value does not appear to be getting called (the hex method reference is simply being converted to a string) and no random hash is generated:

option(
:token_payload,
default: proc { { token: SecureRandom.method(:hex) } }
)

Usage example

Hello!

I'm trying to use that gem in my application but i can't do that. I actually don't even know if i'm doing it right. Anyway, i have a jwt token generated by ruby-jwt, using secret key of my rails app.

Sending a requests to my oauth2 api with a header Authorization: Bearer <my token> results in 401. What's weird - i can see in the server console that doorkeeper tries to find that token i'm sending in the doorkeeper tables and, if i understand JWT properly, that should not happen at all?

image

I would be really thankfull for any usage example or ideas on what might be wrong in my approach. Thanks in advance!

  • doorkeeper 3.1.0
  • doorkeeper-jwt 0.1.4

Using example config fails with 'Doorkeeper::JWT does not respond to .generate'

When using the example config from Readme - token POST request fails with

{
    "error": "Doorkeeper::JWT does not respond to `.generate`.",
    "error_description": "The authorization server encountered an unexpected condition which prevented it from fulfilling the request."
}

I still have no clue why this should fail though.

Accessing nil application in application_secret method raises NoMethodError `[]`

    # doorkeeper-jwt.rb
     def application_secret(opts)
        opts = { application: {} }.merge(opts)
       # This line raises an error if opts contains application: nil
        return opts[:application][:secret] if opts[:application][:secret]
        fail "JWT `use_application_secret` config set, but no app secret set."
      end

doorkeeper-gem/doorkeeper#943

To provide a bit more context, I had set use_application_secret true and then tried to use the oauth resource owner password credentials grant without passing a client_id.

ActiveRecord::RecordInvalid already taken (token already exists)

Hi :)

while using this access token generator, the second time my client try to authorize against my oauth provider, I get a validation error from Rails, telling me that the token is already taken. This does not happen when I'm using the default doorkeeper token generator.

Doorkeeper::AccessToken Exists (0.3ms)  SELECT  1 AS one FROM "oauth_access_tokens" WHERE "oauth_access_tokens"."token" = $1 LIMIT $2  [["token", "TOKENTOKEN( I deleted for privacy)"], ["LIMIT", 1]]
   (0.2ms)  ROLLBACK
Completed 422 Unprocessable Entity in 353ms



ActiveRecord::RecordInvalid (Validazione fallita: Token è già presente):

activerecord (5.1.1) lib/active_record/validations.rb:78:in `raise_validation_error'
activerecord (5.1.1) lib/active_record/validations.rb:50:in `save!'

I think it happens because the JWT is not unique. What am I doing wrong? Is this the right place to post or should I ask directly in doorkeeper github page?

I'm using these versions:

doorkeeper-jwt (0.2.0)
doorkeeper (4.2.6)

And this is my doorkeeper configuration:

Doorkeeper.configure do
  # Change the ORM that doorkeeper will use (needs plugins)
  orm :active_record

  # This block will be called to check whether the resource owner is authenticated or not.
  resource_owner_authenticator do
    # Put your resource owner authentication logic here.
    # Example implementation:
    #   User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
    current_user || warden.authenticate!(:scope => :user)
  end

  # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
  # admin_authenticator do
  #   # Put your admin authentication logic here.
  #   # Example implementation:
  #   Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
  # end

  # Authorization Code expiration time (default 10 minutes).
  # authorization_code_expires_in 10.minutes

  # Access token expiration time (default 2 hours).
  # If you want to disable expiration, set this to nil.
  # access_token_expires_in 2.hours

  # Assign a custom TTL for implicit grants.
  # custom_access_token_expires_in do |oauth_client|
  #   oauth_client.application.additional_settings.implicit_oauth_expiration
  # end

  # Use a custom class for generating the access token.
  # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
  access_token_generator '::Doorkeeper::JWT'

  # The controller Doorkeeper::ApplicationController inherits from.
  # Defaults to ActionController::Base.
  # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
  # base_controller 'ApplicationController'

  # Reuse access token for the same resource owner within an application (disabled by default)
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
  # reuse_access_token

  # Issue access tokens with refresh token (disabled by default)
  # use_refresh_token

  # Provide support for an owner to be assigned to each registered application (disabled by default)
  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
  # a registered application
  # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
  # enable_application_owner confirmation: false

  # Define access token scopes for your provider
  # For more information go to
  # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
  # default_scopes  :public
  # optional_scopes :write, :update

  # Change the way client credentials are retrieved from the request object.
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
  # Check out the wiki for more information on customization
  # client_credentials :from_basic, :from_params

  # Change the way access token is authenticated from the request object.
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
  # falls back to the `:access_token` or `:bearer_token` params from the `params` object.
  # Check out the wiki for more information on customization
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param

  # Change the native redirect uri for client apps
  # When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
  # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
  # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
  #
  # native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'

  # Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
  # by default in non-development environments). OAuth2 delegates security in
  # communication to the HTTPS protocol so it is wise to keep this enabled.
  #
  # force_ssl_in_redirect_uri !Rails.env.development?

  # Specify what grant flows are enabled in array of Strings. The valid
  # strings and the flows they enable are:
  #
  # "authorization_code" => Authorization Code Grant Flow
  # "implicit"           => Implicit Grant Flow
  # "password"           => Resource Owner Password Credentials Grant Flow
  # "client_credentials" => Client Credentials Grant Flow
  #
  # If not specified, Doorkeeper enables authorization_code and
  # client_credentials.
  #
  # implicit and password grant flows have risks that you should understand
  # before enabling:
  #   http://tools.ietf.org/html/rfc6819#section-4.4.2
  #   http://tools.ietf.org/html/rfc6819#section-4.4.3
  #
  # grant_flows %w(authorization_code client_credentials)

  # Under some circumstances you might want to have applications auto-approved,
  # so that the user skips the authorization step.
  # For example if dealing with a trusted application.
  skip_authorization do |resource_owner, client|
    # client.superapp? or resource_owner.admin?
    true # Do not show "Authorize required" page to user
  end

  # WWW-Authenticate Realm (default "Doorkeeper").
  # realm "Doorkeeper"
end

Doorkeeper::JWT.configure do
  # Set the payload for the JWT token. This should contain unique information
  # about the user.
  # Defaults to a randomly generated token in a hash
  # { token: "RANDOM-TOKEN" }

  token_payload do |opts|
    user = User.find(opts[:resource_owner_id])

    {
      user: {
        id: user.id,
        email: user.email
      }
    }
  end

  # Optionally set additional headers for the JWT. See https://tools.ietf.org/html/rfc7515#section-4.1
  token_headers do |opts|
    {
      kid: opts[:application][:uid]
    }
  end

  # Use the application secret specified in the Access Grant token
  # Defaults to false
  # If you specify `use_application_secret true`, both secret_key and secret_key_path will be ignored
  use_application_secret false

  # Set the encryption secret. This would be shared with any other applications
  # that should be able to read the payload of the token.
  # Defaults to "secret"
  secret_key "MY-SECRET"

  # If you want to use RS* encoding specify the path to the RSA key
  # to use for signing.
  # If you specify a secret_key_path it will be used instead of secret_key
  # secret_key_path "path/to/file.pem"

  # Specify encryption type. Supports any algorithim in
  # https://github.com/progrium/ruby-jwt
  # defaults to nil
  encryption_method :hs256
end

Thanks :)

How does one test whether Doorkeeper-JWT works with a certain version of Doorkeeper?

The readme currently states "Confirmed to work with Doorkeeper 2.2.x - 4.x. Untested with later versions of Doorkeeper."

Please describe how you confirmed this, so that the community can confirm that Doorkeeper-JWT works with other versions of Doorkeeper. Was there manual testing performed? Could you please describe what the manual test suite consists of, and anything to look out for that might entail modifying the manual test suite for newer versions of Doorkeeper?

Thanks.

Can't save JWT token Doorkeeper::AccessToken. token length too long in mysql

Hi,

Having issue when creating access token. It is trying to save the entire token to DB. Which result in
column too long error in MySQL.

Doorkeeper config

Doorkeeper.configure do
  orm :active_record
  resource_owner_authenticator do
    current_user || warden.authenticate!(scope: :user)
  end

  admin_authenticator do
    if current_user
      unless current_user.is_admin?
        redirect_to root_url
      end
    else
      redirect_to new_user_session_path
    end
  end

  access_token_generator '::Doorkeeper::JWT'

  enforce_configured_scopes
  default_scopes  :read
  optional_scopes :write, :update
end

JWT config

Doorkeeper::JWT.configure do
  token_payload do |opts|
    user = User.find(opts[:resource_owner_id])

    {
      iss: 'Test',
      iat: Time.current.utc.to_i,

      # @see JWT reserved claims - https://tools.ietf.org/html/draft-jones-json-web-token-07#page-7
      jti: SecureRandom.uuid,

      user: {
        id: user.id,
        email: user.email
      }
    }
  end

  # Optionally set additional headers for the JWT. See
  # https://tools.ietf.org/html/rfc7515#section-4.1
  token_headers do |opts|
    { kid: opts[:application][:uid] }
  end
  use_application_secret true
  encryption_method :hs512
end

When I try to get access token, its throwing MySQL error

Mysql2::Error: Data too long for column 'token' at row 1

Index on "index_oauth_access_tokens_on_token" fails on Postgres

When a user creates an oauth token, the following error is being generated by Postgres:

ERROR: index row size [NUMBER] exceeds maximum [NUMBER] for index "index_oauth_access_tokens_on_token" HINT: Values larger than [NUMBER]/[NUMBER] of a buffer page cannot be indexed. Consider a function index of an MD5 hash of the value, or use full text indexing. 

The error seems to occur due to the btree index used on token, as btree indexes can't handle data with more that 2713 bytes.

This doesn't seem to occur using doorkeeper without doorkeeper-jwt.

I've resolved the issue by replacing the hashing function of the index with an md5 function, which I've detailed on the doorkeeper wiki.

There should probably be a reference to the issue over here, for the benefit of future doorkeeper-jwt users. I'm happy for you to either reference the doorkeeper wiki, or to copy the solution - up to you.

World writable executable files (console, setup)

When doing a recent security review we discovered the bin/console and bin/setup are world writable on a default install. Both on Ubuntu and MacOS.

# MacOS
$ gem install --install-dir ./test/ doorkeeper-jwt:0.4.1
Fetching jwt-2.4.1.gem
Successfully installed jwt-2.4.1
Fetching doorkeeper-jwt-0.4.1.gem
Successfully installed doorkeeper-jwt-0.4.1
Parsing documentation for jwt-2.4.1
Installing ri documentation for jwt-2.4.1
Parsing documentation for doorkeeper-jwt-0.4.1
Installing ri documentation for doorkeeper-jwt-0.4.1
Done installing documentation for jwt, doorkeeper-jwt after 0 seconds
2 gems installed

$ ls -l test/gems/doorkeeper-jwt-0.4.1/bin
total 16
-rwxrwxrwx  1 richard  wheel  372 13 Jun 08:52 console
-rwxrwxrwx  1 richard  wheel  125 13 Jun 08:52 setup

Looking at the source code the files aren't world writable, so I'm guessing it's something to do with the gem packaging. But from hunting around I can't see what's making these files world writable.

# Git checkout
$ ls -l bin
total 16
-rwxr-xr-x  1 richard  staff  372 27 May 10:36 console
-rwxr-xr-x  1 richard  staff  125 27 May 10:36 setup

For what it's worth my umask is the standard on MacOS.

$ umask
022

$ umask -S
u=rwx,g=rx,o=rx

Application-based signatures

I'd prefer not to have a single secret or key-pair shared across all the applications using JWT tokens.

I've looked at a few other implementations of JWT, including external services like Auth0. A lot of these have some type of application/partner reference they set in the aud claim and then lookup a secret based on this.

Is this something you're either looking at doing or would accept as a pull request? The application UID set in the aud and the application secret used to sign the message when using HS* encryption and the application secret used as the public key when using RS* encryption?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.