doorkeeper-gem / doorkeeper-jwt Goto Github PK
View Code? Open in Web Editor NEWJWT Token support for Doorkeeper
License: MIT License
JWT Token support for Doorkeeper
License: MIT License
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.
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
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?
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:
doorkeeper-jwt/lib/doorkeeper/jwt/config.rb
Lines 112 to 115 in 25223d6
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?
I would be really thankfull for any usage example or ideas on what might be wrong in my approach. Thanks in advance!
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.
Can we release a new version to rubygems?
I don't know how to make this gem work with multimple models for auth, how do I differentiate when generating the token?
# 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
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.
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 :)
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.
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.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
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
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.
There have been a lot of changes / bugfixes since jwt 1.5.6.
It would be better to update this dependency.
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
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.