formapro / FpOpenIdBundle

Symfony2 OpenID security extension
53 stars 31 forks source link

[integration] FosUserBundle #48

Closed quba closed 12 years ago

quba commented 12 years ago

Maybe somebody will have time to answer it. I'm almost done with fosuserbundle integration. everything seems look alright except one thing. After successfull login and redirect to the homepage (as specified in the firewall) I'm not logged in. It looks so in logs:

[2012-07-16 15:36:32] doctrine.DEBUG: SET NAMES UTF8 ([]) [] []
[2012-07-16 15:36:32] doctrine.DEBUG: SELECT t0.identity AS identity1, t0.attributes AS attributes2, t0.id AS id3, t0.user_id AS user_id4 FROM openid_identities t0 WHERE t0.identity = ? LIMIT 1 (["https:\/\/www.google.com\/accounts\/o8\/id?id=AItOawlGZ5nVE6k5H-RZp07BgAzj4BE8aqAz5qo"]) [] []
[2012-07-16 15:36:32] doctrine.DEBUG: SELECT t0.username AS username1, t0.username_canonical AS username_canonical2, t0.email AS email3, t0.email_canonical AS email_canonical4, t0.enabled AS enabled5, t0.salt AS salt6, t0.password AS password7, t0.last_login AS last_login8, t0.locked AS locked9, t0.expired AS expired10, t0.expires_at AS expires_at11, t0.confirmation_token AS confirmation_token12, t0.password_requested_at AS password_requested_at13, t0.roles AS roles14, t0.credentials_expired AS credentials_expired15, t0.credentials_expire_at AS credentials_expire_at16, t0.facebookId AS facebookId17, t0.id AS id18, t0.safe_mode AS safe_mode19 FROM users t0 WHERE t0.id = ? (["1"]) [] []
[2012-07-16 15:36:32] security.INFO: User "u1" has been authenticated successfully [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "security.interactive_login" to listener "FOS\UserBundle\Security\InteractiveLoginListener::onSecurityInteractiveLogin". [] []
[2012-07-16 15:36:32] doctrine.DEBUG: UPDATE users SET last_login = ? WHERE id = ? ([{"date":"2012-07-16 17:36:32","timezone_type":3,"timezone":"Europe\/Berlin"},1]) [] []
[2012-07-16 15:36:32] security.DEBUG: Remember-me was requested; setting cookie. [] []
[2012-07-16 15:36:32] event.DEBUG: Listener "Symfony\Component\Security\Http\Firewall::onKernelRequest" stopped propagation of the event "kernel.request". [] []
[2012-07-16 15:36:32] event.DEBUG: Listener "bomba\PageBundle\Listener\Kernel::onKernelRequest" was not called for event "kernel.request". [] []
[2012-07-16 15:36:32] event.DEBUG: Listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener::onKernelRequest" was not called for event "kernel.request". [] []
[2012-07-16 15:36:32] event.DEBUG: Listener "Knp\Bundle\PaginatorBundle\Subscriber\SlidingPaginationSubscriber::onKernelRequest" was not called for event "kernel.request". [] []
[2012-07-16 15:36:32] event.DEBUG: Listener "FOS\RestBundle\EventListener\BodyListener::onKernelRequest" was not called for event "kernel.request". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\Security\Http\Firewall\ContextListener::onKernelResponse". [] []
[2012-07-16 15:36:32] security.DEBUG: Write SecurityContext in the session [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\SecurityBundle\EventListener\ResponseListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bridge\Monolog\Handler\FirePHPHandler::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ResponseListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\StreamedResponseListener::onKernelResponse". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.terminate" to listener "Symfony\Bundle\SwiftmailerBundle\EventListener\EmailSenderListener::onKernelTerminate". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\RouterListener::onKernelRequest". [] []
[2012-07-16 15:36:32] request.INFO: Matched route "homepage" (parameters: "_controller": "bomba\PageBundle\Controller\PageController::indexAction", "type": "all", "_route": "homepage") [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest". [] []
[2012-07-16 15:36:32] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2012-07-16 15:36:32] security.DEBUG: Read SecurityContext from the session [] []
[2012-07-16 15:36:32] security.DEBUG: Reloading user from user provider. [] []
[2012-07-16 15:36:32] doctrine.DEBUG: SET NAMES UTF8 ([]) [] []
[2012-07-16 15:36:32] doctrine.DEBUG: SELECT t0.username AS username1, t0.username_canonical AS username_canonical2, t0.email AS email3, t0.email_canonical AS email_canonical4, t0.enabled AS enabled5, t0.salt AS salt6, t0.password AS password7, t0.last_login AS last_login8, t0.locked AS locked9, t0.expired AS expired10, t0.expires_at AS expires_at11, t0.confirmation_token AS confirmation_token12, t0.password_requested_at AS password_requested_at13, t0.roles AS roles14, t0.credentials_expired AS credentials_expired15, t0.credentials_expire_at AS credentials_expire_at16, t0.facebookId AS facebookId17, t0.id AS id18, t0.safe_mode AS safe_mode19 FROM users t0 WHERE t0.id = ? LIMIT 1 ([0]) [] []
[2012-07-16 15:36:32] security.WARNING: Username "u1" could not be found. [] []
[2012-07-16 15:36:32] security.DEBUG: Remember-me cookie detected. [] []
[2012-07-16 15:36:32] security.WARNING: User class for remember-me cookie not supported. [] []
[2012-07-16 15:36:32] security.DEBUG: Clearing remember-me cookie "REMEMBERME" [] []
[2012-07-16 15:36:32] security.INFO: Populated SecurityContext with an anonymous Token [] []

So there's an error while reloading user from user provider. This query:

[2012-07-16 15:36:32] doctrine.DEBUG: SELECT t0.username AS username1, t0.username_canonical AS username_canonical2, t0.email AS email3, t0.email_canonical AS email_canonical4, t0.enabled AS enabled5, t0.salt AS salt6, t0.password AS password7, t0.last_login AS last_login8, t0.locked AS locked9, t0.expired AS expired10, t0.expires_at AS expires_at11, t0.confirmation_token AS confirmation_token12, t0.password_requested_at AS password_requested_at13, t0.roles AS roles14, t0.credentials_expired AS credentials_expired15, t0.credentials_expire_at AS credentials_expire_at16, t0.facebookId AS facebookId17, t0.id AS id18, t0.safe_mode AS safe_mode19 FROM users t0 WHERE t0.id = ? LIMIT 1 ([0]) [] []

Should select user with ID 16, not 0. I dont know why it cant read that ID from the session.

quba commented 12 years ago

@makasim can you tell me where the token is set? The token that is refreshUser's function argment returns 0 when I want to debug $token->getUser()-getId(). I don't know why openIdbundles authentication sets this token incorrectly. For example $token->getUser()-getUsername() returns good value. There's only problem with ID, which is needed to realod user from security user provider.

makasim commented 12 years ago

the token created in the security listener: https://github.com/formapro/FpOpenIdBundle/blob/master/Security/Http/Firewall/OpenIdAuthenticationListener.php#L36

fpopenid bundle does not refresh token: https://github.com/formapro/FpOpenIdBundle/blob/master/Model/UserManager.php#L67

makasim commented 12 years ago

do you have id in serialize method of the user?

quba commented 12 years ago

I am using fosuserbundle and yes - user id is serialized in model. When I am trying to login with a fresh user and I create user with createUserFromIdentity, then user is correct reloaded from session. So after creating account I am correct authenticated. What is strange here - when I am trying to login, serialized token has strange proxy. Serialized user while registering new account:

C:62:"Fp\OpenIdBundle\Security\Core\Authentication\Token\OpenIdToken":502:{a:3:{i:0;s:6:"public";i:1;s:80:"https://www.google.com/accounts/o8/id?id=AItOawnA9Y_2CZR50TQOsswOfhDj_SZHgXaA8JA";i:2;s:374:"a:4:{i:0;C:30:"codebug\UserBundle\Entity\User":121:{a:2:{i:0;N;i:1;s:97:"a:9:{i:0;s:0:"";i:1;s:0:"";i:2;s:3:"u18";i:3;s:3:"u18";i:4;b:0;i:5;b:0;i:6;b:0;i:7;b:1;i:8;i:18;}";}}i:1;b:1;i:2;a:1:{i:0;O:41:"Symfony\Component\Security\Core\Role\Role":1:{s:47:"Symfony\Component\Security\Core\Role\Rolerole";s:9:"ROLE_USER";}}i:3;a:1:{s:13:"contact/email";s:14:"kuba@bomba.org";}}";}}

Serialized user before executing refreshUser from FosUserBundle:

C:62:"Fp\OpenIdBundle\Security\Core\Authentication\Token\OpenIdToken":517:{a:3:{i:0;s:6:"public";i:1;s:80:"https://www.google.com/accounts/o8/id?id=AItOawnA9Y_2CZR50TQOsswOfhDj_SZHgXaA8JA";i:2;s:389:"a:4:{i:0;C:45:"Proxies\__CG__\codebug\UserBundle\Entity\User":121:{a:2:{i:0;N;i:1;s:97:"a:9:{i:0;s:0:"";i:1;s:0:"";i:2;s:3:"u18";i:3;s:3:"u18";i:4;b:0;i:5;b:0;i:6;b:0;i:7;b:1;i:8;i:18;}";}}i:1;b:1;i:2;a:1:{i:0;O:41:"Symfony\Component\Security\Core\Role\Role":1:{s:47:"Symfony\Component\Security\Core\Role\Rolerole";s:9:"ROLE_USER";}}i:3;a:1:{s:13:"contact/email";s:14:"kuba@bomba.org";}}";}}

What is this Proxies\__CG__? Maybe that's the thing which is causing problems?

quba commented 12 years ago

Here: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/ContextListener.php

In onKernelResponse() before serializing the token, $token->getUser()->getId() returns correct value. So it is before the token is set to session. Then while reading token from session in handle() function after $token = unserialize($token);, $token->getUser()->getId() returns 0.

So it's serialization issue. Don't know what's wrong there :/

quba commented 12 years ago

Looks like it isn't possible to correct serialize doctrine proxys. User is retrieved from identityManager->getUser(). So as far as I have read, we cant serialize it. It wasn't problem in fosfacebookbundle, because there we don't have OpenIdIdentity entity. I don't know what is the best solution but it could be solved by adding EAGER to the doctrine's assotiation between OpenIdIdentity and User class. It looks now so:

/**
     * @var Symfony\Component\Security\Core\User\UserInterface
     *
     * @ORM\OneToOne(targetEntity="codebug\UserBundle\Entity\User", fetch="EAGER")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    protected $user;

Please close unless you can propose better solution. BTW. thanks for integrating this bundle with Symfony's security layer. That was the only thing I was missing in this bundle. ;) Great job.

makasim commented 12 years ago

@quba I am not sure but it could help. the UsernamePasswordListener try to resolve all POST request to check_path url. https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php#L58

Please try one of these: