fix: Revoke Linear OAuth token when integration is deleted (#11838)

When users delete the Linear integration from their Chatwoot dashboard,
the access token remains valid in Linear's system. This causes the
integration to still appear as connected in Linear's UI, even though
it's been removed from Chatwoot. Users need to manually disconnect from
Linear's side to fully remove the integration.


https://www.loom.com/share/5c102cbdf02e49bcb7a6fa6d409b531a?sid=0c664250-c867-4fc8-b44d-e1c1165337a7
This commit is contained in:
Muhsin Keloth
2025-07-01 13:31:02 +05:30
committed by GitHub
parent 2573f37d90
commit 14ba73fc63
3 changed files with 27 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
before_action :fetch_hook, only: [:destroy]
def destroy
revoke_linear_token
@hook.destroy!
head :ok
end
@@ -120,4 +121,15 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
def fetch_hook
@hook = Integrations::Hook.where(account: Current.account).find_by(app_id: 'linear')
end
def revoke_linear_token
return unless @hook&.access_token
begin
linear_client = Linear.new(@hook.access_token)
linear_client.revoke_token
rescue StandardError => e
Rails.logger.error "Failed to revoke Linear token: #{e.message}"
end
end
end

View File

@@ -1,5 +1,6 @@
class Linear
BASE_URL = 'https://api.linear.app/graphql'.freeze
REVOKE_URL = 'https://api.linear.app/oauth/revoke'.freeze
PRIORITY_LEVELS = (0..4).to_a
def initialize(access_token)
@@ -86,6 +87,14 @@ class Linear
process_response(response)
end
def revoke_token
response = HTTParty.post(
REVOKE_URL,
headers: { 'Authorization' => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
)
response.success?
end
private
def validate_team_and_title(params)

View File

@@ -14,6 +14,12 @@ RSpec.describe 'Linear Integration API', type: :request do
describe 'DELETE /api/v1/accounts/:account_id/integrations/linear' do
it 'deletes the linear integration' do
# Stub the HTTP call to Linear's revoke endpoint
allow(HTTParty).to receive(:post).with(
'https://api.linear.app/oauth/revoke',
anything
).and_return(instance_double(HTTParty::Response, success?: true))
delete "/api/v1/accounts/#{account.id}/integrations/linear",
headers: agent.create_new_auth_token,
as: :json