Symfony3でHWIOAuthBundleを使ったFacebookログイン

Symfony3.4でHWIOAuthBundleを使ってFacebookログインするところまでの手順を記載します。
ログインに成功するとFOSUserBundleのエンティティにFacebookのIDやアクセストークンが保存される状態になります。
でもその後の処理を考えると KnpUOAuth2ClientBundle を使うほうが良さそうです。

主な環境

  • LinuxまたはMacOS
  • PHP 5.6以上
  • Composer
  • Symfony 3.4
  • HWIOAuthBundle 0.6.1

前提

  • Facebookアプリの登録が完了し、app IDなどが取得済みであること
  • FOSUserBundleのインストール、設定、エンティティの準備が完了していること

Userエンティティに項目追加

src/AppBundle/Entity/User.php
    /**
     * @var string
     *
     * @ORM\Column(name="facebook_id", type="string", nullable=true)
     */
    private $facebookId;

    /**
     * @var string
     *
     * @ORM\Column(name="facebook_access_token", type="string", nullable=true)
     */
    private $facebookAccessToken;

    // setterとgetterも追加(bin/console d:g:entities AppBundle/Entity/User)

HWIOAuthBundleのインストールと設定

GitHubのドキュメントの通り

# コンソールで実行
composer require hwi/oauth-bundle php-http/guzzle6-adapter php-http/httplug-bundle
app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
        new Http\HttplugBundle\HttplugBundle(), // If you require the php-http/httplug-bundle package.
        new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
    );
}
app/config/routing.yml
hwi_oauth_redirect:
    resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
    prefix:   /connect

hwi_oauth_connect:
    resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
    prefix:   /connect

hwi_oauth_login:
    resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
    prefix:   /login

各種ymlの設定

parameters.ymlの設定

app/config/parameters.yml
parameters:
    # 以下を追加(*はFacebookアプリに応じて設定)
    facebook_id: *******************
    facebook_secret: *******************

config.ymlの設定

app/config/config.yml
# 以下を追加
httplug:
    plugins:
        logger: ~
    clients:
        default:
            factory: 'httplug.factory.curl'
        hwi_special:
            factory: 'httplug.factory.guzzle6'
            plugins: ['httplug.plugin.logger']
            config:
                timeout: 10
                verify_peer: false
                verify: false
                max_redirects: 1
                ignore_errors: false
                allow_redirects:
                    strict: false
                    protocols: ["http", "https"]

hwi_oauth:
    http:
        client: httplug.client.hwi_special
    firewall_names: [secured_area]
    fosub:
        username_iterations: 30
        properties:
            facebook: facebookId
    connect:
        confirmation: true
        account_connector: my.oauth_aware.user_provider.service
    resource_owners:
        facebook:
            type:            facebook
            client_id:       '%facebook_id%'
            client_secret:   '%facebook_secret%'
            scope:           "email, public_profile"
            infos_url:       "https://graph.facebook.com/me?fields=id,name,email,picture.type(large)"
            paths:
                email: email

# NelmioSecurityBundleを利用している場合は次の設定も追加
nelmio_security:
    external_redirects:
        # 追加
        whitelist:
            - facebook.com

security.ymlの設定

app/config/security.yml
firewalls:
        # 以下を追加
    secured_area:
        anonymous: true
        oauth:
            resource_owners:
                facebook:      "/login/check-facebook"
            login_path:        /login
            provider:                   fos_userbundle
            use_forward:       false
            failure_path:      /login

            oauth_user_provider:
                service: my.oauth_aware.user_provider.service

service.ymlの設定

app/config/service.yml
services:
        # 以下を追加
    my.oauth_aware.user_provider.service:
        class: AppBundle\Security\Core\User\OAuthUserProvider
        arguments:
            - '@fos_user.user_manager'
            - {facebook: facebookId}

OAuthUserProviderの作成

このファイルにFacebookログインした後の動作を記述します。
GitHubのドキュメントも参考にしてください。

src/AppBundle/Security/Core/User/OAuthUserProvider.php
<?php
namespace AppBundle\Security\Core\User;

use AppBundle\Entity\User;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserChecker;
use Symfony\Component\Security\Core\User\UserInterface;
/**
 * Class OAuthUserProvider
 */
class OAuthUserProvider extends BaseClass
{
    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $socialID = $response->getUsername();
        $user = $this->userManager->findUserBy(array($this->getProperty($response)=>$socialID));
        $email = $response->getEmail();
        if (null === $user) {
            $user = $this->userManager->findUserByEmail($email);

            if (null === $user || !$user instanceof UserInterface) {
                $user = $this->userManager->createUser();
                $user->setUsername($email);
                $user->setEmail($email);
                $user->setEnabled(true);
            }
            $service = $response->getResourceOwner()->getName();
            switch ($service) {
                case 'facebook':
                    $user->setFacebookId($socialID);
                    $user->setFacebookAccessToken($response->getAccessToken());
                    break;
            }

            $this->userManager->updateUser($user);
        } else {
            $checker = new UserChecker();
            $checker->checkPreAuth($user);
        }

        die('登録完了');

        return $user;
    }
}

ログイン画面HTMLの変更

app/Resources/FOSUserBundle/views/Security/login.html.twig
{# 次のリンクを追加 #}
<a href="{{ path('hwi_oauth_service_redirect', { 'service' : 'facebook' }) }}">Login with Facebook</a>

確認

# コンソールで実行
php bin/console server:run 0.0.0.0:8000
  1. ブラウザで http://localhost:8000/login にアクセス
  2. Login with FacebookリンクをクリックしてFacebookの画面に遷移
  3. Facebook内でログインやアプリの許可を行った後に登録完了画面が表示される
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.