Common-SenseMakers / sensemakers

Sensemakers infrastructure for developing AI-based tools for semantic annotations of social posts. Cross-poster app to publish your semantic posts on different networks.
GNU General Public License v3.0
1 stars 2 forks source link

[APP] Twitter OAuth 2 Token Refresh #32

Closed weswalla closed 5 months ago

weswalla commented 5 months ago

With OAuth 2.0 for the twitter API, the access token is valid only for 2 hours after being issued and there is no way to extend the expiry date. The provided refresh token is supposedly valid for 6 months, so we will need to implement logic to check if the access token is still valid (or check the response type) and refresh accordingly.

This will certainly increase our total requests which some devs have expressed is unfeasible for their apps and have downgraded to OAuth 1.0:

IMHO this renders the OAuth 2.0 API unusable for 95% of apps. We centainly have to downgrade our project to OAuth 1 with this limitation since we don’t want to run a cron job on every user every 2h. source

There are other tools out there that can help us manage these access tokens and refresh tokens, like: https://github.com/superfaceai/passport-twitter-oauth2/tree/main

Alternatively, it does look like it is possible to specifically request read or write access with the oauth 1.0 flow: https://devcommunity.x.com/t/how-to-request-read-and-read-write-permissions-on-the-same-app/170242/9 which provides an access token that doesn't expire.

The access type seems to be supported in the twitter-api-v2 module as well:

/**
     * Generate the OAuth request token link for user-based OAuth 1.0 auth.
     *
     * ```ts
     * // Instantiate TwitterApi with consumer keys
     * const client = new TwitterApi({ appKey: 'consumer_key', appSecret: 'consumer_secret' });
     *
     * const tokenRequest = await client.generateAuthLink('oob-or-your-callback-url');
     * // redirect end-user to tokenRequest.url
     *
     * // Save tokenRequest.oauth_token_secret somewhere, it will be needed for next auth step.
     * ```
     */
    generateAuthLink(oauth_callback?: string, { authAccessType, linkMode, forceLogin, screenName, }?: Partial<RequestTokenArgs>): Promise<{
        oauth_token: string;
        oauth_token_secret: string;
        oauth_callback_confirmed: "true";
        url: string;
    }>;

export interface RequestTokenArgs {
    authAccessType: 'read' | 'write';
    linkMode: 'authenticate' | 'authorize';
    forceLogin: boolean;
    screenName: string;
}

Though from the forum discussion there may be some limitations in using oauth 1.0 for login (authentication) along with authorization:

OK just tested. This is not the expected behavior, it’s ignoring the fact that you already authorized the app with higher permission than requested, and asking you to authorize again with lower permissions. So I don’t think you are doing something wrong from your end (and I apologize I should have confirmed that things are still working as usual before my earlier response) Unfortunately unless someone from the Twitter team flags this for fixing, there isn’t much you can do This does break the use of Twitter login function, basically the only way I see this is for you to ditch Twitter authentication and implement your own login. Then record which level of Twitter auth each user has and challenge them accordingly.

weswalla commented 5 months ago

If we stick with OAuth 2.0, my proposed solution is the following:

This will be a continuous loop running as long as the user grants twitter access.

pepoospina commented 5 months ago

I think the refreshToken might be valid even after the original accessToken expires. We will have to test this.

If this is the case, the refresh flow can be implemented directly in the TwitterService getUserClient method.

Also, a note: the accessType 'read' option in OAuth 1.0 was not effective when I tried it. Even if you configure it, the permissions requested include posting in the name of the user.