具有外部用户来源的OAuth2服务器

时间:2015-07-23 09:50:49

标签: php symfony oauth fosoauthserverbundle

我正在使用优秀的FOSOAuthServer捆绑包构建OAuth2服务器。

我的Symfony应用程序验证来自其他来源(实际上是另一台服务器)的用户。

我创建了一个自定义UserProvider,可以使用默认的Symfony安全层。我有UserInterface的实现,但它显然不是数据库的实体。

实施AccessTokenRefreshToken&的课程对于Doctrine,AuthCodetold in the installation instructions,我将用户引用定义为

//...
/**
 * @ORM\Column(type="integer")
 */
protected $user_id;
//...

在那之前它似乎合乎逻辑吗?

现在真正的问题是: 在哪里指定将用户链接到不同令牌的方式?

出于可见度目的,我还在asking the question官方回购

1 个答案:

答案 0 :(得分:1)

我最终做了两件事:

  • 覆盖代币制定者&属性的吸气器user
  • 使用Doctrine LifecycleEvent侦听器

首先扩展令牌类(例如使用Trait

namespace AppBundle\Entity;

use AppBundle\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;

trait AppTokenTrait
{
    /**
     * @ORM\Column(type="string")
     * @var string
     */
    protected $username;

    public function setUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new \InvalidArgumentException(
                sprintf("User must be an instance of %s", User::class)
            );
        }

        $this->username = $user->getUsername();
        $this->user = $user;
    }

    public function getUser()
    {
        if (!$this->user) {
            throw new \RuntimeException(
                "Unable to get user - user was not loaded by postLoad"
            );
        }

        return $this->user;
    }

    /**
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }
}

在3个令牌类中(并且不要忘记更新数据库架构):

//...
    use AppTokenTrait;
//...

创建监听器

namespace AppBundle\Services;

use AppBundle\Entity\AccessToken;
use AppBundle\Entity\AuthCode;
use AppBundle\Entity\RefreshToken;
use AppBundle\Security\UserProvider;
use Doctrine\ORM\Event\LifecycleEventArgs;

class AppTokenListener
{
    /**
     * @var UserProvider
     */
    protected $userProvider;

    public function __construct(UserProvider $userProvider)
    {
        $this->userProvider = $userProvider;
    }

    public function postLoad(LifecycleEventArgs $event)
    {
        $object = $event->getObject();

        if (
            $object instanceof AccessToken or
            $object instanceof AuthCode or
            $object instanceof RefreshToken
        ) {
            $user = $this->userProvider->loadUserByUsername($object->getUsername());
            $object->setUser($user);
        }
    }
}

将其注册为服务

app.token.listener:
    class: AppBundle\Services\AppTokenListener
    tags:
        - { name: doctrine.event_listener, event: postLoad }

现在,用户对象应始终附加到令牌