atymic / twitter

Twitter API for Laravel 5.5+, 6.x, 7.x & 8.x
https://atymic.dev
MIT License
922 stars 290 forks source link

Instructions for login via v2? #405

Closed CyberPunkCodes closed 1 year ago

CyberPunkCodes commented 1 year ago

Using v2 as the API Version breaks the login/webhook process. Twitter::getRequestToken() isn't found.

Is it possible to have a user authenticate with twitter to login to my site, on v2 with this library?

Or do I need to specify with version 1 or something?

I feel like there is something missing for the docs about settings up for v2.

scottybo commented 1 year ago

@CyberPunkCodes did you find out how to do this?

joelvanpatten commented 1 year ago

I am also trying to do this. If anyone has figured this out it would be great to post.

scottybo commented 1 year ago

Getting kind of urgent now with Twitter starting to shut things off. Any luck @joelvanpatten ?

joelvanpatten commented 1 year ago

No. I honestly just abandoned this package and started creating my own OAuth2 implementation using Laravels Guzzle wrappers.

return Http::withBasicAuth($clientId, $clientSecret) ->asForm() // Content-Type of application/x-www-form-urlencoded via a header ->post($url, $data);

scottybo commented 1 year ago

For anyone else arriving on this thread, I also gave up and just did a Guzzle request

    public function redirectToTwitter()
    {
        $state = Str::random(40);
        $codeChallenge = Str::random(64);
        $codeChallengeMethod = 'plain';

        // Store the state and code_challenge values in session
        session([
            'state' => $state,
            'code_challenge' => $codeChallenge,
            'code_challenge_method' => $codeChallengeMethod,
        ]);

        $callback_url = config('app.callback_url').'callback/twitter';

        $queryParams = [
            'response_type' => 'code',
            'client_id' => config('twitter.access_token'),
            'redirect_uri' => $callback_url,
            'state' => $state,
            'code_challenge' => $codeChallenge,
            'code_challenge_method' => $codeChallengeMethod,
            'scope' => 'offline.access tweet.read tweet.write',
        ];

        $url = 'https://twitter.com/i/oauth2/authorize?' . http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986);

        return redirect($url);
    }

And for the Callback

use GuzzleHttp\Client;
...
    public function handleTwitterCallback(Request $request) {

        $code = $request->input('code');
        $state = $request->input('state');
        $sessionState = session('state', '');
        $codeVerifier = session('code_challenge', '');

        // Verify the state parameter to protect against CSRF attacks
        if ($state !== $sessionState) {
            return redirect('/auth/twitter')->withErrors(['Invalid state parameter']);
        }

        $callbackUrl = config('app.callback_url').'callback/twitter';

        $client = new Client([
            'base_uri' => 'https://api.twitter.com/2/',
        ]);

        $basicAuthHeader = base64_encode(config('twitter.access_token') . ':' . config('twitter.access_token_secret'));

        $response = $client->post('oauth2/token', [
            'headers' => [
                'Authorization' => 'Basic ' . $basicAuthHeader,
                'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8',
            ],
            'form_params' => [
                'grant_type' => 'authorization_code',
                'code' => $code,
                'redirect_uri' => $callbackUrl,
                'code_verifier' => $codeVerifier,
            ],
        ]);

        $accessToken = json_decode((string)$response->getBody(), true)['access_token'];

        dd($accessToken);

    }
scottybo commented 1 year ago

P.s. if you want to get the User, do the following:

            $accessToken = json_decode((string)$response->getBody(), true)['access_token'];

            // Docs: https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me
            $userContextResponse = $client->get('https://api.twitter.com/2/users/me', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $accessToken,
                ],
                'query' => [
                    'user.fields' => 'id,name,username,profile_image_url',
                ],
            ]);
atymic commented 1 year ago

Would recommend the socialite provider for this, if anyone wants to fix the implementation in this repo feel free to PR. https://github.com/SocialiteProviders/Twitter