You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Facebook账号登录后刷新页面出现This authorization code has been used错误求助

Facebook授权后刷新页面触发「This authorization code has been used」错误排查

问题概述

使用Facebook账号完成登录操作后刷新页面,触发「This authorization code has been used」错误,相关代码如下,请求协助排查。

相关代码

Providers\FacebookRepository.php

class FacebookRepository
{
    protected $facebook;

    public function __construct()
    {
        $this->facebook = new Facebook([
            'app_id' => config('providers.facebook.app_id'),
            'app_secret'    => config('providers.facebook.app_secret'),
            'default_graph_version' =>  'v11.0'
        ]);
    }

    public function redirectTo()
    {
        $helper = $this->facebook->getRedirectLoginHelper();

        $permissions = [
            'pages_manage_posts',
            'pages_read_engagement'
        ];

        $redirectUri = config('app.url') . '/home/facebookPage';

        return $helper->getLoginUrl($redirectUri, $permissions);
    }

    public function handleCallback()
    {
        $helper = $this->facebook->getRedirectLoginHelper();

        if (request('state')) {
            $helper->getPersistentDataHandler()->set('state', request('state'));
        }

        try {
            $accessToken = $helper->getAccessToken();
        } catch(FacebookResponseException $e) {
            throw new Exception("Graph returned an error: {$e->getMessage()}");
        } catch(FacebookSDKException $e) {
            throw new Exception("Facebook SDK returned an error: {$e->getMessage()}");
        }
        //$accessToken = Api::where('app_id', 107003655273452)->pluck('access_token')->first();
        $accessToken = $helper->getAccessToken();
        if (!isset($accessToken)) {
            throw new Exception('Access token error');
        }

        if (!$accessToken->isLongLived()) {
            try {
                $oAuth2Client = $this->facebook->getOAuth2Client();
                $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
            } catch (FacebookSDKException $e) {
                throw new Exception("Error getting a long-lived access token: {$e->getMessage()}");
            }
        }

        return $accessToken->getValue();
    }

    public function getPages($accessToken)
    {
        $pages = $this->facebook->get('/me/accounts', $accessToken);
        $pages = $pages->getGraphEdge()->asArray();

        return array_map(function ($item) {
            return [
                'access_token' => $item['access_token'],
                'id' => $item['id'],
                'name' => $item['name'],
                'image' => "https://graph.facebook.com/{$item['id']}/picture?type=large"
            ];
        }, $pages);
    }
}

Controller\SocialController.php

class SocialController extends Controller
{
    protected $facebook;

    public function __construct()
    {
        $this->facebook = new FacebookRepository();
    }

    public function redirectToProvider()
    {
        return redirect($this->facebook->redirectTo());
    }

    public function handleProviderCallback()
    {
        if (request('error') == 'access_denied')
        {
            //handle error
            dd(request('error'));
        }

        $accessToken = $this->facebook->handleCallback();
        //dd($accessToken);

        //use token to get facebook pages
        $page = $this->facebook->getPages($accessToken);

        //store acceess token in databese and use it to get pages

        //dd($accessToken);

        return redirect(route('facebook.login.callback'))->with('page', $page);
    }
}

问题根源分析

  1. 重复调用授权码兑换逻辑:在FacebookRepository.php的handleCallback方法中,连续两次调用$helper->getAccessToken()。第一次调用已经消耗了Facebook返回的授权码,第二次调用时授权码已失效,直接触发「This authorization code has been used」错误。
  2. 回调页面无防刷新处理:用户刷新回调页面时,浏览器会重复发送包含已使用授权码的请求,此时未做判断就重新执行授权流程,必然触发错误。

修复方案

1. 移除重复的授权码兑换调用

修改FacebookRepository.php的handleCallback方法,删除第二次多余的getAccessToken()调用:

public function handleCallback()
{
    $helper = $this->facebook->getRedirectLoginHelper();

    if (request('state')) {
        $helper->getPersistentDataHandler()->set('state', request('state'));
    }

    try {
        $accessToken = $helper->getAccessToken(); // 仅保留这一次调用
    } catch(FacebookResponseException $e) {
        throw new Exception("Graph returned an error: {$e->getMessage()}");
    } catch(FacebookSDKException $e) {
        throw new Exception("Facebook SDK returned an error: {$e->getMessage()}");
    }

    if (!isset($accessToken)) {
        throw new Exception('Access token error');
    }

    if (!$accessToken->isLongLived()) {
        try {
            $oAuth2Client = $this->facebook->getOAuth2Client();
            $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
        } catch (FacebookSDKException $e) {
            throw new Exception("Error getting a long-lived access token: {$e->getMessage()}");
        }
    }

    return $accessToken->getValue();
}

2. 添加回调页面防刷新逻辑

在SocialController.php的handleProviderCallback方法中,缓存授权结果,避免刷新时重复执行授权流程:

public function handleProviderCallback()
{
    if (request('error') == 'access_denied')
    {
        dd(request('error'));
    }

    // 检查Session中是否已有缓存数据,避免重复授权
    if(session()->has('facebook_page_data')) {
        return redirect(route('facebook.login.callback'))->with('page', session('facebook_page_data'));
    }

    try {
        $accessToken = $this->facebook->handleCallback();
        $page = $this->facebook->getPages($accessToken);

        // 将数据存入Session,关联当前用户的话也可存入数据库
        session(['facebook_page_data' => $page, 'facebook_access_token' => $accessToken]);

        return redirect(route('facebook.login.callback'))->with('page', $page);
    } catch(Exception $e) {
        // 错误处理:跳转到登录页并提示错误
        return redirect(route('facebook.login'))->with('error', $e->getMessage());
    }
}

3. 额外优化建议

  • 确保state参数验证逻辑正常运行,防止CSRF攻击(当前代码已包含该逻辑,无需修改)
  • 长期令牌获取后建议持久化到数据库,避免用户每次登录都重新授权

内容的提问来源于stack exchange,提问作者iyed ghodhbane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 15:15:26