diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index c3e6503a4b..bf40143de9 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -49,6 +49,13 @@ Doorkeeper.configure do context.scopes.exists?('offline_access') end + after_successful_strategy_response do |request, _response| + if request.is_a? Doorkeeper::OAuth::RefreshTokenRequest + Web::PushSubscription.where(access_token_id: request.refresh_token.id).update!(access_token_id: request.access_token.id) + SessionActivation.where(access_token_id: request.refresh_token.id).update!(access_token_id: request.access_token.id) + end + 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" diff --git a/spec/fabricators/application_fabricator.rb b/spec/fabricators/application_fabricator.rb index 272821304c..072f355bfa 100644 --- a/spec/fabricators/application_fabricator.rb +++ b/spec/fabricators/application_fabricator.rb @@ -3,5 +3,5 @@ Fabricator(:application, from: Doorkeeper::Application) do name 'Example' website 'http://example.com' - redirect_uri 'http://example.com/callback' + redirect_uri 'urn:ietf:wg:oauth:2.0:oob' end diff --git a/spec/requests/oauth/token_spec.rb b/spec/requests/oauth/token_spec.rb index 04e3d3fc88..27bbbe7ac5 100644 --- a/spec/requests/oauth/token_spec.rb +++ b/spec/requests/oauth/token_spec.rb @@ -105,6 +105,53 @@ RSpec.describe 'Managing OAuth Tokens' do end end end + + context "with grant_type 'refresh_token'" do + let(:grant_type) { 'refresh_token' } + + let!(:user) { Fabricate(:user) } + let!(:application) { Fabricate(:application, scopes: 'read offline_access') } + let!(:access_token) do + Fabricate( + :accessible_access_token, + resource_owner_id: user.id, + application: application, + # Even though the `application` uses the `offline_access` scope, the + # generation of a refresh token only happens when the model is created + # with `use_refresh_token: true`. + # + # This is normally determined from the request to create the access + # token, but here we are just creating the access token model, so we + # need to force the `access_token` to have `use_refresh_token: true` + use_refresh_token: true + ) + end + + let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) } + + let(:params) do + { + grant_type: grant_type, + refresh_token: access_token.refresh_token, + } + end + + it 'updates the Web::PushSubscription when refreshed' do + expect { subject } + .to change { access_token.reload.revoked_at }.from(nil).to(be_present) + + expect(response).to have_http_status(200) + + new_token = Doorkeeper::AccessToken.by_token(response.parsed_body[:access_token]) + + expect(web_push_subscription.reload.access_token_id).to eq(new_token.id) + + # Assert that there are definitely no subscriptions left for the + # previous access token: + expect(Web::PushSubscription.where(access_token: access_token.id).count) + .to eq(0) + end + end end describe 'POST /oauth/revoke' do