Symfony で FOSOAuthServerBundle のトークン認証が必要な WEB API のデモを作ってみた

  • 12
    いいね
  • 0
    コメント

Symfony Advent Calendar 2016 の 13日目の投稿です。FOSOAuthServerBundle の基本的な導入と利用について日本語でまとまっている記事がなかったので書いてみました。WEB API、ユーザーシステムの下地として、FOSRestBundle, FOSUserBunble も利用しています。

今回、実装したデモ用のソースコードは以下に置いて置いてあります :smile_cat:

概要

  • FOSOAuthServerBundle を利用してトークン認証が必要な WEB API のデモを作りました。
  • FOSOAuthServerBundle による トークン発行、トークンのリフレッシュ、有効期限が切れたトークンの削除 の方法について説明しました。

1. 環境

  • Symfony 2.8
  • PHP 7.0.8
  • MySQL

2. ユーザーシステムとデモ API を作成

では、さっそく取り掛かっていきます。

まず、Symfony Installer でプロジェクトを作成し、FOSRestBundle, FOSUserBundle を追加しユーザーシステムとデモ API をセットアップしていきます。手順の説明は、公式ドキュメントに記載がありますので今回は省略します。以下の公式ドキュメントを参考にしてください。

STEP 2.1 プロジェクトの作成

$ symfony new symfony-oauth-sever 2.8
$ cd symfony-oauth-server

STEP 2.2 Bundle のインストール

$ composer require friendsofsymfony/rest-bundle 1.3.*
$ composer require friendsofsymfony/user-bundle
$ composer require jms/serializer-bundle
app/AppKernel.php
...

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new AppBundle\AppBundle(),

            // 追加
            new FOS\RestBundle\FOSRestBundle(),
            new FOS\UserBundle\FOSUserBundle(),
            new JMS\SerializerBundle\JMSSerializerBundle(),
        );

...

}

STEP 2.3 Bundle の設定

app/config/config.yml
fos_rest:
    routing_loader:
        default_format: json
        include_format: false

fos_user:
    db_driver: orm
    firewall_name: api
    user_class: AppBundle\Entity\User
app/config/security.yml
security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

STEP 2.4 User Entity クラスの作成

src/AppBundle/Entity/User.php
<?php
// src/AppBundle/Entity/User.php

namespace AppBundle\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();
        // your own logic
    }
}

STEP 2.5 データベースの準備

$ php app/console doctrine:database:create
$ php app/console doctrine:schema:update --force
mysql> use symfony-oauth-server;
mysql> show tables;
+--------------------------------+
| Tables_in_symfony-oauth-server |
+--------------------------------+
| fos_user                       |
+--------------------------------+
1 rows in set (0.00 sec)

STEP 2.6 ユーザの作成

$ php app/console fos:user:create

Please choose a username:admin
Please choose an email:admin@example.com
Please choose a password:adminpass
Created user admin
mysql> select * from fos_user;
+----+----------+--------------------+-------------------+-------------------+---------+---------------------------------+--------------------------------------------------------------+------------+--------+---------+------------+--------------------+-----------------------+--------+---------------------+-----------------------+
| id | username | username_canonical | email             | email_canonical   | enabled | salt                            | password                                                     | last_login | locked | expired | expires_at | confirmation_token | password_requested_at | roles  | credentials_expired | credentials_expire_at |
+----+----------+--------------------+-------------------+-------------------+---------+---------------------------------+--------------------------------------------------------------+------------+--------+---------+------------+--------------------+-----------------------+--------+---------------------+-----------------------+
|  1 | admin    | admin              | admin@example.com | admin@example.com |       1 | kjflxygblxcwccgkg4o4ooggkckgggw | $2y$13$kjflxygblxcwccgkg4o4oe34L7Y6Iorvaz4V5Sr9lg3nbSnHn.b.i | NULL       |      0 |       0 | NULL       | NULL               | NULL                  | a:0:{} |                   0 | NULL                  |
+----+----------+--------------------+-------------------+-------------------+---------+---------------------------------+--------------------------------------------------------------+------------+--------+---------+------------+--------------------+-----------------------+--------+---------------------+-----------------------+
1 row in set (0.01 sec)

STEP 2.7 API の作成

app/config/routing.yml
api:
    resource: "@AppBundle/Controller/"
    prefix:   api
    type:     rest
src/AppBundle/Controller/WelcomeController.php
<?php

namespace AppBundle\Controller;

use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Controller\FOSRestController;

/**
 * @RouteResource("welcome")
 */
class WelcomeController extends FOSRestController
{
    public function getAction()
    {
        return ["welcome!"];
    }
}

STEP 2.8 動作確認

PHP の build-in server で動作を確認します。

$ php app/console server:start

HTTP のリクエストには HTTPie を利用しています。ユーザーフレンドリーなシンタックスやハイライトを提供してくれて JSON にも対応しているためオススメです。

$ http GET http://localhost:8000/app_dev.php/api/welcome
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/json

[
    "welcome!"
]

・・・はい、さくっとできましたね :smile_cat: 新しいバンドル導入方法は、多くのバンドルで同じ流れが多いのでいまいちピンと来てない方は再度おさらいしておくことをオススメします :smiley_cat:

3. FOSOAuthServerBundle を導入する

では、ここからが本編です。FOSOAuthServerBundle を使っていきます。

まずはインストールから。

STEP 3.1 インストール

$ composer require friendsofsymfony/oauth-server-bundle
app/AppKernel.php
...

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new AppBundle\AppBundle(),

            // 追加
            new FOS\OAuthServerBundle\FOSOAuthServerBundle(),
            new FOS\RestBundle\FOSRestBundle(),
            new FOS\UserBundle\FOSUserBundle(),
            new JMS\SerializerBundle\JMSSerializerBundle(),
        );

...

}

STEP 3.2 Entity の追加

次に利用する Entity を追加していきます。追加する Entity は以下の4つです。

  • 1) AccessToken.php

    src/AppBundle/Entity/AccessToken.php
    <?php
    
    namespace AppBundle\Entity;
    
    use FOS\OAuthServerBundle\Entity\AccessToken as BaseAccessToken;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     */
    class AccessToken extends BaseAccessToken
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @ORM\ManyToOne(targetEntity="Client")
         * @ORM\JoinColumn(nullable=false)
         */
        protected $client;
    
        /**
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
         */
        protected $user;
    }
    
  • 2) AuthCode.php

    src/AppBundle/Entity/AuthCode.php
    <?php
    
    namespace AppBundle\Entity;
    
    use FOS\OAuthServerBundle\Entity\AuthCode as BaseAuthCode;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     */
    class AuthCode extends BaseAuthCode
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @ORM\ManyToOne(targetEntity="Client")
         * @ORM\JoinColumn(nullable=false)
         */
        protected $client;
    
        /**
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
         */
        protected $user;
    }
    
  • 3) Client.php

    src/AppBundle/Entity/Client.php
    <?php
    
    namespace AppBundle\Entity;
    
    use FOS\OAuthServerBundle\Entity\Client as BaseClient;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     */
    class Client extends BaseClient
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    }
    
  • 4) RefreshToken.php

    src/AppBundle/Entity/RefreshToken.php
    <?php
    
    namespace AppBundle\Entity;
    
    use FOS\OAuthServerBundle\Entity\RefreshToken as BaseRefreshToken;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity
     */
    class RefreshToken extends BaseRefreshToken
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @ORM\ManyToOne(targetEntity="Client")
         * @ORM\JoinColumn(nullable=false)
         */
        protected $client;
    
        /**
         * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
         */
        protected $user;
    }
    

STEP 3.3 データベースの準備

$ php app/console doctrine:schema:update --force
+--------------------------------+
| Tables_in_symfony-oauth-server |
+--------------------------------+
| access_token                   |
| auth_code                      |
| client                         |
| fos_user                       |
| refresh_token                  |
+--------------------------------+
5 rows in set (0.00 sec)

STEP 3.4 設定の追加

config.yml に設定を追加していきます。

app/config/config.yml
fos_oauth_server:
    db_driver: orm       # Drivers available: orm, mongodb, or propel
    client_class:        AppBundle\Entity\Client
    access_token_class:  AppBundle\Entity\AccessToken
    refresh_token_class: AppBundle\Entity\RefreshToken
    auth_code_class:     AppBundle\Entity\AuthCode
    service:
        user_provider: fos_user.user_provider.username

ルーティングも追加します。

app/config/routing.yml
fos_oauth_server_token:
    resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml"

fos_oauth_server_authorize:
    resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml"

serurity.yml に認証の設定を追加しましょう。

app/config/security.yml
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html
security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

    # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
    providers:
        in_memory:
            memory: ~

    firewalls:
        oauth_token:
            pattern:    ^/oauth/v2/token
            security:   false

        api:
            pattern:    ^/api
            fos_oauth:  true
            stateless:  true
            anonymous:  false # can be omitted as its default value

    access_control:
        - { path: ^/api, roles: [ IS_AUTHENTICATED_FULLY ] }

この設定で、全ての API はトークン認証なしにはアクセスできなります。ここまで進んだところで、先程作成した Welcom API を叩いてアクセスが拒否されることを確認してみましょう。

$ http GET http://localhost:8000/app_dev.php/api/welcome
HTTP/1.1 401 Unauthorized
Cache-Control: no-store, private
Content-Type: application/json
Host: localhost:8000
Pragma: no-cache
WWW-Authenticate: Bearer realm="Service", error="access_denied", error_description="OAuth2 authentication required"

{
    "error": "access_denied",
    "error_description": "OAuth2 authentication required"
}

無事にアクセスが拒否されています :smile_cat: ここからは、この API にトークン認証でアクセスできるようにしていきます。

4. OAuth によるトークン認証

はい。ではここから FOSOAuthServerBundle で OAuth によるトークン認証を試していきます。今回試す Grant Type は Resource Owner Password Credentials とします。

STEP 4.1 クライアントの作成

まず、クライアントを作成します。ぐぐってみると、FOSOAuthServerBundle でクライアントを発行するにはいくつかみつかりました。

  • SQL で登録
  • WEB フォームから登録
  • Symfony Command で登録

せっかくなので、Symfony Command で作ってみます :smiley:
なお、FOSOAuthServerBundle が Symfony Command を用意しているわけではなく、自前で実装する必要があります。

src/AppBundle/Command/CreateOAuthClientCommand.php
<?php

namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CreateOAuthClientCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('app:oauth-client:create')
            ->setDescription('Create OAuth Client.')
            ->addArgument('redirectUri', InputArgument::REQUIRED, 'The redirect uri')
            ->addArgument('grantType',   InputArgument::REQUIRED, 'The grant type')
            ->setHelp(<<<EOT
The <info>app:oauth:create</info> command creates a OAuth Client:

  <info>php app/console app:oauth:create</info>

This interactive shell will ask you for an client name, a redirect uri and then a grant type.

EOT
            );
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $redirectUri = $input->getArgument('redirectUri');
        $grantType   = $input->getArgument('grantType');

        $clientManager = $this->getContainer()->get('fos_oauth_server.client_manager.default');
        $client = $clientManager->createClient();
        $client->setRedirectUris([$redirectUri]);
        $client->setAllowedGrantTypes([$grantType]);
        $clientManager->updateClient($client);

        $output->writeln(sprintf('Created OAuth Client'));

        return;
    }

    protected function interact(InputInterface $input, OutputInterface $output)
    {
        if (!$input->getArgument('redirectUri')) {
            $redirectUri = $this->getHelper('dialog')->askAndValidate(
                $output,
                'Please choose an Redirect Uri:',
                function($redirectUri) {
                    if (empty($redirectUri)) {
                        throw new \Exception('Redirect Uri can not be empty');
                    }

                    return $redirectUri;
                }
            );
            $input->setArgument('redirectUri', $redirectUri);
        }

        if (!$input->getArgument('grantType')) {
            $grantType = $this->getHelper('dialog')->askAndValidate(
                $output,
                'Please choose a Grant Type:',
                function($grantType) {
                    if (empty($grantType)) {
                        throw new \Exception('Grant Type can not be empty');
                    }

                    return $grantType;
                }
            );
            $input->setArgument('grantType', $grantType);
        }
    }
}

では、さっそく使ってみましょう! Grant Type は Resource Owner Password Credentials を利用するために passwordrefresh_token を登録しています。

$ php app/console app:oauth-client:create

Please choose an Redirect Uri:http://example.com
Please choose a Grant Types (separate multiple grant type with a space):password refresh_token
Created OAuth Client
mysql> select * from client;
+----+----------------------------------------------------+--------------------------------------+----------------------------------------------------+---------------------------+
| id | random_id                                          | redirect_uris                        | secret                                             | allowed_grant_types       |
+----+----------------------------------------------------+--------------------------------------+----------------------------------------------------+---------------------------+
|  1 | 1avth1a6t18kc4coc4o48wkogsww0c0o4oko0oc4wsgc4848c4 | a:1:{i:0;s:18:"http://example.com";} | 18u7clil6ww008480ko4occkkw80s4k4w0o0w8wgko44wwgkg0 | a:2:{i:0;s:8:"password";i:1;s:13:"token_refresh";} |
+----+----------------------------------------------------+--------------------------------------+----------------------------------------------------+---------------------------+
1 row in set (0.00 sec)

無事に登録できましたね :smile_cat:

STEP 4.2 トークンの発行

ではトークンを発行していきます。前述の通り、FOSOAuthServerBundle のトークン発行のエンドポイントはドキュメント通り設定すると以下です。

$ php app/console router:debug |grep token

fos_oauth_server_token       GET|POST   ANY      ANY    /oauth/v2/token

Resource Owner Password Credentials によるトークンの発行には以下のデータを送信する必要があります。

名前 内容
grant_type Grant Type を指定します。 Resource Owner Password Credentials とするためには password という文字列を送ります
username 認証するユーザー名
password 認証するパスワード
scope スコープがある場合は設定します(任意)

またクライアント認証(Client Authentication)のためにクライントアプリケーションが何であるかを特定するためのデータを送信する必要があります。これは先程作成した Client ID, Client Secret を利用します。OAuth では、Authorization ヘッダに登録する方法と client_id, client_secret という名前でリクエストボディに入れる方法があります。リクエストボディにデータを設定してトークンを発行してみます。

$ http POST http://localhost:8000/app_dev.php/oauth/v2/token \
grant_type=password \
username=admin \
password=adminpass \
client_id=1_1avth1a6t18kc4coc4o48wkogsww0c0o4oko0oc4wsgc4848c4 \
client_secret=18u7clil6ww008480ko4occkkw80s4k4w0o0w8wgko44wwgkg0 
HTTP/1.1 200 OK
Cache-Control: no-store, private
Content-Type: application/json
Pragma: no-cache

{
    "access_token": "OWRiNWU5OTJlMGIzOGE1OTRiNjQ2MGZkM2EwYTM1YWFjNjdjYzc3NWEwYjMxN2VlOWNjY2E4ZDE0ZDRlOTdjZg",
    "expires_in": 3600,
    "refresh_token": "MmMwODYwYjg1Y2VmZGQ4NTExYmQwOTE1NTg4YzhiOTY4N2EzZTcyZmI2MGI1MTVjMjA1NTMxMTE0Zjc0Zjg4MQ",
    "scope": null,
    "token_type": "bearer"
}

AccessToken, RefeshToken がレスポンスとして返ってきましたね。データベースも確認してみましょう。

mysql> select * from access_token;
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
| id | client_id | user_id | token                                                                                  | expires_at | scope |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
|  1 |         1 |       1 | OWRiNWU5OTJlMGIzOGE1OTRiNjQ2MGZkM2EwYTM1YWFjNjdjYzc3NWEwYjMxN2VlOWNjY2E4ZDE0ZDRlOTdjZg | 1481609172 | NULL  |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
1 row in set (0.00 sec)
mysql> select * from refresh_token;
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
| id | client_id | user_id | token                                                                                  | expires_at | scope |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
|  1 |         1 |       1 | MmMwODYwYjg1Y2VmZGQ4NTExYmQwOTE1NTg4YzhiOTY4N2EzZTcyZmI2MGI1MTVjMjA1NTMxMTE0Zjc0Zjg4MQ | 1482815172 | NULL  |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
1 row in set (0.00 sec)

トークンとリフレッシュトークンが登録されていますね :smile_cat:

STEP 4.3 トークン認証を利用した API へのアクセス

では、発行したトークンを利用して API にアクセスしてみます。

$ http GET http://localhost:8000/app_dev.php/api/welcome \
"Authorization:Bearer OWRiNWU5OTJlMGIzOGE1OTRiNjQ2MGZkM2EwYTM1YWFjNjdjYzc3NWEwYjMxN2VlOWNjY2E4ZDE0ZDRlOTdjZg"
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/json

[
    "welcome!"
]

無事にアクセスすることができました :smile_cat: OAuth 2.0 の仕様のざっくり把握できていれば特に迷うこと無くさくっと構築できますね。

STEP 4.4 トークンのリフレッシュ

認証で利用するトークンの有効期限が切れた場合はリフレッシュしましょう。有効期限が切れた場合、API は以下のレスポンスを返します。

$ http GET http://localhost:8000/app_dev.php/api/welcome \
"Authorization:Bearer OWRiNWU5OTJlMGIzOGE1OTRiNjQ2MGZkM2EwYTM1YWFjNjdjYzc3NWEwYjMxN2VlOWNjY2E4ZDE0ZDRlOTdjZg"
HTTP/1.1 401 Unauthorized
Cache-Control: no-store, private
Content-Type: application/json
Pragma: no-cache
WWW-Authenticate: Bearer realm="Service", error="invalid_grant", error_description="The access token provided has expired."

{
    "error": "invalid_grant",
    "error_description": "The access token provided has expired."
}

ではトークンをリフレッシュしてみます。

$ http POST http://localhost:8000/app_dev.php/oauth/v2/token \
grant_type=refresh_token \
refresh_token=MmMwODYwYjg1Y2VmZGQ4NTExYmQwOTE1NTg4YzhiOTY4N2EzZTcyZmI2MGI1MTVjMjA1NTMxMTE0Zjc0Zjg4MQ \ client_id=1_1avth1a6t18kc4coc4o48wkogsww0c0o4oko0oc4wsgc4848c4 \
client_secret=18u7clil6ww008480ko4occkkw80s4k4w0o0w8wgko44wwgkg0
HTTP/1.1 200 OK
Cache-Control: no-store, private
Content-Type: application/json
Pragma: no-cache

{
    "access_token": "MjhlZWNlMTFmNTA1ZmIwMWJkMzc0NDMyYmZmZWNkZDE1ZWZiNzYwM2I5MWU2MmNlMmY4YzQ1ZWJmZjYzMzQxMw",
    "expires_in": 3600,
    "refresh_token": "ZGU0YmQzYzA4MDY2MWI5NTU4YTE3NjU0NmUzN2I3MmM0MzEyZjMyNmMxZjhjOTkwZjY3YjRkNWM2YjE5NTU5Yg",
    "scope": null,
    "token_type": "bearer"
}

無事にリフレッシュに成功した模様です :smiley_cat: リフレッシュできたアクセストークンで API にアクセスしてみます。

$ http GET http://localhost:8000/app_dev.php/api/welcome \
"Authorization:Bearer MjhlZWNlMTFmNTA1ZmIwMWJkMzc0NDMyYmZmZWNkZDE1ZWZiNzYwM2I5MWU2MmNlMmY4YzQ1ZWJmZjYzMzQxMw"
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/json

[
    "welcome!"
]

アクセスできましたね :smile_cat:

STEP 4.5 有効期限が切れたトークンの削除

最後に有効期限が切れたトークンの削除を行います。これは FOSOAuthServerBundle が Symfony Command を用意してくれています。早速つかってみましょう。削除する前のデータです。 id = 1 のレコードが有効期限切れのトークンです。

mysql> select * from access_token;
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
| id | client_id | user_id | token                                                                                  | expires_at | scope |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
|  1 |         1 |       1 | OWRiNWU5OTJlMGIzOGE1OTRiNjQ2MGZkM2EwYTM1YWFjNjdjYzc3NWEwYjMxN2VlOWNjY2E4ZDE0ZDRlOTdjZg | 1481609172 | NULL  |
|  2 |         1 |       1 | MjhlZWNlMTFmNTA1ZmIwMWJkMzc0NDMyYmZmZWNkZDE1ZWZiNzYwM2I5MWU2MmNlMmY4YzQ1ZWJmZjYzMzQxMw | 1481613560 | NULL  |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
2 rows in set (0.00 sec)

では、Symfony Command を実行します。コマンド名は fos:oauth-server:clean です。

$ php app/console fos:oauth-server:clean

Removed 1 items from Access token storage.
Removed 0 items from Refresh token storage.
Removed 0 items from Auth code storage.
mysql> select * from access_token;
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
| id | client_id | user_id | token                                                                                  | expires_at | scope |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
|  2 |         1 |       1 | MjhlZWNlMTFmNTA1ZmIwMWJkMzc0NDMyYmZmZWNkZDE1ZWZiNzYwM2I5MWU2MmNlMmY4YzQ1ZWJmZjYzMzQxMw | 1481613560 | NULL  |
+----+-----------+---------+----------------------------------------------------------------------------------------+------------+-------+
1 row in set (0.00 sec)

無事に削除できました :smile_cat:

まとめ

FOSOAuthServerBundle の基本的な導入と Resource Owner Password Credentials を利用した認証について紹介しました。また、トークンのリフレッシュと削除についても触れました。便利なバンドルが OSS としてたくさん公開されていることも Symfony の魅力のひとつですよね。ぜひ FOSOAuthServerBundle も使ってみてください。

Symfony Advent Calendar も今日で折り返しですね :smile_cat: 明日からも楽しみです。

参考URL

以下を参考にしました。ありがとうございます。

この投稿は Symfony Advent Calendar 201613日目の記事です。