xdevplatform / account-activity-dashboard

Sample web app and helper scripts to get started with the premium Account Activity API
Apache License 2.0
169 stars 96 forks source link

Unable to add new subscription. #5

Open vverma508 opened 5 years ago

vverma508 commented 5 years ago

I think after latest changes from twitter, add subscription if throwing error. Please help.

Error: Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings at Strategy.parseErrorResponse (d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\passport-twitter\lib\strategy.js:206:12) at Strategy.OAuthStrategy._createOAuthError (d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\passport-oauth1\lib\strategy.js:393:16) at d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\passport-oauth1\lib\strategy.js:244:41 at d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\oauth\lib\oauth.js:543:17 at passBackControl (d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\oauth\lib\oauth.js:397:13) at IncomingMessage. (d:\VSCodeWorkSapce\account-activity-dashboard-master\node_modules\oauth\lib\oauth.js:409:9) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:138:11) at process._tickCallback (internal/process/next_tick.js:180:9)

vverma508 commented 5 years ago

Found this,

https://twittercommunity.com/t/action-required-sign-in-with-twitter-users-must-whitelist-callback-urls/105342

andypiper commented 5 years ago

This is documented in the README - see step 6. You need to whitelist your callback URLs on the developer dashboard. If you've made sure that your URLs are indeed whitelisted then the subscription calls should work. I'm not able to reproduce this error myself.

jk-park commented 5 years ago

I have same error with this, although I have whitelisted callback URLs as follows.

https://my-own-dashboard.herokuapp.com/callbacks/addsub
https://my-own-dashboard.herokuapp.com/callbacks/removesub

I wonder if I have written wrong URLs or something. (Other functionalities include command line example scripts work well.)

ArchieJG commented 5 years ago

I've also been running into this issue, any solution?

ArchieJG commented 5 years ago

newer

This is my app config, the callback urls have been whitelisted but I get the same error as @vverma508 when trying to add a subscription

guumaster commented 5 years ago

While #6 is considered, you can fix it by adding your full domain url to the callback for subscriptions add/remove.

Edit app.js near line 99 and change to something like this:

callbackURL: 'https://your.app.domain/callbacks/addsub`

Same for removesub.

ArchieJG commented 5 years ago

So I edited the app.js to use the full domain and it sort of worked, it took me to the sign in page on twitter to authorise the application but then redirected to an error page that said "Client application is not permitted to access this user's webhook subscriptions" I've pasted the logs below from the redirect (I replaced sensitive info with ***)

{ StatusCodeError: 401 - "{\"errors\":[{\"code\":348,\"message\":\"Client application is not permitted to access this user's webhook subscriptions.\"}]}"
    at new StatusCodeError (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/errors.js:32:15)
    at Request.plumbing.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:104:33)
    at Request.RP$callback [as _callback] (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:46:31)
    at Request.self.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:185:22)
    at Request.emit (events.js:182:13)
    at Request.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1161:10)
    at Request.emit (events.js:182:13)
    at IncomingMessage.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:273:13)
    at IncomingMessage.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  name: 'StatusCodeError',
  statusCode: 401,
  message:
   '401 - "{\\"errors\\":[{\\"code\\":348,\\"message\\":\\"Client application is not permitted to access this user\'s webhook subscriptions.\\"}]}"',
  error:
   '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}',
  options:
   { url:
      'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
     oauth:
      { consumer_key: '***********************',
        consumer_secret: '**************************************',
        token: '*************************************',
        token_secret: '***************************************' },
     resolveWithFullResponse: true,
     method: 'POST',
     callback: [Function: RP$callback],
     transform: undefined,
     simple: true,
     transform2xxOnly: false },
  response:
   IncomingMessage {
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: true,
        endEmitted: true,
        reading: false,
        sync: false,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        emitClose: true,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: false,
     _events:
      { end: [Array],
        close: [Array],
        data: [Function],
        error: [Function] },
     _eventsCount: 4,
     _maxListeners: undefined,
     socket:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     connection:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     httpVersionMajor: 1,
     httpVersionMinor: 1,
     httpVersion: '1.1',
     complete: true,
     headers:
      { 'cache-control':
         'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        connection: 'close',
        'content-disposition': 'attachment; filename=json.json',
        'content-length': '118',
        'content-type': 'application/json; charset=utf-8',
        date: 'Thu, 01 Nov 2018 11:37:03 GMT',
        expires: 'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified': 'Thu, 01 Nov 2018 11:37:03 GMT',
        pragma: 'no-cache',
        server: 'tsa_f',
        'set-cookie': [Array],
        'strict-transport-security': 'max-age=631138519',
        'x-connection-hash': 'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options': 'nosniff',
        'x-frame-options': 'SAMEORIGIN',
        'x-response-time': '131',
        'x-xss-protection': '1; mode=block; report=https://twitter.com/i/xss_report' },
     rawHeaders:
      [ 'cache-control',
        'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        'connection',
        'close',
        'content-disposition',
        'attachment; filename=json.json',
        'content-length',
        '118',
        'content-type',
        'application/json; charset=utf-8',
        'date',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'expires',
        'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'pragma',
        'no-cache',
        'server',
        'tsa_f',
        'set-cookie',
        'personalization_id="v1_nIE2pGKHytAaPWHYTbxVWA=="; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'set-cookie',
        'guest_id=v1%3A154107222313615891; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'strict-transport-security',
        'max-age=631138519',
        'x-connection-hash',
        'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options',
        'nosniff',
        'x-frame-options',
        'SAMEORIGIN',
        'x-response-time',
        '131',
        'x-xss-protection',
        '1; mode=block; report=https://twitter.com/i/xss_report' ],
     trailers: {},
     rawTrailers: [],
     aborted: false,
     upgrade: false,
     url: '',
     method: null,
     statusCode: 401,
     statusMessage: 'Authorization Required',
     client:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     _consuming: true,
     _dumped: false,
     req:
      ClientRequest {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedConnection: false,
        _removedContLen: false,
        _removedTE: false,
        _contentLength: 0,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [TLSSocket],
        connection: [TLSSocket],
        _header:
         'POST /1.1/account_activity/all/dev/subscriptions.json HTTP/1.1\r\nhost: api.twitter.com\r\nAuthorization: OAuth oauth_consumer_key="********************",oauth_nonce="*************************",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1541072223",oauth_token="*****************************",oauth_version="1.0",oauth_signature="Ef1lwfGVZ7dUYkDrsZWsjrj%2FtKc%3D"\r\ncontent-length: 0\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: noopPendingOutput],
        agent: [Agent],
        socketPath: undefined,
        timeout: undefined,
        method: 'POST',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        _ended: true,
        res: [Circular],
        aborted: undefined,
        timeoutCb: null,
        upgradeOrConnect: false,
        parser: null,
        maxHeadersCount: null,
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     request:
      Request {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        resolveWithFullResponse: true,
        method: 'POST',
        readable: true,
        writable: true,
        explicitMethod: true,
        _qs: [Querystring],
        _auth: [Auth],
        _oauth: [OAuth],
        _multipart: [Multipart],
        _redirect: [Redirect],
        _tunnel: [Tunnel],
        _rp_resolve: [Function],
        _rp_reject: [Function],
        _rp_promise: [Promise],
        _rp_callbackOrig: undefined,
        callback: [Function],
        _rp_options: [Object],
        headers: [Object],
        setHeader: [Function],
        hasHeader: [Function],
        getHeader: [Function],
        removeHeader: [Function],
        localAddress: undefined,
        pool: {},
        dests: [],
        __isRequestRequest: true,
        _callback: [Function: RP$callback],
        uri: [Url],
        proxy: null,
        tunnel: true,
        setHost: true,
        originalCookieHeader: undefined,
        _disableCookies: true,
        _jar: undefined,
        port: 443,
        host: 'api.twitter.com',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        httpModule: [Object],
        agentClass: [Function],
        agent: [Agent],
        _started: true,
        href:
         'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
        req: [ClientRequest],
        ntick: true,
        response: [Circular],
        originalHost: 'api.twitter.com',
        originalHostHeaderName: 'host',
        responseContent: [Circular],
        _destdata: true,
        _ended: true,
        _callbackCalled: true },
     toJSON: [Function: responseToJSON],
     caseless: Caseless { dict: [Object] },
     body:
      '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}' } }
jk-park commented 5 years ago

While #6 is considered, you can fix it by adding your full domain url to the callback for subscriptions add/remove.

Edit app.js near line 99 and change to something like this:

callbackURL: 'https://your.app.domain/callbacks/addsub`

Same for removesub.

This works well for both add and remove. Thanks.

mainakchhari commented 5 years ago

So I edited the app.js to use the full domain and it sort of worked, it took me to the sign in page on twitter to authorise the application but then redirected to an error page that said "Client application is not permitted to access this user's webhook subscriptions" I've pasted the logs below from the redirect (I replaced sensitive info with ***)

{ StatusCodeError: 401 - "{\"errors\":[{\"code\":348,\"message\":\"Client application is not permitted to access this user's webhook subscriptions.\"}]}"
    at new StatusCodeError (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/errors.js:32:15)
    at Request.plumbing.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:104:33)
    at Request.RP$callback [as _callback] (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:46:31)
    at Request.self.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:185:22)
    at Request.emit (events.js:182:13)
    at Request.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1161:10)
    at Request.emit (events.js:182:13)
    at IncomingMessage.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:273:13)
    at IncomingMessage.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  name: 'StatusCodeError',
  statusCode: 401,
  message:
   '401 - "{\\"errors\\":[{\\"code\\":348,\\"message\\":\\"Client application is not permitted to access this user\'s webhook subscriptions.\\"}]}"',
  error:
   '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}',
  options:
   { url:
      'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
     oauth:
      { consumer_key: '***********************',
        consumer_secret: '**************************************',
        token: '*************************************',
        token_secret: '***************************************' },
     resolveWithFullResponse: true,
     method: 'POST',
     callback: [Function: RP$callback],
     transform: undefined,
     simple: true,
     transform2xxOnly: false },
  response:
   IncomingMessage {
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: true,
        endEmitted: true,
        reading: false,
        sync: false,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        emitClose: true,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: false,
     _events:
      { end: [Array],
        close: [Array],
        data: [Function],
        error: [Function] },
     _eventsCount: 4,
     _maxListeners: undefined,
     socket:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     connection:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     httpVersionMajor: 1,
     httpVersionMinor: 1,
     httpVersion: '1.1',
     complete: true,
     headers:
      { 'cache-control':
         'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        connection: 'close',
        'content-disposition': 'attachment; filename=json.json',
        'content-length': '118',
        'content-type': 'application/json; charset=utf-8',
        date: 'Thu, 01 Nov 2018 11:37:03 GMT',
        expires: 'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified': 'Thu, 01 Nov 2018 11:37:03 GMT',
        pragma: 'no-cache',
        server: 'tsa_f',
        'set-cookie': [Array],
        'strict-transport-security': 'max-age=631138519',
        'x-connection-hash': 'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options': 'nosniff',
        'x-frame-options': 'SAMEORIGIN',
        'x-response-time': '131',
        'x-xss-protection': '1; mode=block; report=https://twitter.com/i/xss_report' },
     rawHeaders:
      [ 'cache-control',
        'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        'connection',
        'close',
        'content-disposition',
        'attachment; filename=json.json',
        'content-length',
        '118',
        'content-type',
        'application/json; charset=utf-8',
        'date',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'expires',
        'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'pragma',
        'no-cache',
        'server',
        'tsa_f',
        'set-cookie',
        'personalization_id="v1_nIE2pGKHytAaPWHYTbxVWA=="; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'set-cookie',
        'guest_id=v1%3A154107222313615891; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'strict-transport-security',
        'max-age=631138519',
        'x-connection-hash',
        'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options',
        'nosniff',
        'x-frame-options',
        'SAMEORIGIN',
        'x-response-time',
        '131',
        'x-xss-protection',
        '1; mode=block; report=https://twitter.com/i/xss_report' ],
     trailers: {},
     rawTrailers: [],
     aborted: false,
     upgrade: false,
     url: '',
     method: null,
     statusCode: 401,
     statusMessage: 'Authorization Required',
     client:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     _consuming: true,
     _dumped: false,
     req:
      ClientRequest {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedConnection: false,
        _removedContLen: false,
        _removedTE: false,
        _contentLength: 0,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [TLSSocket],
        connection: [TLSSocket],
        _header:
         'POST /1.1/account_activity/all/dev/subscriptions.json HTTP/1.1\r\nhost: api.twitter.com\r\nAuthorization: OAuth oauth_consumer_key="********************",oauth_nonce="*************************",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1541072223",oauth_token="*****************************",oauth_version="1.0",oauth_signature="Ef1lwfGVZ7dUYkDrsZWsjrj%2FtKc%3D"\r\ncontent-length: 0\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: noopPendingOutput],
        agent: [Agent],
        socketPath: undefined,
        timeout: undefined,
        method: 'POST',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        _ended: true,
        res: [Circular],
        aborted: undefined,
        timeoutCb: null,
        upgradeOrConnect: false,
        parser: null,
        maxHeadersCount: null,
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     request:
      Request {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        resolveWithFullResponse: true,
        method: 'POST',
        readable: true,
        writable: true,
        explicitMethod: true,
        _qs: [Querystring],
        _auth: [Auth],
        _oauth: [OAuth],
        _multipart: [Multipart],
        _redirect: [Redirect],
        _tunnel: [Tunnel],
        _rp_resolve: [Function],
        _rp_reject: [Function],
        _rp_promise: [Promise],
        _rp_callbackOrig: undefined,
        callback: [Function],
        _rp_options: [Object],
        headers: [Object],
        setHeader: [Function],
        hasHeader: [Function],
        getHeader: [Function],
        removeHeader: [Function],
        localAddress: undefined,
        pool: {},
        dests: [],
        __isRequestRequest: true,
        _callback: [Function: RP$callback],
        uri: [Url],
        proxy: null,
        tunnel: true,
        setHost: true,
        originalCookieHeader: undefined,
        _disableCookies: true,
        _jar: undefined,
        port: 443,
        host: 'api.twitter.com',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        httpModule: [Object],
        agentClass: [Function],
        agent: [Agent],
        _started: true,
        href:
         'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
        req: [ClientRequest],
        ntick: true,
        response: [Circular],
        originalHost: 'api.twitter.com',
        originalHostHeaderName: 'host',
        responseContent: [Circular],
        _destdata: true,
        _ended: true,
        _callbackCalled: true },
     toJSON: [Function: responseToJSON],
     caseless: Caseless { dict: [Object] },
     body:
      '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}' } }

I am facing the same problem. error code 348 pops up right after the twitter app oauth window is redirected back

mainakchhari commented 5 years ago

So I edited the app.js to use the full domain and it sort of worked, it took me to the sign in page on twitter to authorise the application but then redirected to an error page that said "Client application is not permitted to access this user's webhook subscriptions" I've pasted the logs below from the redirect (I replaced sensitive info with ***)

{ StatusCodeError: 401 - "{\"errors\":[{\"code\":348,\"message\":\"Client application is not permitted to access this user's webhook subscriptions.\"}]}"
    at new StatusCodeError (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/errors.js:32:15)
    at Request.plumbing.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:104:33)
    at Request.RP$callback [as _callback] (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request-promise-core/lib/plumbing.js:46:31)
    at Request.self.callback (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:185:22)
    at Request.emit (events.js:182:13)
    at Request.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1161:10)
    at Request.emit (events.js:182:13)
    at IncomingMessage.<anonymous> (/home/squawk/Documents/Elixir/Phoenix/account-activity-dashboard/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:273:13)
    at IncomingMessage.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  name: 'StatusCodeError',
  statusCode: 401,
  message:
   '401 - "{\\"errors\\":[{\\"code\\":348,\\"message\\":\\"Client application is not permitted to access this user\'s webhook subscriptions.\\"}]}"',
  error:
   '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}',
  options:
   { url:
      'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
     oauth:
      { consumer_key: '***********************',
        consumer_secret: '**************************************',
        token: '*************************************',
        token_secret: '***************************************' },
     resolveWithFullResponse: true,
     method: 'POST',
     callback: [Function: RP$callback],
     transform: undefined,
     simple: true,
     transform2xxOnly: false },
  response:
   IncomingMessage {
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: true,
        endEmitted: true,
        reading: false,
        sync: false,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        emitClose: true,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: false,
     _events:
      { end: [Array],
        close: [Array],
        data: [Function],
        error: [Function] },
     _eventsCount: 4,
     _maxListeners: undefined,
     socket:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     connection:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     httpVersionMajor: 1,
     httpVersionMinor: 1,
     httpVersion: '1.1',
     complete: true,
     headers:
      { 'cache-control':
         'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        connection: 'close',
        'content-disposition': 'attachment; filename=json.json',
        'content-length': '118',
        'content-type': 'application/json; charset=utf-8',
        date: 'Thu, 01 Nov 2018 11:37:03 GMT',
        expires: 'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified': 'Thu, 01 Nov 2018 11:37:03 GMT',
        pragma: 'no-cache',
        server: 'tsa_f',
        'set-cookie': [Array],
        'strict-transport-security': 'max-age=631138519',
        'x-connection-hash': 'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options': 'nosniff',
        'x-frame-options': 'SAMEORIGIN',
        'x-response-time': '131',
        'x-xss-protection': '1; mode=block; report=https://twitter.com/i/xss_report' },
     rawHeaders:
      [ 'cache-control',
        'no-cache, no-store, must-revalidate, pre-check=0, post-check=0',
        'connection',
        'close',
        'content-disposition',
        'attachment; filename=json.json',
        'content-length',
        '118',
        'content-type',
        'application/json; charset=utf-8',
        'date',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'expires',
        'Tue, 31 Mar 1981 05:00:00 GMT',
        'last-modified',
        'Thu, 01 Nov 2018 11:37:03 GMT',
        'pragma',
        'no-cache',
        'server',
        'tsa_f',
        'set-cookie',
        'personalization_id="v1_nIE2pGKHytAaPWHYTbxVWA=="; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'set-cookie',
        'guest_id=v1%3A154107222313615891; Expires=Sat, 31 Oct 2020 11:37:03 GMT; Path=/; Domain=.twitter.com',
        'strict-transport-security',
        'max-age=631138519',
        'x-connection-hash',
        'e8f5181b4855f4a7504120edf7256264',
        'x-content-type-options',
        'nosniff',
        'x-frame-options',
        'SAMEORIGIN',
        'x-response-time',
        '131',
        'x-xss-protection',
        '1; mode=block; report=https://twitter.com/i/xss_report' ],
     trailers: {},
     rawTrailers: [],
     aborted: false,
     upgrade: false,
     url: '',
     method: null,
     statusCode: 401,
     statusMessage: 'Authorization Required',
     client:
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: 'api.twitter.com',
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 8,
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: 'api.twitter.com',
        _readableState: [ReadableState],
        readable: false,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: false,
        allowHalfOpen: false,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: null,
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: null,
        _httpMessage: [ClientRequest],
        write: [Function: writeAfterFIN],
        [Symbol(res)]: [TLSWrap],
        [Symbol(asyncId)]: 824,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]: null,
        [Symbol(kBytesRead)]: 1033,
        [Symbol(kBytesWritten)]: 443,
        [Symbol(connect-options)]: [Object] },
     _consuming: true,
     _dumped: false,
     req:
      ClientRequest {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedConnection: false,
        _removedContLen: false,
        _removedTE: false,
        _contentLength: 0,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [TLSSocket],
        connection: [TLSSocket],
        _header:
         'POST /1.1/account_activity/all/dev/subscriptions.json HTTP/1.1\r\nhost: api.twitter.com\r\nAuthorization: OAuth oauth_consumer_key="********************",oauth_nonce="*************************",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1541072223",oauth_token="*****************************",oauth_version="1.0",oauth_signature="Ef1lwfGVZ7dUYkDrsZWsjrj%2FtKc%3D"\r\ncontent-length: 0\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: noopPendingOutput],
        agent: [Agent],
        socketPath: undefined,
        timeout: undefined,
        method: 'POST',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        _ended: true,
        res: [Circular],
        aborted: undefined,
        timeoutCb: null,
        upgradeOrConnect: false,
        parser: null,
        maxHeadersCount: null,
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     request:
      Request {
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        resolveWithFullResponse: true,
        method: 'POST',
        readable: true,
        writable: true,
        explicitMethod: true,
        _qs: [Querystring],
        _auth: [Auth],
        _oauth: [OAuth],
        _multipart: [Multipart],
        _redirect: [Redirect],
        _tunnel: [Tunnel],
        _rp_resolve: [Function],
        _rp_reject: [Function],
        _rp_promise: [Promise],
        _rp_callbackOrig: undefined,
        callback: [Function],
        _rp_options: [Object],
        headers: [Object],
        setHeader: [Function],
        hasHeader: [Function],
        getHeader: [Function],
        removeHeader: [Function],
        localAddress: undefined,
        pool: {},
        dests: [],
        __isRequestRequest: true,
        _callback: [Function: RP$callback],
        uri: [Url],
        proxy: null,
        tunnel: true,
        setHost: true,
        originalCookieHeader: undefined,
        _disableCookies: true,
        _jar: undefined,
        port: 443,
        host: 'api.twitter.com',
        path: '/1.1/account_activity/all/dev/subscriptions.json',
        httpModule: [Object],
        agentClass: [Function],
        agent: [Agent],
        _started: true,
        href:
         'https://api.twitter.com/1.1/account_activity/all/dev/subscriptions.json',
        req: [ClientRequest],
        ntick: true,
        response: [Circular],
        originalHost: 'api.twitter.com',
        originalHostHeaderName: 'host',
        responseContent: [Circular],
        _destdata: true,
        _ended: true,
        _callbackCalled: true },
     toJSON: [Function: responseToJSON],
     caseless: Caseless { dict: [Object] },
     body:
      '{"errors":[{"code":348,"message":"Client application is not permitted to access this user\'s webhook subscriptions."}]}' } }

I am facing the same problem. error code 348 pops up right after the twitter app oauth window is redirected back

It was a permissions issue. https://twittercommunity.com/t/getting-error-code-348-while-trying-to-add-subscription/101796 solved it for me. Thanks!

faraz66 commented 3 years ago

The Solution is so easy, Just Follow The Given Steps:

1.Go to Your Code File -> Open app.js file 2.Find And Update this line:

Before:

app.get('/subscriptions/add', passport.authenticate('twitter', {
  callbackURL: '/callbacks/addsub'
}));

/**
 * Starts Twitter sign-in process for removing a user subscription
 **/
app.get('/subscriptions/remove', passport.authenticate('twitter', {
  callbackURL: '/callbacks/removesub'
}));

After: Just add your ngrok link to the callbackurl like shown below

app.get('/subscriptions/add', passport.authenticate('twitter', {
  callbackURL: 'https://18161ccd3a7f.ngrok.io/callbacks/addsub'
}));
/**
 * Starts Twitter sign-in process for removing a user subscription
 **/
app.get('/subscriptions/remove', passport.authenticate('twitter', {
  callbackURL: 'https://18161ccd3a7f.ngrok.io/callbacks/removesub'
}));

Make Sure You Have Whitelisted Your Callback Urls in Twitter Developer Account

  1. https://d38193955539.ngrok.io/callbacks/addsub
  2. https://d38193955539.ngrok.io/callbacks/removesub
  3. https://18161ccd3a7f.ngrok.io/twitter/webhook
guumaster commented 3 years ago

or ask to re-open PR #6 that fix this issue properly.