Disable OAuth access token reuse feature
GitLab currently returns the same OAuth access token to clients that authenticate with an application as long as the access token is still valid.
Per Doorkeeper configuration documentation:
This option protects your application from creating new tokens before old valid one becomes expired so your database doesn't bloat. Keep in mind that when this option is enabled Doorkeeper doesn't update existing token expiration time, it will create a new token instead if no active matching token found for the application, resources owner and/or set of scopes. Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
This behavior causes problems for some clients who may need to request a token multiple times and store the access tokens independently (see original description below for customer use-case and rationale)
One concern about changing this behavior is the potential for access token record bloat in the database. Since refresh tokens currently have no expiration, unless they are actually used, it could be difficult to clean up records. I think automatic reuse detection might make it easier to determine whether a record can be cleaned up.
Original description
Insight
Our technology partner, Postman, were able to find the root cause for the token issue, but they need help with a resolution.
The problem arises due to the way in which GitLab (GL) issues the access and refresh token pairs:
When the user first completes the OAuth flow, GL will issue AC1 and RT1 to the user, with AC1 being valid for 2 hrs.
If the user does the OAuth flow again while the access token is still valid, GL will issue the same pair of tokens again (AC1 and RT1). This will cause our 2 different integrations to point to the same token pairs stored in 2 different rows.
If the user refreshes the token for the 1st integration, the refresh token and the access token (RT1 and AC1) will be invalidated and GL will issue AC2 and RT2, which the 1st integration will point to. However, our 2nd integration is still pointing to AC1 and RT1 which is now invalid.
Is there any way to force GL to issue new AC and RT pairs every-time the OAuth flow is done via the OAuth endpoints?
Per @dblessing, this happens because we use the setting reuse_access_tokens
Supporting evidence
The Use Case: Postman lets users create multiple "APIs", and each API can be linked to a separate repository on GitLab. If one user configures integrations between multiple Postman API<>Gitlab Repo pairs, we see a situation where one integration refreshes its access token, but this operation renders the other refresh tokens invalid.
All of this is happening with the same OAuth2 application (the one owned by Postman) and for the same GitLab user ID, with the same set of requested scopes.
Separately, can you confirm that asking for different scopes will forcibly issue a different access token?
Action
Per @dblessing - Now that we expire tokens I wonder if we are in a better position to stop re-using tokens. My only concern would be we may still be unable to purge expired tokens because the refresh token is still valid infinitely. To delete an expired token would also negate the ability to refresh the token.
I'm struggling in my own mind to determine what the ideal approach is - generate unique tokens for each grant, or have integrations like Postman create distinct OAuth applications.
Resources
Tasks
-
Assign this issue to the appropriate Product Manager, Product Designer, or UX Researcher. -
Add the appropriate Group(such as~"group::source code") label to the issue. This helps identify and track actionable insights at the group level. -
Link this issue back to the original research issue in the GitLab UX Research project and the Dovetail project. -
Adjust confidentiality of this issue if applicable