Back to Blog
Feb 23rd, 2016

Introducing KnpUOAuth2ClientBundle: Making Social Easy

Written by weaverryan

Edit
Introducing KnpUOAuth2ClientBundle: Making Social Easy

tl;dr KnpUOAuth2ClientBundle has hit 1.0 - use it for all sorts of "social connect" functionality in Symfony without a headache.

Logging in with Facebook, connecting with your Twitter account, or registering via GitHub - integrating with "Social" networks is now a standard feature of many sites. But in Symfony, it wasn't easy enough to build this. The most popular solution - HWIOAuthBundle - is good and has a lot of built-in OAuth providers. But, it's also confusing to use and frustrating to extend. I know, we use it here on KnpUniversity. I wanted a better option.

Today, I'm thrilled to announce the 1.0 release of KnpUOAuth2ClientBundle, which is built on the backs of the wonderful OAuth 2.0 Client Library from the PHP League. In other words: take the best from the PHP world and make it sing inside of Symfony.

Simple to use: You're in Control

In a nut-shell, here's how it works:

1) You configure a provider. This gives you a "client" service:

# app/config/config.yml
knpu_oauth2_client:
    clients:
        # will create a service: knpu.oauth2.client.facebook_main
        facebook_main:
            type: facebook
            client_id: %facebook_app_id%
            client_secret: %facebook_app_secret%
            # see below
            redirect_route: connect_facebook_check

2) Use the new service to redirect to Facebook and do some cool stuff when the user comes back:

// ...

class FacebookController extends Controller
{
    /**
     * Link to this controller to start the "connect" process
     *
     * @Route("/connect/facebook")
     */
    public function connectAction()
    {
        return $this->get('oauth2.registry')
            ->getClient('facebook_main')
            ->redirect();
    }

    /**
     * Facebook redirects to back here afterwards
     *
     * @Route("/connect/facebook/check", name="connect_facebook_check")
     */
    public function connectCheckAction(Request $request)
    {
        $client = $this->get('oauth2.registry')
            ->getClient('facebook_main');

        $user = $client->fetchUser();
        // do something with all this new power!
        $user->getFirstName();
    }
}

Simple, right?

Guard Auth Integration

You can use this new power to just "get some user information" or actually authenticate your user. For that, the bundles comes with integration for Symfony's Guard security. This includes the ability to "finish registration": i.e. redirect a new user to a registration form before logging them in. See the tutorial below for more info.

Tutorial & Documentation

Ready to try it? Let's do this!

A) Official Documentation

B) Example Project

C) Tutorial (coming soon)

Like everything, this is a community project meant to make our collective lives easier (and honestly, more fun). If you have some ideas or problems - please open an issue.

Cheers!

94 Comments

Sort By
Login or Register to join the conversation
Kasal avatar Kasal hace 1 año

Hi there,

I want to integrate Facebook, Google, and Twitter. I'm confused about which bundle I use.

| Reply |

Hi!

All you need it main KnpOauth2ClientBundle and official clients libraries you want to use, which you can find in the bundle readme file

Cheers!

1 | Reply |

Thanks but i'm getting this error with :

#[Route(path: '/connect/facebook', name: 'app_facebook_start')]
    public function connectAction(ClientRegistry $clientRegistry)
    {
        // on Symfony 3.3 or lower, $clientRegistry = $this->get('knpu.oauth2.registry');

        // will redirect to Facebook!
        $client = $clientRegistry->getClient('facebook_main');
        // dd($client);
        return $client->redirect([
            'public_profile', 'email' // the scopes you want to access
        ]);
        
            
    }

It says the redirect method requires 2 arguments but when i click on the Facebook connect button it redirects me to a blank page. What's wrong?

| Reply |

have you added correct FB credentials to .env file? also you can search the clue why it's so in the address bar on redirect, FB should pass error string in it

Cheers

1 | Reply |

Hi Sadikoff,
Thanks and sorry for the late response!

Yeah! It works but I am across another issue. When I click on the button connect with Facebook I see the email of the user is null while I get the name, first_name, last_name and the id .
Here is my Facebook Authenticator :

<?php

namespace App\Security;

use App\Entity\User; // your user entity
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;

class FacebookAuthenticator extends OAuth2Authenticator implements AuthenticationEntrypointInterface
{
    private $clientRegistry;
    private $entityManager;
    private $router;

    public function __construct(ClientRegistry $clientRegistry, EntityManagerInterface $entityManager, RouterInterface $router)
    {
        $this->clientRegistry = $clientRegistry;
        $this->entityManager = $entityManager;
        $this->router = $router;
    }
    public function supports(Request $request): ?bool
    {
        // continue ONLY if the current ROUTE matches the check ROUTE
        return $request->attributes->get('_route') === 'connect_facebook_check';
    }
    public function authenticate(Request $request): Passport
    {
        $client = $this->clientRegistry->getClient('facebook_main');
        $accessToken = $this->fetchAccessToken($client);
        dd($client);
        return new SelfValidatingPassport(
            new UserBadge($accessToken->getToken(), function () use ($accessToken, $client) {
                /** @var FacebookUser $facebookUser */
                $facebookUser = $client->fetchUserFromToken($accessToken);
                dd($facebookUser);
                $email = $facebookUser->getEmail();
                // dd($email);
                // 1) have they logged in with Facebook before? Easy!
                $existingUser = $this->entityManager->getRepository(User::class)->findOneBy(['facebookId' => $facebookUser->getId()]);
                // dd($existingUser);
                if ($existingUser) {
                    return $existingUser;
                } else {
                    // 2) do we have a matching user by email?
                    $user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]);
                    if (!$user) {
                        /** @var User $user */
                        $user = new User();
                        $user->setEmail($email);
                    }
                }



                // 3) Maybe you just want to "register" them by creating
                // a User object
                $user->setFacebookId($facebookUser->getId());
                $this->entityManager->persist($user);
                $this->entityManager->flush();

                return $user;
            })
        );
    }


    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        // change "app_homepage" to some route in your app
        $targetUrl = $this->router->generate('app_compte_annonceur');

        return new RedirectResponse($targetUrl);

        // or, on success, let the request continue to be handled by the controller
        //return null;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        $message = strtr($exception->getMessageKey(), $exception->getMessageData());

        return new Response($message, Response::HTTP_FORBIDDEN);
    }
    /**
     * Called when authentication is needed, but it's not sent.
     * This redirects to the 'login'.
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        return new RedirectResponse(
            $this->router->generate('app_login')
        );
    }

    // ...

}

| Reply |

woh...sorry missed your answer, hope you solved the issue?

Cheers.

1 | Reply |

Yeah it is working now but i am stuck with the Twitter oauth 2. You can see the description of my issue : [https://stackoverflow.com/questions/77725780/error-fetching-oauth-credentials-missing-required-parameter-code-verifier](twitter oauth2 issue)

| Reply |

Hey @Kasal

Twitter oauth2 is a pretty complex situation, especially because twitter has paid API and this provider is not fully maintained anymore. I'd suggest to check https://github.com/smolblog/oauth2-twitter this docs, there is an example how to use properly the provider, hope it will help you solve this issue

Cheers!

1 | Reply |

Hello @sadikoff,

Thankyou for your great response! I'm using this provider. I have figure out with this issue by generating the code_verifier and include it in the auth request as you can see here but i'm encountering with another which is in the comment.

Cheers!

| Reply |
t5810 avatar t5810 hace 1 año

Hi

Is there any chance that this article will be updated at some point?

| Reply |

Hey,

That is a good question... but does it needs an update? Honestly there is no so much technical details about oauth, so in most cases you can just rely on https://github.com/knpuniversity/oauth2-client-bundle documentation and you will get a good working code =)

PS I already did so several times ;)

Cheers!

| Reply |

Hi

I am trying to make my login form to work with github also using knpuniversity/oauth2-client-bundle, but I am stuck, so if you can help me it would be great:

Here is my knpu_oauth2_client.yaml file:

knpu_oauth2_client:
    clients:
       
        github:
            type: github
            client_id: '%env(OAUTH_GITHUB_CLIENT_ID)%'
            client_secret: '%env(OAUTH_GITHUB_CLIENT_SECRET)%'
            redirect_route: connect_github_check
            redirect_params: { }
           

I have added the OAUTH_GITHUB_CLIENT_ID and the OAUTH_GITHUB_CLIENT_SECRET and their values in my .env file

I have created the following controller:

...
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
class GithubController extends AbstractController
{

    #[Route("/connect/github", name: "github_connect")]
    public function connect(ClientRegistry $clientRegistry)
    {
        /** @var GithubClient $client */
        $client = $clientRegistry->getClient('github');

        return $client->redirect(['read:user', 'user:email']);
    }
    
    #[Route("connect/github/check", name: "connect_github_check")]
    public function connectCheckAction(Request $request, ClientRegistry $clientRegistry)
    {

        /** @var GithubClient $client */
        $client = $clientRegistry->getClient('github_main');

        try {
            // The exact class depends on which provider you're using
            // This class may not be correct one
            /** @var GithubClient $user */
            $user = $client->fetchUser();

            // do something with all this new power!
            // e.g. $name = $user->getFirstName();
            var_dump($user);
            die;
            // ...
        } catch (IdentityProviderException $e) {
            // something went wrong!
            // probably you should return the reason to the user
            var_dump($e->getMessage());
            die;
        }
    }

And in my login link I have created the link above of my login form:

<a href="{{ path('github_connect') }}">Sign in with Github</a>

On the end, in my app in Github the Authorization Callback URL is set to:
http://127.0.0.1:8000/connect/github/check

Clicking on the link, I am redirected on GitHub page, but there I am presented with 404 error, that is I am not reaching the github login form at all. Can you tell me what I am doing wrong? If possible, can you tell me what else should be done after this step?

I guess that I should authorize the user, with an authenticator in Security folder or...?

Any help will be deeply appreciated.

| Reply |

Hey, hey,

Sorry for the long delay with reply, I was on vacation and was not able to answer, do you still have an issue with it? Or you found how to make it work?

Cheers!

| Reply |

Hi Sadikoff
I hope you had great time on your vacation.
No, the issue remained, I simply get stuck there, and I have no idea how to proceed further. It is a project in which I test my Symfony knowledge, but it is a disappointing to not be able to find solution, even I spent 20+ hours in total so far.

Regards,

| Reply |

as I see you have some errors in code block you pasted,

#[Route("connect/github/check", name: "connect_github_check")]

you should have a / before connect word, and below in function client name should be github

of course easier will be to see the code, so if you have a GH repository with it, I can help you better =)

Cheers!

| Reply |

Hi

Sorry about my delayed response.

Unfortunately, the fixes above didn't worked.

I created a repository on GitHub, so how can I send you the invitation?
I would really like to know the mistakes that I did, so please point everything that I have done wrong It would help me a lot.

Thanks in advance.
Regards.

| Reply |

You can find me on github at https://github.com/sadikoff

Cheers.

| Reply |
Default user avatar Florian hace 4 años edited

Using it with Google. I'm trying to get the user refresh token, unfortunately $credentials->getRefreshToken() returns null in my GoogleAuthenticator::getUser(AccessToken $credentials, UserProviderInterface $userProvider) method.

I set access_type: 'offline' in the knpu_oauth2_client.clients.google configuration.

Am I missing something ?

| Reply |

Hey Florian,

Hm, it sounds like you did everything correct. But from the provider's docs I see:

It is important to note that the refresh token is only returned on the first request after this it will be null. You should securely store the refresh token when it is returned

Is it chance that we're not talking about the 1st request? It sounds like the case. If you ever need to get a new refresh token you can request one by forcing the consent prompt, see the docs for more info:
https://github.com/thephple...

Does it helps?

Cheers!

2 | Reply |

Hello Victor,

Sorry I'm late. You're right, the refresh token is only returned at the first authorization.

Thanks a lot!

| Reply |

Hey Florian,

Great! Thanks for replying that it helps you!

Cheers!

| Reply |
Lijana Z. avatar Lijana Z. hace 4 años edited

Just integegrated with google. Works so cool. But I dont get why in google documentation they say that we need javascript. Am I doing something wrong then?

https://developers.google.com/identity/sign-in/web/backend-auth

var xhr = new XMLHttpRequest();<br />xhr.open('POST', 'https://yourbackend.example.com/tokensignin');<br />xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');<br />xhr.onload = function() {<br /> console.log('Signed in as: ' + xhr.responseText);<br />};<br />xhr.send('idtoken=' + id_token);

| Reply |

Hey Lijana Z.

It's probably that Google's API changed since this tutorial was written. What I understood from the link you posted is that you need to get the user's token from Google and then use that instead of the user id.

Cheers!

| Reply |

I dont know, but with JS I did nothing, just did same way as with fb, just set 2 parameters in config - secret key and something else and, and reused lot of code from facebook login and it looks like is working.

| Reply |
Lijana Z. avatar Lijana Z. hace 4 años edited

Here also I do not understand what do they mean by clients:

"Use unique short-term tokens on clients."
https://developers.facebook.com/docs/facebook-login/security#codeflow

Can you explain? Is a client my whole app or is client is the web browser with html, JS? I do not use tokens on frontend side so maybe I dont need to worry.

If the client is our whole application - backend and frontend and server is facebook
Is this taken care of by this bundle?

I just use

public function getCredentials(Request $request)
    {
        // this method is only called if supports() returns true

        return $this->fetchAccessToken($this->getFacebookClient());
    }```


token here in authenticator class by your example. Should I do anything extra?
| Reply |

Hey Lijana Z.!

I think they're referring to JavaScript as the "client" in this case. And they're saying "Don't get a long-term token on your server and then pass it to JavaScript".

So, you're probably good - you're fetching the token form the bundle and then always keeping it on the server (not passing it to JavaScript). You're also using the more-secure "code flow". And also, the token you get from this bundle is not a long-lived token anyways (https://developers.facebook....

Cheers!

1 | Reply |
Lijana Z. avatar Lijana Z. hace 4 años

https://developers.facebook...

2. Check to make sure a user access token is still valid
In addition, when a person logged in with Facebook Login is actively using an app or website, developers should check that the user access token is still valid by making an API call or by checking permissions. Be sure to log the user out when their access token is invalidated.

So this bundle is doing this in getAccessToken() ? Inside this function variables are named $expectedState and $actualState but maybe thats is doing this part which I quoted?

If not, then maybe it is still done somewhere else in the bundle and I dont need to do this?

| Reply |

Hi there!

I don't know much about this specifically. But it basically sounds like this:

> If you actively use the access token while a user is logged in, if the access token suddenly fails, you should log out the user.

But, I'm not sure how this affects the main-use case for this bundle. One very common use-case is this:

A) Use this bundle + Facebook login to get an access token
B) Use that access token immediately to get user information. Then, you never use the access token again
C) Use that user information to log the user in (if they already have an account) or create a new user (e.g. they become registered on your site).

What's not clear is that, if a user revokes access to your Facebook application, that you should do anything special. After all, you've discarded the access token and aren't making any more requests for user data anyways - you simply used Facebook once as an easy way for a user to register on your site. In fact, because you discarded the access token, if the user revoked your Facebook app while actively using your site, you wouldn't even know about this - because you would need to make an API request with the access token to realize it failed.

So, this is honestly a bit fuzzy to me... but I'm if you are using the workflow I described, I'm not sure what you could really do differently.

> So this bundle is doing this in getAccessToken() ? Inside this function variables are named $expectedState and $actualState but maybe thats is doing this part which I quoted?

The "state" this is something else - it's a standard OAuth security measure. This whole paragraph is about what happens when you try to make your OWN API requests later (outside of this bundle) - so the bundle doesn't really have anything to do with it.

I hope this helps - it's always confusing :).

Cheers!

| Reply |

Yea, bit confusing some parts, but in short, probably it is ok to just use this bundle like in the code example and should not make security hole I guess :)

| Reply |
Lijana Z. avatar Lijana Z. hace 4 años edited

Another problem is - after logout and login again with facebook, I get "Invalid state parameter passed in callback URL." . Noticed when I try logging in again, then it logs in succesfully, but also not always.

Thats because session is empty and so it does not find state.


public function getAccessToken()
    {
        if (!$this->isStateless) {
            $expectedState = $this->getSession()->get(self::OAUTH2_SESSION_STATE_KEY);
            $actualState = $this->getCurrentRequest()->query->get('state');
            if (!$actualState || ($actualState !== $expectedState)) {
                throw new InvalidStateException('Invalid state');
            }
        }

        $code = $this->getCurrentRequest()->get('code');

        if (!$code) {
            throw new MissingAuthorizationCodeException('No "code" parameter was found (usually this is a query parameter)!');
        }

        return $this->provider->getAccessToken('authorization_code', [
            'code' => $code,
        ]);
    }

Why can this be?

| Reply |

Prefetching was the problem. Chrome was sending 2 requests - one prefech and one after I hit enter in the address bar. And this was not planned and used to break things. Damn never heard such thing before. But xdebug was stopping at breakpoints and I did not undertsand why even when I had not hit enter yet.

| Reply |

Wow. That's crazy! I'm glad you figured that out... but it's super strange...

| Reply |

:)

| Reply |
Lijana Z. avatar Lijana Z. hace 4 años edited

I am having problem - I made FacebookAuthenticator and it authenticates, but user is still redirected to /login. As I understand it is because form_login authenticator does not understand that user has logged in with facebook and so asks again to login. How to deal with this?

firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern:            .*
            context:            user
            logout:             ~
            anonymous:          ~
            form_login:
                login_path:     /login
                check_path:     /login_check
                failure_handler: vop_user.event_listener.login_failed
            switch_user: true
            guard:
                authenticators:
                    - Vop\UserBundle\Security\FacebookAuthenticator```


Here is something wrong? Tabs are off because disquss makes them skip.
| Reply |
Lijana Z. avatar Lijana Z. Lijana Z. hace 4 años edited

I have debugged and found prolbem is same as for this guy:https://stackoverflow.com/questions/40566647/symfony-3-fb-login-after-oauth-login-flow-i-go-back-at-login-page-because-the

and there is an answer. Does that answer does not introduce some security hole? Because it looks different from what is in the documetntaition here https://github.com/knpuniversity/oauth2-client-bundle

Also debuged that it sets here to $this->setAuthenticated(false);


public function setUser($user)
    {
        if (!($user instanceof UserInterface || (\is_object($user) && method_exists($user, '__toString')) || \is_string($user))) {
            throw new \InvalidArgumentException('$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.');
        }

        if (null === $this->user) {
            $changed = false;
        } elseif ($this->user instanceof UserInterface) {
            if (!$user instanceof UserInterface) {
                $changed = true;
            } else {
                $changed = $this->hasUserChanged($user);
            }
        } elseif ($user instanceof UserInterface) {
            $changed = true;
        } else {
            $changed = (string) $this->user !== (string) $user;
        }

        if ($changed) {
            $this->setAuthenticated(false);
        }

        $this->user = $user;
    }

Thats because for some reason when it compares $this->user to $user - it finds that it is changed.

$this->getUser()->isAccountNonLocked() is null, but $user isAccountNonLocked() is true so they are different.

But I cannot find where it sets $this->user with isAccountNonLocked() null.
Also cannot find it somewhere changing isAccountNonLocked value.

| Reply |

Hey Lijana Z.!

Sorry for my slow reply! Excellent debugging! I think you've stumbled over a class, annoying, hard-to-debug edge case. Here's an extensive answer to get you started: https://symfonycasts.com/screencast/symfony3-security/automatic-login-handling#comment-3868014263

But, the key to your question is this:

But I cannot find where it sets $this->user with isAccountNonLocked() null.
Also cannot find it somewhere changing isAccountNonLocked value.

My guess is that this value is never being changed. But rather, when your User object is serialized, this value is not being serialized. And so, when the User object is deserialized from the session, the value isn't there - so it's null. If you have a custom __serialize() method, I would try removing it. Also, the AdvancedUserInterface that these isAccountNonLocked() methods come from is deprecated - so you could also remove all of those properties & methods, and that will also probably fix the issue.

If you need more guidance - let us know!

Cheers!

| Reply |

We are using 3.4 symfony. Can there be any potential problems when removing AdvancedUserIterface but keeping methods of this interface in actual class? I am not sure how to solve this would be best at the moment. Or maybe keep the manual setting session as in that stack overflow question, until we update symfony? Because removing custome serialise I am also afraid, because can introduce some bugs.

| Reply |

Not sure if anyone can blame author for slow replies when we dont pay you for this :) but really sometimes would be probably more cost effective to just pay and quickly solve the problem instead of trying to find solution myself :) but of course depends on the price.

I see we have public function serialize() and there is https://www.php.net/manual/... used. When I remove the interface , then serialize() is not called and then it works ok without this extra code. But then I guess whole user object is save to session, so I am not sure if it is the option to remove custom serialize method, maybe I would introduce new bugs then. I see custome method just serializes 5 user properties.

Also tried removing AdvancedUserInterface. Then I got error that getUser() has to return UserInterface. So then instead of AdvancedUserInterface I placed UserInterface and it also helps without removing our custom serializer.

Without you this would be super hard to find. At least also this is good that it is opensource so we can debug source. I am not sure how people work if libraries are not open source.

Is this really an edge case? How can I be so "lucky" ? :D

Also watched the video you gave the link, but did not see how can I apply that for facebook login.

| Reply |

Hey Lijana Z.!

Both solutions - removing serialize() or replacing AdvancedUserInterface in favor of UserInterface are fine. You're right that removing serialize() means the whole User object is serialized to the session. I'm mostly "meh" on this unless you see that it causes a problem. As you can see, if you don't serialize perfectly, then you can have a very difficult to debug problem. But, removing AdvancedUserInterface is fine too. Btw, the reason AdvancedUserInterface is causing a problem is that your serialize() method is not serializing the properties that the methods from this interface are using. This means that after your User object is deserialized from the session, the AdvancedUserInterface methods return different values than they did before, and that's a "red flag" (a false one) that something changed on the user and this user should be logged out for security concerns.

> Is this really an edge case? How can I be so "lucky" ? :D

It's *fairly* edge :). It was more common in earlier versions of Symfony. But not because anything has changed, only because you rarely see documentation anymore that recommends adding serialize() - as it just messed things up. For example, if you use the make:user command from MakerBundle, you would not see this method. Also, AdvancedUserInterface which was also a frequent cause of the problem was deprecated in Symfony 4.1 and will be removed in 5.0.

Cheers!

| Reply |

Looks like adding field $this->isAccountNonLocked to serialize and unserialize also solves our problem, so we will now use this to have least bug risk.

| Reply |

That's it! Well done!

1 | Reply |
Cesar avatar Cesar hace 5 años

Hi again guys:

I am using KnpUOAuth2ClientBundle for social login with LinkedIn. Everything was working fine but because LinkedIn have change its api, now I can not get the user's email.

I update to version 1.28 of this bundle and 5.1 of thephpleague/oauth2-linkedin. I can get information of the user but not his email.

I understood that we need to use another method now to retrieve the user's email (https://docs.microsoft.com/...

Any advice to fix this ? I would appreciate your help.

Cesar

| Reply |

Hey Cesar!

I think this shouldn't be too much trouble :). The purpose of the bundle (and the underlying library) is really to help you through the OAuth process so that you can ultimately get an access token. Along the way, it also gives you an easy way to fetch some basic user data. To do this, behind the scenes, the library uses your access token to make a request to GET https://api.linkedin.com/v2/me. But, as you correctly pointed out, it looks like that doesn't give you the email address anymore.

So, the solution is to get the access token $client->getAccessToken(); and use to to make your own API request (e.g. using Guzzle, or whatever HTTP client you want) to the endpoint shown here: https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/migration-faq?context=linkedin/consumer/context#how-do-i-retrieve-the-members-email-address

tl;dr: this library gives you an access token and then IT can be used to make any API request :).

Cheers!

| Reply |

Thank you Ryan for your fast answer. I have one more concern.

I am using Symfony 3.4 and authenticating the user with Guard. So, I need to get the user's email in the getUser function of the Authenticator class (https://github.com/knpunive... However, the accessToken is storaged in the $credentials variable and the function getAccessToken does't return the access token there.

Do you have any advice to get the access token and use Guzzle with that in getUser? Sorry if the solution is obvious but I am not seeing it.

| Reply |

Don't worry. I solved it. I store the token in a variable in getCredentials and use it after in getUser to do a couple of requests using Guzzle. It's not fancy but it works. Cheers.

| Reply |
Cesar avatar Cesar hace 5 años

Hi guys:
I am using KnpUOAuth2ClientBundle since a while and everything is working great for Google Login.

But, do you know if we need to do something because Google is shutting down Google+ Api ? If I am right, this bundle is configured with that API. Maybe are you going to change this bundle ?

I hope you can help me.

Cesar

| Reply |

Hey Cesar!

Excellent question! You can find some answers about that here: https://github.com/knpunive...

Cheers!

| Reply |

Thank you Ryan!

| Reply |
Default user avatar benjamin rideveau hace 5 años

An other question ....
i must desactive
public function supportsRememberMe()
{
return false;
}
else i have the response "App\Security\SocialAuth::onAuthenticationSuccess *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.
"
which response ???? thanks

| Reply |

Hey benjamin rideveau!

The onAuthenticationSuccess method is called after authentication is successful, and usually (unless you're building an API) you will create a RedirectResonse() and redirect the user to some page. In our docs for the bundle (I just checked), we show return null in that method. I'm not sure why - it makes much more sense to redirect somewhere after handling, for example, a successful Facebook login. So, for a good UX, probably you should do this. AND also it's required for remember me, if you want that.

Cheers!

| Reply |

Delete comment?

Share this comment

astronaut with balloons in space

"Houston: no signs of life"
Start the conversation!