Register FOSUserBundle and HWIOAuthBundle

I am trying to combine FOSUserBundle and HWIOAuthBundle with the following articles such as https://gist.github.com/danvbe/4476697 . However, I do not want to automatically register users who authenticate with OAuth2: additional information must be provided by the user.

Desired Result

For example, I would like to receive the following information for a registered user:

  • (Username, although I would just use email)
  • Display Name (required)
  • Profile Image (required)
  • Email address (required if there is no Facebook-id)
  • Password (required if there is no Facebook-id)
  • Facebook-id (required if there is no email address)

Now that the user is authenticated via Facebook and the user does not exist yet, I want the missing information (display name and profile picture) to be filled in the registration form. Only after this should a new FOSUser be created. In most manuals, fields such as a profile picture and email address are automatically populated with Facebook information. This is not always desirable and not possible.

Also, think about things like accepting the terms of the agreement and the rules that you want to show before creating the user.

Possible approaches

It would be, in my opinion, the decision to create a new view - an anonymous Token, OAuthenticatedToken, which contains relevant OAuth2 information, but does not take into account authenticity. Then do all the pages for this type of authentication and let the other pages redirect to the OAuth login page. However, this seems like an unnecessarily difficult decision for me.

Another solution would probably be to write code from scratch and not use the two bundles mentioned. I really hope this is not necessary.

Q: How can I insert the registration completion code into the rest of the login stream?

(I would like to share some code, but since this is the concept itself, in which I need help, I have nothing to show.)

Edit: solution

Following Derick adivce, I started working like this:

The custom user provider saves the information (unfortunately, there is no access to the raw token, so I can not register the user after registration):

class UserProvider extends FOSUBUserProvider { protected $session; public function __construct(Session $session, UserManagerInterface $userManager, array $properties) { $this->session = $session; parent::__construct( $userManager, $properties ); } public function loadUserByOAuthUserResponse(UserResponseInterface $response) { try { return parent::loadUserByOAuthUserResponse($response); } catch ( AccountNotLinkedException $e ) { $this->session->set( 'oauth.resource', $response->getResourceOwner()->getName() ); $this->session->set( 'oauth.id', $response->getResponse()['id'] ); throw $e; } } } 

Custom error handler:

 <?php // OAuthFailureHandler.php class OAuthFailureHandler implements AuthenticationFailureHandlerInterface { public function onAuthenticationFailure( Request $request, AuthenticationException $exception) { if ( !$exception instanceof AccountNotLinkedException ) { throw $exception; } return new RedirectResponse( 'fb-register' ); } } 

Both are registered as a service:

 # services.yml services: app.userprovider: class: AppBundle\Security\Core\User\UserProvider arguments: [ "@session", "@fos_user.user_manager", {facebook: facebookID} ] app.oauthfailurehandler: class: AppBundle\Security\Handler\OAuthFailureHandler arguments: ["@security.http_utils", {}, "@service_container"] 

And configured in the security configuration:

 # security.yml security: providers: fos_userbundle: id: fos_user.user_provider.username_email firewalls: main: form_login: provider: fos_userbundle csrf_provider: form.csrf_provider login_path: /login check_path: /login_check default_target_path: /profile oauth: login_path: /login check_path: /login_check resource_owners: facebook: hwi_facebook_login oauth_user_provider: service: app.userprovider failure_handler: app.oauthfailurehandler anonymous: true logout: path: /logout target: /login 

In / fb-register, I let the user enter the username and save the user on their own:

 /** * @Route("/fb-register", name="hwi_oauth_register") */ public function registerOAuthAction(Request $request) { $session = $request->getSession(); $resource = $session->get('oauth.resource'); if ( $resource !== 'facebook' ) { return $this->redirectToRoute('home'); } $userManager = $this->get('fos_user.user_manager'); $newUser = $userManager->createUser(); $form = $this->createForm(new RegisterOAuthFormType(), $newUser); $form->handleRequest($request); if ( $form->isValid() ) { $newUser->setFacebookId( $session->get('oauth.id') ); $newUser->setEnabled(true); $userManager->updateUser( $newUser ); try { $this->container->get('hwi_oauth.user_checker')->checkPostAuth($newUser); } catch (AccountStatusException $e) { // Don't authenticate locked, disabled or expired users return; } $session->remove('oauth.resource'); $session->remove('oauth.id'); $session->getFlashBag() ->add('success', 'You\'re succesfully registered!' ); return $this->redirectToRoute('home'); } return $this->render( 'default/register-oauth.html.twig', array( 'form' => $form->createView() ) ); } 

After that, the user will not log in, which is too bad. In addition, the normal fosub functionality (editing a profile, changing a password) no longer works out of the box.

I just use the username as the display name, I don’t know why I have not seen this before.

+6
source share
1 answer

Step 1: Create your own provider. Extend OAuthUserProvider and customize to suit your needs. If the user has successfully sealed, throw a specific exception (possibly an accountnotlinkedException) and throw all the relevant login information

Step 2: Create your own authentication failure handler. Make sure you select the error shown in step 1. Here you are redirected to your secondary page.

Here's how to register custom handlers:

 #security.yml firewall: main: oauth: success_handler: authentication_handler failure_handler: social_auth_failure_handler #user bundle services.yml (or some other project services.yml) services: authentication_handler: class: ProjectName\UserBundle\Handler\AuthenticationHandler arguments: ["@security.http_utils", {}, "@service_container"] tags: - { name: 'monolog.logger', channel: 'security' } social_auth_failure_handler: class: ProjectName\UserBundle\Handler\SocialAuthFailureHandler arguments: ["@security.http_utils", {}, "@service_container"] tags: - { name: 'monolog.logger', channel: 'security' } 

Step 3: Create Your Subpage. Pull all the relevant data that you saved in step 1, and create a user if everything is verified.

0
source

Source: https://habr.com/ru/post/980201/


All Articles