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

Symfony 6.3 Linkedin登录生成JWT令牌无效问题求助

问题:LinkedIn OAuth生成的JWT令牌无效,返回401错误

问题详情

已完成以下操作:

  • 成功获取LinkedIn用户数据
  • 创建User对象并注入用户信息
  • 将用户数据持久化到数据库
  • 生成JWT令牌:
$jwtToken = $this->jwtManager->create($userEntity);

但使用该令牌访问接口时,返回401错误:

{
    "code": 401,
    "message": "Invalid credentials."
}

直接调用Security的/api/login_check接口时,认证正常,返回:

{
    "message": "Welcome to your new controller!",
    "path": "src/Controller/DashboardController.php"
}

已尝试的解决方案(均未生效)

  • 调用return $security->login($userEntity, 'json_login', 'login');,其中"login"是JWT使用的防火墙,"json_login"是认证器
  • 调用return $authenticationSuccessHandler->handleAuthenticationSuccess($user);

补充说明:$userEntity包含正确的用户信息,生成的JWT令牌也包含所有用户详情。接口响应中已返回令牌,但将其放入Bearer Token中使用时仍然无效。

已安装的Bundle

"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"doctrine/doctrine-bundle": "^2.10",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.16",
"friendsofsymfony/rest-bundle": "^3.6",
"jms/serializer-bundle": "^5.3",
"league/oauth2-linkedin": "^5.1",
"lexik/jwt-authentication-bundle": "*",
"symfony/console": "6.3.*",
"symfony/dotenv": "6.3.*",
"symfony/flex": "^2",
"symfony/framework-bundle": "6.3.*",
"symfony/runtime": "6.3.*",
"symfony/yaml": "6.3.*"

Security配置

security:
    enable_authenticator_manager: true
    password_hashers:
        App\Entity\User: 'auto'
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
            algorithm: 'auto'
            cost:      15
    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        login:
            pattern: ^/api/login
            stateless: true
            json_login:
                check_path: /api/login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
  
        api:
            pattern:   ^/api
            stateless: true
            jwt: ~
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider

    access_control:
        - { path: ^/api/register, roles: PUBLIC_ACCESS  }
        - { path: ^/api/login, roles: PUBLIC_ACCESS  }
        - { path: ^/api/auth/linkedin, roles: PUBLIC_ACCESS  }
        - { path: ^/api/li-callback, roles: PUBLIC_ACCESS  }
        - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

when@test:
    security:
        password_hashers:
            Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                algorithm: auto
                cost: 4 # Lowest possible value for bcrypt
                time_cost: 3 # Lowest possible value for argon
                memory_cost: 10 # Lowest possible value for argon

控制器代码

<?php

// src/Controller/LinkedinAuthController.php

namespace App\Controller;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use App\Service\LinkedinAuthService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use League\OAuth2\Client\Provider\Linkedin;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\SecurityBundle\Security;

class LinkedinAuthController extends AbstractController
{
    private $linkedinAuthService;
    private $entityManager;
    private $jwtManager;

    public function __construct(LinkedinAuthService $linkedinAuthService, EntityManagerInterface $entityManager, JWTTokenManagerInterface $jwtManager)
    {
        $this->linkedinAuthService = $linkedinAuthService;
        $this->entityManager = $entityManager;
        $this->jwtManager = $jwtManager;
    }

    /**
     * @Route("/api/auth/linkedin", name="api_auth_linkedin")
     */
    public function redirectToLinkedin(): Response
    // public function redirectToLinkedin(): JsonResponse
    {...}

    /**
     * @Route("/api/li-callback", name="api_linkedin_callback")
     */
    public function linkedinCallback(Request $request, Security $security): JsonResponse
    {
        session_start();

        if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
            unset($_SESSION['oauth2state']);
            return new JsonResponse(['error' => 'Invalid state'], 401);
        }
       
        try {
            $linkedinUser = $this->linkedinAuthService->getUserData($_GET['code']);

            $userEntity = $this->findOrCreateUser($linkedinUser);
            
            // Generate JWT Token
            // $jwtToken = $this->jwtManager->create($userEntity);            
        
            // you can also log in on a different firewall
            return $security->login($userEntity, 'json_login', 'login');
            
        } catch (IdentityProviderException $e) {
            return new JsonResponse(['error' => 'Authentication failed: '.$e->getMessage()], 401);
        }
    }
}

内容的提问来源于stack exchange,提问作者Thierry Beaucamp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:37:32