formapro / FpOpenIdBundle

Symfony2 OpenID security extension
53 stars 31 forks source link

I need update a existing user with the new attributes #84

Closed clubdesarrolladores closed 11 years ago

clubdesarrolladores commented 11 years ago

Hi,

There is a way to update a existing user with the new data (ex. the gender change).?

Reading OpenIdAuthenticationProvider::getProviderUser i see there is no way to do that because UserProvider::loadUserByUsername dont have the $attributes array available.

I need get the attributes array and the existing user, and perform my custom update.

Thanks.

makasim commented 11 years ago

you have to create a custom controller where you perform openid authorization (using relying party directly) and when you get response from openid provider (with attributes) update your user.

clubdesarrolladores commented 11 years ago

Can you please give me an example?

makasim commented 11 years ago

This the action from real app. It allows user to connect other his external accounts. You custom logic must be insideif ($result instanceof IdentityProviderResponse) { condition.

<?php

class SecurityExternalAuthenticationController extends Controller
{
    /**
     * @Secure(roles="ROLE_NON_EMPLOYER")
     */
    public function connectAction(Request $request)
    {
        $result = $this->getOpenIdRelyingParty()->manage($request);
        if ($result instanceof RedirectResponse) {
            return $result;
        }

        if ($result instanceof IdentityProviderResponse) {
            $user = $this->getUser();
            $messageSuccess = $this->get('translator')->trans('message.connected.success');
            if ($identity = $this->getIdentityManager()->findByIdentity($result->getIdentity())) {
                $identity->getUser() === $user ?
                    $this->getFlashMessenger()->setValid($messageSuccess) :
                    $this->getFlashMessenger()->setNotice('An account is alreday assigned to other user')
                ;
            } else {
                $identity = $this->getIdentityManager()->create();
                $identity->setUser($user);
                $identity->setIdentity($result->getIdentity());
                $identity->setAttributes($result->getAttributes());
                $identity->setLabel('');
                $this->getIdentityManager()->update($identity);

                $this->getFlashMessenger()->setValid($messageSuccess);
            }

            return $this->redirectList();
        }

        throw new \LogicException('Unexpected call of this action');
    }
}
clubdesarrolladores commented 11 years ago

Thanks for your help.

I have a question.

If i extends:

class IntegrarRelyingParty extends LightOpenIdRelyingParty

I can override

protected function complete(Request $request)

and get the attributes like this:

$lightOpenId = $this->createLightOpenID($this->guessTrustRoot($request));
$lightOpenId->getAttributes();

This is ok? The complete method is execute when we receive a response from the endpoint, right?

What do you think about this approach?

makasim commented 11 years ago

The complete method is execute when we receive a response from the endpoint, right?

yes this is true,

What do you think about this approach?

I dont get the whole picture. you can extend and get attributes from lightopenid object but how you set them to user identity?

clubdesarrolladores commented 11 years ago

I do with this:

    $attributes = $lightOpenId->getAttributes();
    if($user = $this->appUserManager->findUserByGuid($attributes['person/guid'])) {
        $this->appUserManager->updateUser($user, $attributes);
    }

in my case person/guid is the ID of the user in the endpoint.

makasim commented 11 years ago

I think you have to register on success auth listener. and update user there like fos user set last login time. The OpenIdToken has those attributes from lightopenid.

clubdesarrolladores commented 11 years ago

That is a good idea.

Thanks!