Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The authorization should not be triggered when a previous expired token is provided and reuse_access_token is enabled. #1138

Closed
thromera opened this issue Aug 29, 2018 · 12 comments

Comments

@thromera
Copy link
Contributor

thromera commented Aug 29, 2018

Steps to reproduce

Flag reuse_access_token is turned on. Whenever the access_token expires, instead of silently renewing the access_token, the user is redirected to the authorization/new page where she has to click on "Accept" or "Decline". (The user approved the application previously, and gave the expired access token in the request).

The incriminating commit: c87b13c#diff-1282d211312f992c2a614d1f4a6302fe - especially the token.accessible? check.

  • it's not mentioned in the Changelog for 5.0.0 while it should've been, it's a change of behavior
  • It now triggers an authorization window whenever my access_token is expired, while I specified to reuse_access_token (so the renewal should be invisible, the user should not have to approve again the application).

doorkeeper.rb:

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
    sign_out(current_user) unless current_user&.is_a?(Admin)
    session[:user_return_to] = request.fullpath
    current_user&.is_a?(Admin) ? current_user : redirect_to(new_user_session_url)
  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
    current_user.is_a?(Admin) || redirect_to(new_user_session_url)
  end

  # resource_owner_from_credentials do |routes|
  #   admin = Admin.find_for_database_authentication(email: params[:username])
  #   if admin && admin.valid_for_authentication? { admin.valid_password?(params[:password]) }
  #     admin
  #   end
  # 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 'ActionController::Base'

  # 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/ht§l/rfc6819#section-4.4.3
  #
  grant_flows %w(implicit)

  # 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?
  # end

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

System configuration

Doorkeeper 5.0.0

@nbulaj
Copy link
Member

nbulaj commented Aug 29, 2018

Hi @Erowlin . I'm terribly busy right now, would you like to submit a revert fix for this?

@thromera
Copy link
Contributor Author

thromera commented Aug 30, 2018

Sure, do you confirm that it is RFC compliant?

@nbulaj
Copy link
Member

nbulaj commented Sep 6, 2018

As far as I remember RFC 6749 says nothing about token reuse, so this functionality looks like an extension to OAuth protocol. Fix me if I'm wrong. This changes were done during the investigation of expired tokens issues, and now looks more like a bug.

@nbulaj
Copy link
Member

nbulaj commented Sep 19, 2018

Hi @Erowlin . Would you like to propose a fix? I have some troubles with a free time now, so don't sure when I will be able to fix it myself

nbulaj added a commit that referenced this issue Sep 20, 2018
@nbulaj
Copy link
Member

nbulaj commented Sep 20, 2018

Hi @Erowlin . I have 10 minutes of free time :D
Could you please check this branch with the changes related to this issue? https://github.com/doorkeeper-gem/doorkeeper/compare/revert-expiration-check-for-matching-token

Thanks

@thromera
Copy link
Contributor Author

Thanks for your time, sorry for my silence radio, busy times here as well.

I'm checking now.

@thromera
Copy link
Contributor Author

Ok, it seems to be fixed, however, 1 behavior still not fixed:

  • When I update manually my expires_in in 1 second, a new token is issued instead of renewing the actual token (And extending the expires_in). Is it the intended behavior?

(It's my localhost, don't worry).
image

@nbulaj
Copy link
Member

nbulaj commented Sep 20, 2018

I think this is related to this line

@thromera
Copy link
Contributor Author

thromera commented Sep 20, 2018 via email

@nbulaj
Copy link
Member

nbulaj commented Sep 20, 2018

I think that reuse access token currently works fine - it protects from creating new tokens before old one becomes expired. Please, read the orinal PR and issue: #383 and #387 . It doesn't work as "update old token expiration date instead of creating new token" . Also there are refresh token strategy..

@thromera
Copy link
Contributor Author

thromera commented Sep 20, 2018 via email

@nbulaj nbulaj closed this as completed in 72531d3 Sep 21, 2018
nbulaj added a commit that referenced this issue Sep 21, 2018
…for-matching-token

[#1138] Revert matching token changes for Authorization
@nbulaj
Copy link
Member

nbulaj commented Dec 3, 2021

NOTICE: #1542 will break the topic once again after release.

reuse_access_token doesn't mean Doorkeeper will always use the same database record and just update it expiration time. It means that Doorkeeper will just try to find an active token issued for the same application and resource owner with the same set of scopes. If it's not found - user should authorize.

If you need always use the same access token record (which is insecure by design) - use an infinite TTL (set expiration time to nil in the config).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants