Video Tutorial Social Authentication on Symfony
Welcome to this video where I invite you to discover how to set up authentication via social networks using the KnpUOAuth2ClientBundle bundle.
00:00 Introduction and configuration of the symfony application
08:40 Using KnpUOAuth2ClientBundle
36:08 Get the email in the case of github
The stages of implementation
First, you will have to install the bundle as well as the client you want to set up.
composer require knpuniversity / oauth2-client-bundle
composer require league / oauth2-github
Then we will create an OAuth application on the social network that interests us and recover the id and the secret key that we put in our environment variable.
GITHUB_ID = c39f620296adf6722a5c
GITHUB_SECRET = 37eaa24ec6d843e52fa80bbc2ba9055e475db8e4
We configure our client by modifying the file config / packages / knpu_oauth2_client.yaml
knpu_oauth2_client:
clients:
github:
type: github
client_id: '% env (GITHUB_ID)%'
client_secret: '% env (GITHUB_SECRET)%'
redirect_route: oauth_check
redirect_params:
service: github
This customer can then be retrieved through the service KnpU OAuth2ClientBundle Client ClientRegistry
. It will also be used to redirect the user to the authentication portal.
/ **
* @Route ("/ connect / github", name = "github_connect")
* /
public function connect (ClientRegistry $ clientRegistry): RedirectResponse
{
/ ** @var GithubClient $ client * /
$ client = $ clientRegistry-> getClient ('github');
return $ client-> redirect (('read: user', 'user: email'));
}
To manage the return, we will use a route that will be intercepted by our authenticator.
# config / routes.yaml
oauth_check:
path: / oauth / check / {service}
controller: Symfony Bundle FrameworkBundle Controller TemplateController
``
Finally, all we have to do is create the authenticator which will intercept the request and authenticate the user.
`` php
router = $ router;
$ this-> clientRegistry = $ clientRegistry;
$ this-> userRepository = $ userRepository;
}
public function start (Request $ request, AuthenticationException $ authException = null)
{
return new RedirectResponse ($ this-> router-> generate ('app_login'));
}
/ **
* If the route corresponds to the expected one, then we trigger this authenticator
** /
public function supports (Request $ request)
{
return 'oauth_check' === $ request-> attributes-> get ('_ route') && $ request-> get ('service') === 'github';
}
public function getCredentials (Request $ request)
{
return $ this-> fetchAccessToken ($ this-> getClient ());
}
/ **
* Retrieves the user from the AccessToken
*
* @param AccessToken $ credentials
* /
public function getUser ($ credentials, UserProviderInterface $ userProvider)
{
/ ** @var GithubResourceOwner $ githubUser * /
$ githubUser = $ this-> getClient () -> fetchUserFromToken ($ credentials);
// We get the user's email (specific to github)
$ response = HttpClient :: create () -> request (
'GET',
'https://api.github.com/user/emails',
(
'headers' => (
'authorization' => "token {$ credentials-> getToken ()}"
)
)
);
$ emails = json_decode ($ response-> getContent (), true);
foreach ($ emails as $ email) {
if ($ email ('primary') === true && $ email ('verified') === true) {
$ data = $ githubUser-> toArray ();
$ data ('email') = $ email ('email');
$ githubUser = new GithubResourceOwner ($ data);
}
}
if ($ githubUser-> getEmail () === null) {
throw new NotVerifiedEmailException ();
}
return $ this-> userRepository-> findOrCreateFromGithubOauth ($ githubUser);
}
public function onAuthenticationFailure (Request $ request, AuthenticationException $ exception)
{
if ($ request-> hasSession ()) {
$ request-> getSession () -> set (Security :: AUTHENTICATION_ERROR, $ exception);
}
return new RedirectResponse ($ this-> router-> generate ('app_login'));
}
public function onAuthenticationSuccess (Request $ request, TokenInterface $ token, string $ providerKey)
{
$ targetPath = $ this-> getTargetPath ($ request-> getSession (), $ providerKey);
return new RedirectResponse ($ targetPath?: '/');
}
private function getClient (): GithubClient {
return $ this-> clientRegistry-> getClient ('github');
}
}
And There you go ! All you have to do is make the code more generic in order to adapt it to other social networks;)