Setting up HWIOAuthBundle in Symfony 4

Inleiding

De HWIOAuthBundle voegt ondersteuning toe voor het authenticeren van gebruikers via OAuth in Symfony. Met andere woorden kun je met HWIOAuthBundle zorgen dat gebruikers kunnen inloggen of aanmelden met onder andere Facebook, Google, Twitter of Dropbox. Voor de complete lijst zie documentatie van deze Bundel. Aangezien deze bundle behoorlijk technisch is en nogal wat mogelijkheden biedt heb ik besloten er een artikel over te schrijven. De documentatie van HWIOAuthBundle gaat in op een koppeling met de FOSUserBundle. Maar ik ga in dit artikel de OAuth bundle koppelen met onze eigen User en UserProvider class. Dit artikel is geschreven voor Symfony 4.3.

Hou er rekening mee dat je project op een domeinnaam met SSL encryptie moet draaien alvorens je kunt inloggen met Facebook. Hoe je dit voor elkaar krijgt wordt niet in dit artikel beschreven.

Voorbereiding

Om goed met met HWIOAuth aan de gang te kunnen hebben we een Symfony project nodig waarin al de nodige functionaliteit aanwezig is betreffende het aanmelden, inloggen of authenticeren van gebruikers. Daarom zullen we beginnen met een nieuw project waarin we vervolgens een User entity, een inlogformulier, een loginAuthenticator, een Registratie formulier en een tweetal profiel pagina's aanmaken. We starten met een nieuw Symfony 4.3 project met behulp van Composer:

composer create-project symfony/website-skeleton hwio
Open het .env configuratiebestand en stel de database parameters in. Laat doctrine de database aanmaken:
cd hwio
bin/console doctrine:database:create
Controller en homepage
Maak een controller aan:
bin/console make:controller Default
en verander de annotations zodat de route naar de homepage wijst:
class DefaultController extends AbstractController
{
    /**
     * @Route("/", name="homepage")
     */
    public function index()
    {
        return $this->render('default/index.html.twig', [
            'controller_name' => 'DefaultController',
        ]);
    }
}
User Entity
bin/console make:user
Druk bij alle vragen gewoon op enter.
bin/console make:entity User
Voeg twee properties toe:
1) username, string, 64, nullable: no.
2) facebookId, string 255, nullable: yes.
Open User.php in de editor en verander de getUsername() method zodat $this->username teruggegeven wordt in plaats van $this->email:
    public function getUsername(): string
    {
        return (string) $this->username;
    }
Voer de wijzigingen door naar de database:
bin/console doctrine:schema:update --force
En maak een gebruiker aan. Doe dit met bijvoorbeeld phpMyAdmin. Vul in bij roles: ['ROLE_USER]. Het wachtwoord kun je versleutelen met:
bin/console security:encode-password
De Output is iets als:
----------------- --------------------------------------------------------------------------------------------------- 
  Key                Value                                                                                              
 ------------------ --------------------------------------------------------------------------------------------------- 
  Encoder used       Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder                                      
  Encoded password   $argon2id$v=19$m=65536,t=4,p=1$WJFLKiKWsQmAx9YEg5biFg$CwPFWcsyemA5Npv1DpPxXWafzd7nr5NCXPDCB0Er16Q  
 ------------------ --------------------------------------------------------------------------------------------------- 
Kopiëer de complete versleutelde waarde en plak het in de password veld in phpMyAdmin.
LoginFormAuthenticator
bin/console make:auth
Kies optie 1 en vervolgens LoginFormAuthenticator.
Open LoginFormAuthenticator.php in de Security map en kijk naar de één na onderste functie. Voeg een redirect toe naar de homepage en haal de exception weg.
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
            return new RedirectResponse($targetPath);
        }
        
        return new RedirectResponse($this->urlGenerator->generate('homepage'));
    }
Navigatie
Open base.html.twig en voeg de navigatie toe in de body:
<ul>
    <li><a href="{{ path('homepage') }}">Homepage</a></li>
    {% if app.user %}
        {# <li><a href="{{ path('profile_show') }}">Profile</a></li> #}         
        <li><a href="{{ path('app_logout') }}">Logout</a></li>            
    {% else %}
        <li><a href="{{ path('app_login') }}">Login</a></li>
    {% endif %}
</ul>
Als het goed is kun je nu in- en uitloggen!
Registratie formulier
bin/console make:registration-form
Beantwoord de vragen met een enter. Open RegistrationFormType.php en voeg een formulier veld toe voor de username en een HiddenType field voor facebookId:
use Symfony\Component\Form\Extension\Core\Type\HiddenType;

class RegistrationFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username')
            ->add('facebookId', HiddenType::class)
            // ...
En voeg de username field ook toe in register.html.twig:
        {{ form_row(registrationForm.username) }}
Maak een link onderaan in de login.html.twig:
<a href="{{ path('app_register') }}">Register</a>
Profielpagina's
Als laatste voorbereiding voegen we een pagina toe die het profiel laat zien en een pagina waarin de gebruiker zijn profiel kan wijzigen. Voeg de volgende use statements en methods toe aan de SecurityController:
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use App\Form\ProfileType;
    /**
     * @Route("/profile", name="profile_show", methods={"GET"})
     * @Security("is_granted('ROLE_USER')")
     */
    public function showProfile(): Response
    {
        return $this->render('security/profile_show.html.twig', [
            'user' => $this->getUser(),
        ]);
    }

    /**
     * @Route("/profile/edit", name="profile_edit", methods={"GET","POST"})
     * @Security("is_granted('ROLE_USER')")
     */
    public function edit(Request $request): Response
    {
        $form = $this->createForm(ProfileType::class, $this->getUser());
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->getDoctrine()->getManager()->flush();

            return $this->redirectToRoute('profile_show');
        }

        return $this->render('security/profile_edit.html.twig', [
            'user' => $this->getUser(),
            'form' => $form->createView(),
        ]);
    }
Maak de volgende bestanden aan:
templates/security/profile_show.html.twig:
{% extends 'base.html.twig' %}

{% block title %}User{% endblock %}

{% block body %}
    <h1>Your Profile</h1>

    <table class="table">
        <tbody>
            <tr>
                <th>Username</th>
                <td>{{ user.username }}</td>
            </tr>
            <tr>
                <th>Email</th>
                <td>{{ user.email }}</td>
            </tr>
            <tr>
{#            <tr>
                <th>Facebook</th>
                <td>
                    {% if user.facebookId %}
                        Connected
                    {% else %}
                        Not connected <a href="{{ path('hwi_oauth_service_redirect', {'service': 'facebook' }) }}">Connect with Facebook</a>
                    {% endif %}
                </td>
            </tr>
#}            
        </tbody>
    </table>

    <a href="{{ path('profile_edit') }}">edit</a>

{% endblock %}
templates/security/profile_edit.html.twig:
{% extends 'base.html.twig' %}

{% block title %}Edit User{% endblock %}

{% block body %}
    <h1>Edit User</h1>

    {{ form_start(form) }}
        {{ form_widget(form) }}
        <button>Update</button>
    {{ form_end(form) }}

    <a href="{{ path('profile_show') }}">back</a>
{% endblock %}
src/Form/ProfileType.php:
<?php

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ProfileType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username')
            ->add('email')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}
Voeg als laatste een link in de navigatie toe naar de profile-show pagina door deze uit het commentaar blok te halen in base.html.twig. De login, logout, registratie én de profiel pagina's zouden nu moeten werken. Gefeliciteerd!

UserProvider

In de voorbereiding op de integratie van de HWIOAuthBundle maken we ook alvast een eigen UserProvider. Een UserProvider is verantwoordelijk voor het laden en verversen van de gegevens van de ingelogde gebruiker. Maak een nieuw php bestand aan in de src/Security directory met de naam UserProvider.php en plak de volgende inhoud in het bestand:

<?php

namespace App\Security;

use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;


class UserProvider implements UserProviderInterface
{
    private $em;
    private $property = 'email';

    public function __construct(EntityManagerInterface $em) {
        $this->em = $em;
    }
    /**
     * Symfony calls this method if you use features like switch_user
     * or remember_me.
     *
     * If you're not using these features, you do not need to implement
     * this method.
     *
     * @return UserInterface
     *
     * @throws UsernameNotFoundException if the user is not found
     */
    public function loadUserByUsername($username)
    {
        $repository = $this->em->getRepository(User::class);
        
        if (null !== $this->property) {
            $user = $repository->findOneBy([$this->property => $username]);
        } else {
            if (!$repository instanceof UserLoaderInterface) {
                throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, \get_class($repository)));
            }
            $user = $repository->loadUserByUsername($username);
        }
        
        if (null === $user) {
            throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
        }
        
        return $user;
    }

    /**
     * Refreshes the user after being reloaded from the session.
     *
     * When a user is logged in, at the beginning of each request, the
     * User object is loaded from the session and then this method is
     * called. Your job is to make sure the user's data is still fresh by,
     * for example, re-querying for fresh User data.
     *
     * If your firewall is "stateless: true" (for a pure API), this
     * method is not called.
     *
     * @return UserInterface
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', User::class));
        }
        
        $repository = $this->em->getRepository(User::class);
        
        if ($repository instanceof UserProviderInterface) {
            $refreshedUser = $repository->refreshUser($user);
        } else {
            $refreshedUser = $repository->find($user->getId());
            if (null === $refreshedUser) {
                throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($user->getId())));
            }
        }
        
        return $refreshedUser;
    }

    
    /**
     * Tells Symfony to use this provider for this User class.
     */
    public function supportsClass($class)
    {
        return User::class === $class;
    }
}
Om er voor te zorgen dat Symfony onze UserProvider gaat gebruiken moeten we de instellingen wijzigen in de provider sectie in security.yaml:
    providers:
        app_user_provider:
            id: App\Security\UserProvider
( Haal de entity, class en property regels weg) Gefeliciteerd je hebt zojuist je eigen UserProvider gemaakt. Deze gaan we straks verder uitbreiden zodat we ook een User kunnen laden met Oauth.

Facebook App

Om met Facebook te kunnen verbinden moeten we in developers.facebook een nieuwe app aanmaken en wat instellingen verrichten. Klik op Add a new App en geef je app een naam. Onder add a product kies voor "Facebook Login" en klik op Setup.
Klik in het menu op Facebook Login en dan op Settings. Vul in bij Valid OAuth Redirect URIs de return URL's. Deze URL's moeten altijd beginnen met https:// gevolgd door uw domeinnaam. HWIO gebruikt twee URL's. De eerste URL wordt gebruikt voor als de gebruiker nog niet ingelogd is, de andere wordt gebruikt als de gebruiker wel ingelogd is. In het laatste geval kan zijn login direct gekoppeld worden aan zijn facebook account. De eerste URL moet eindigen op /login/check-facebook en de tweede op /connect/service/facebook. Het zou zoiets moeten worden als:

https://www.mydomain.com/login/check-facebook & https://www.mydomain.com/connect/service/facebook
Klik op Save Changes.

facebook

HWIOAuthBundle

Nu gaan we de HWIOAuthBundle installeren:

composer require php-http/guzzle6-adapter:^1.1
composer require php-http/httplug-bundle
en kies Yes om het script uit te laten voeren
composer require hwi/oauth-bundle
en kies Yes om het script uit te laten voeren.
Bij deze laatste kreeg ik een foutmelding van een service die afhankelijk is van een niet bestaande service. Geen probleem, dit gaan we oplossen! Voeg onderstaande oauth sectie toe onder firewalls: main: in security.yaml:
    firewalls:
        ...
        
        main:
            oauth:
                resource_owners:
                    facebook: "/login/check-facebook"
                oauth_user_provider:
                    service: App\Security\UserProvider 
                login_path:   /login
                use_forward:  false
                failure_path: /login
Voeg vervolgens de volgende route toe in hwi_oauth_routing.yaml:
facebook_login:
    path: /login/check-facebook
Ga terug naar de facebook Login app settings en klik links in het menu op Settings en dan op Basic. Kopiëer de App Id en Secret en plak deze in .env achter FB_ID= en FB_SECRET=.
###> hwi/oauth-bundle ###
FB_ID=xxxxxxxxxxxxxxx
FB_SECRET=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
###< hwi/oauth-bundle ###
Nu zouden we kunnen proberen in te loggen. Er zal echter een foutmelding komen dat onze UserProvider de OauthAwareUserProviderInterface class moet implementeren alvorens HWIOAuthBundle er mee kan werken.

facebook

Breid de UserProvider uit met de benodigde use statements en implementeer OauthAwareUserProviderInterface:

use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;

class UserProvider implements UserProviderInterface, OAuthAwareUserProviderInterface
Vervolgens worden er drie methods toegevoegd. loadUserByOAuthUserResponse() wordt aangeroepen door HWIOAuthBundle om een gebruiker in te loggen die zich aanmeldt met Facebook.
    /**
     * Loads the user by a given UserResponseInterface object.
     *
     * @param UserResponseInterface $response
     *
     * @return UserInterface
     *
     * @throws UsernameNotFoundException if the user is not found
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $repository = $this->em->getRepository(User::class);
        $username = $response->getUsername();
        
        if (null === $username) {
            throw new AccountNotLinkedException("Username is empty.");
        }

        $user = $repository->findOneBy(array($this->getResourceOnwerPropertyName($response) => $username));
        
        if (null === $user) {
            
            // now that we did not find a user on the id of the service we will try to find the email of the user
            $user = $repository->findOneBy(array('email' => $response->getEmail()));
            
            if (null === $user) {
                throw new AccountNotLinkedException(sprintf("User '%s' not found.", $username)); // redirects to registration form
            }
            
            // connect user 
            $this->setIdForResourceOwner($user, $response);
            
            $this->em->flush();
        }
        
        return $user;
    }

    /**
     * Sets facebookId or googleId etc in the User entity.
     * Requires that your User entity has an Id field for every resourceOwner that you use.
     * 
     * @param UserInterface $user
     * @param UserResponseInterface $response
     */
    private function setIdForResourceOwner(UserInterface $user, UserResponseInterface $response)
    {
            $service = $response->getResourceOwner()->getName();
            $setter = 'set'.ucfirst($service).'Id';
            $user->$setter($response->getUsername());
    }
    
    /**
     * @param UserResponseInterface $response
     * 
     * @return string with the name of the property that can be accessed in the User entity e.g. facebookId or googleId
     */
    private function getResourceOnwerPropertyName(UserResponseInterface $response) : string
    {
            return $response->getResourceOwner()->getName().'Id';
    }
Vervolgens maken we een snelkoppeling om via Facebook in te loggen in login.html.twig:
<a href="{{ path('hwi_oauth_service_redirect', {'service':'facebook'}) }}">Login with Facebook</a><br>
Je kunt nu proberen om via Facebook in te loggen. Is dat gelukt? Dan zal er een uniek ID ingevuld zijn in de database kolom facebookId. Het account is nu gekoppeld aan een Facebook account!

Registreren

Stel nu dat een nieuwe gebruiker zich wil registreren met behulp van zijn Facebook account. De gebruiker kan dan niet gekoppeld worden aan zijn Facebook account voordat er een account is aangemaakt in onze eigen applicatie. Het zou handig zijn als het Registratie formulier zoveel mogelijk wordt ingevuld met de account gegevens (username en email) van het Facebook account. Begin met het kopieren van de Login with Facebook link uit login.html.twig naar register.html.twig zodat de gebruiker daar ook kan koppelen met Facebook.

Om uit te testen wat er nu gebeurt moet je eerst even je eigen account verwijderen uit de database. Je bent dan immers een nieuwe gebruiker.
Nadat je je account verwijderd hebt kun je nogmaals proberen in te loggen met je Facebook account. Je komt dan terug op de loginpagina met de foutmelding Account could not be linked correctly. Deze foutmelding gaan we afvangen en dan gaan we de gebruiker doorsturen naar de Registratie pagina. Voeg het volgende use statement toe aan SecurityController.php:
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
en vervang de login method voor het volgende:
    /**
     * @Route("/login", name="app_login")
     */
    public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
    {
        // get the login error if there is one
        $error = $authenticationUtils->getLastAuthenticationError();
        // last username entered by the user
        $lastUsername = $authenticationUtils->getLastUsername();
        
        if ($error instanceof AccountNotLinkedException) {
            $key = time();
            $session = $request->getSession();
            if (!$session->isStarted()) {
                $session->start();
            }

            $session->set('_hwi_oauth.registration_error.'.$key, $error);

            return $this->redirectToRoute('app_register', array('key' => $key));
        }

        return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
    }
Open nu RegistrationController.php en vervang de complete inhoud:
<?php

namespace App\Controller;

use App\Entity\User;
use App\Form\RegistrationFormType;
use App\Security\LoginFormAuthenticator;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;

class RegistrationController extends Controller
{
     /**
     * @Route("/register/{key}", name="app_register")
     */
    public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $authenticator, $key = false): Response
    {
        $user = new User();
        
        if(false !== $key && $request->getMethod() == 'GET') {
            $user = $this->getUserFromResourceOwner($request, $key);
        }

        $form = $this->createForm(RegistrationFormType::class, $user);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // encode the plain password
            $user->setPassword(
                $passwordEncoder->encodePassword(
                    $user,
                    $form->get('plainPassword')->getData()
                )
            );

            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($user);
            $entityManager->flush();

            // do anything else you need here, like send an email

            return $guardHandler->authenticateUserAndHandleSuccess(
                $user,
                $request,
                $authenticator,
                'main' // firewall name in security.yaml
            );
        }

        return $this->render('registration/register.html.twig', [
            'registrationForm' => $form->createView(),
        ]);
    }

    /**
     * Get a resource owner by name.
     *
     * @param string $name
     *
     * @return ResourceOwnerInterface
     *
     * @throws NotFoundHttpException if there is no resource owner with the given name
     */
    protected function getResourceOwnerByName($name)
    {
        foreach ($this->getParameter('hwi_oauth.firewall_names') as $firewall) {
            $id = 'hwi_oauth.resource_ownermap.'.$firewall;

            if (!$this->container->has($id)) {
                continue;
            }

            $ownerMap = $this->container->get($id);
            if ($resourceOwner = $ownerMap->getResourceOwnerByName($name)) {
                return $resourceOwner;
            }
        }

        throw new NotFoundHttpException(sprintf("No resource owner with name '%s'.", $name));
    }
    
    /**
     * 
     * @param Request $request
     * @param string $key
     * @return User
     * @throws \RuntimeException
     */
    private function getUserFromResourceOwner(Request $request, string $key) : User
    {
        $session = $request->getSession();
        if (!$session->isStarted()) {
            $session->start();
        }

        $error = $session->get('_hwi_oauth.registration_error.'.$key);
        $session->remove('_hwi_oauth.registration_error.'.$key);

        if (!$error instanceof AccountNotLinkedException) {
            throw new \RuntimeException('Cannot register an account.', 0, $error instanceof \Exception ? $error : null);
        }

        $userInformation = $this
            ->getResourceOwnerByName($error->getResourceOwnerName())
            ->getUserInformation($error->getRawToken())
        ;
        
        $setter = 'set'.ucfirst($error->getResourceOwnerName()).'Id';

        $user = new User();
        $user->setEmail($userInformation->getEmail());
        $user->setUsername($userInformation->getRealName());
        $user->$setter($userInformation->getUsername());
        
        return $user;
    }
}
Als je nu op de sign up with Facebook link klikt op de Registratie pagina dan wordt je netjes doorgestuurd naar het registratieformulier welke dan deels voor je ingevuld wordt. Er zit in dit registratie formulier een hidden field waarin het facebookId doorgegeven wordt.

Connecting users

Om gebruikers die ingelogd zijn op hun profiel pagina hun account te verbinden met hun facebook account zullen we nog een aantal stappen moeten nemen. Als eerste gaan we de UserProvider class wederom uitbreiden en implementeren we HWIOAuthBundle's AccountConnectorInterface.

use HWI\Bundle\OAuthBundle\Connect\AccountConnectorInterface;

class UserProvider implements UserProviderInterface, AccountConnectorInterface, OAuthAwareUserProviderInterface
Vervolgens wordt er nog een method toegevoegd:
    /**
     * Connects the response to the user object.
     *
     * @param UserInterface         $user     The user object
     * @param UserResponseInterface $response The oauth response
     */
    public function connect(UserInterface $user, UserResponseInterface $response)
    {
        $username = $response->getUsername();
        
        if (null === $username) {
            throw new AccountNotLinkedException("Username is empty.");
        }
            
        // connect user 
        $this->setIdForResourceOwner($user, $response);

        $this->em->flush();
        
        return $user;
    }
Vervolgens configureren we HWIOAuthBundle zo dat we aangeven dat onze gebruikers hun account kunnen verbinden met hun Facebook account. Dat doen we door het onderstaande toe te voegen aan hwi_oauth.yaml.
    connect:
        confirmation: true
        account_connector: App\Security\UserProvider
Open profile_show.html.twig. Haal daar de kommentaartekens weg bij de tabel-rij "Facebook". Wanneer je nu op de profiel pagina kijkt dan zie je Facebook Connected staan. Zet nu de kolom facebookId weer op null in de database en ververs de profiel pagina. Klik vervolgens op de link Connect with Facebook. Er komt een Pagina in beeld met de vraag of je je Facebook account wilt verbinden. Wil je deze confirmatie-pagina overslaan dan kun je confirmation: op false zetten in hwio_auth.yml. Druk je op de knop dan wordt je account verbonden met je Facebook account. Indien de vertaling niet werkt dan kun je dat oplossen door de cache te legen. Nadat je je account hebt verbonden met je Facebook account krijg je nog een bevestiging. Beide templates kunnen natuurlijk overschreven worden door in de map templates de volgende structuur aan te brengen:
  • templates
    • bundles
      • HWIOAuthBundle
        • Connnect
          • connect_confirm.html.twig
          • connect_success.html.twig
De originele twig bestanden vindt je hier in de HWIOAuthBundle.

Andere providers

Naast Facebook kunnen ook andere providers toegevoegd worden. We doen dit als voorbeeld met Google. Ga naar Google developers. Klik in het menu op Inloggegevens en vervolgens op de blauwe knop Inloggegevens maken en op ClientId OAuth. Kies voor Webapp en geef een naam op voor deze toepassing. (het handigste is iets als de domeinnaam waarop dit gebruikt gaat worden). Bevestig door op Maken te klikken. Er wordt een popupscherm getoond met uw clientId en Secret. Maak twee nieuwe variabelen aan met deze twee waardes in het .env bestand, bijvoorbeeld GO_ID=[clientId] en GO_SECRET=[Secret]. Klik in het OAuth 2.0-client-ID's overzicht op de naam van het zojuist aangemaakte item om de instellingen te bewerken. Vul in bij Geautoriseerde omleidings-URI's de twee return URL'S:

https://www.mydomain.com/login/check-google & https://www.mydomain.com/connect/service/google
Klik op Opslaan.

Zet de instellingen in hwio_auth.yaml onder resource_owners:

        google:
            type:                google
            client_id:           '%env(GO_ID)%'
            client_secret:       '%env(GO_SECRET)%'
            scope:               "email profile"
Voeg een nieuwe route toe aan hwi_oauth_routing.yaml:
google_login:
    path: /login/check-google
Voeg in security.yaml onder resource_owners:
                    google: "/login/check-google"
Maak een link om in te loggen in login.html.twig en register.html.twig:
<a href="{{ path('hwi_oauth_service_redirect', {'service':'google'}) }}">Login with Google</a><br>
Voeg een property toe aan de User entity:
bin/console make:entity User
googleId, string 255, nullable: yes.
bin/console doctrine:schema:update --force
en voeg nog een HiddenType field googleId toe aan het registratie formulier in RegistrationFormType.php
            ->add('googleId', HiddenType::class)
Als laatste kun je nog de Profile pagina bewerken zodat er ook met Google kan worden verbonden.

Reacties

Om een reactie te plaatsen kun je jezelf eenmalig registeren of je kunt hier inloggen.