From 8ac5a606163bd8ab0748d7093cbaddfa7c99b54b Mon Sep 17 00:00:00 2001 From: Srinjoy Date: Fri, 7 Aug 2026 17:42:52 +0530 Subject: [PATCH] fix(X (Formerly Twitter) Node): Update OAuth2 and API endpoints to `x.com` (#32699) --- .../TwitterOAuth2Api.credentials.ts | 4 +-- .../test/TwitterOAuth2Api.credentials.test.ts | 36 +++++++++++++++++++ .../nodes/Twitter/V2/GenericFunctions.ts | 2 +- .../nodes/Twitter/test/Twitter.test.ts | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 packages/nodes-base/credentials/test/TwitterOAuth2Api.credentials.test.ts diff --git a/packages/nodes-base/credentials/TwitterOAuth2Api.credentials.ts b/packages/nodes-base/credentials/TwitterOAuth2Api.credentials.ts index 53f1f218e06..53ed41172c1 100644 --- a/packages/nodes-base/credentials/TwitterOAuth2Api.credentials.ts +++ b/packages/nodes-base/credentials/TwitterOAuth2Api.credentials.ts @@ -43,13 +43,13 @@ export class TwitterOAuth2Api implements ICredentialType { displayName: 'Authorization URL', name: 'authUrl', type: 'hidden', - default: 'https://twitter.com/i/oauth2/authorize', + default: 'https://x.com/i/oauth2/authorize', }, { displayName: 'Access Token URL', name: 'accessTokenUrl', type: 'hidden', - default: 'https://api.twitter.com/2/oauth2/token', + default: 'https://api.x.com/2/oauth2/token', }, { displayName: 'Scope', diff --git a/packages/nodes-base/credentials/test/TwitterOAuth2Api.credentials.test.ts b/packages/nodes-base/credentials/test/TwitterOAuth2Api.credentials.test.ts new file mode 100644 index 00000000000..e2684f52a5d --- /dev/null +++ b/packages/nodes-base/credentials/test/TwitterOAuth2Api.credentials.test.ts @@ -0,0 +1,36 @@ +import { TwitterOAuth2Api } from '../TwitterOAuth2Api.credentials'; + +describe('TwitterOAuth2Api Credential', () => { + const credential = new TwitterOAuth2Api(); + + it('should have correct credential metadata', () => { + expect(credential.name).toBe('twitterOAuth2Api'); + expect(credential.extends).toEqual(['oAuth2Api']); + + const authUrlProperty = credential.properties.find((p) => p.name === 'authUrl'); + expect(authUrlProperty?.default).toBe('https://x.com/i/oauth2/authorize'); + + const accessTokenUrlProperty = credential.properties.find((p) => p.name === 'accessTokenUrl'); + expect(accessTokenUrlProperty?.default).toBe('https://api.x.com/2/oauth2/token'); + }); + + it('should use PKCE grant type', () => { + const grantTypeProperty = credential.properties.find((p) => p.name === 'grantType'); + expect(grantTypeProperty?.type).toBe('hidden'); + expect(grantTypeProperty?.default).toBe('pkce'); + }); + + it('should use header authentication', () => { + const authenticationProperty = credential.properties.find((p) => p.name === 'authentication'); + expect(authenticationProperty?.type).toBe('hidden'); + expect(authenticationProperty?.default).toBe('header'); + }); + + it('should default scope to the full scope list', () => { + const scopeProperty = credential.properties.find((p) => p.name === 'scope'); + expect(scopeProperty?.type).toBe('hidden'); + expect(scopeProperty?.default).toBe( + 'tweet.read users.read tweet.write tweet.moderate.write users.read follows.read follows.write offline.access like.read like.write dm.write dm.read list.read list.write', + ); + }); +}); diff --git a/packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts b/packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts index ba738e3c4c0..4fcf2050bae 100644 --- a/packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Twitter/V2/GenericFunctions.ts @@ -24,7 +24,7 @@ export async function twitterApiRequest( method, body, qs, - url: uri || `https://api.twitter.com/2${resource}`, + url: uri || `https://api.x.com/2${resource}`, json: true, }; try { diff --git a/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts b/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts index fb0953ec612..9a1c00cf397 100644 --- a/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts +++ b/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts @@ -81,7 +81,7 @@ describe('Test Twitter Request Node', () => { }; beforeAll(() => { - const baseUrl = 'https://api.twitter.com/2'; + const baseUrl = 'https://api.x.com/2'; //GET nock(baseUrl).get('/users/me').reply(200, meResult);