Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
November 10, 2022 02:21 pm GMT

Symfony 6: User Authentication

Summary

Symfony is one of PHP web frameworks. It is my favorite one, because it is clearly classified, functional and robust. It is designed with security in mind, is accompanied with useful helpers like MakerBundle, and also provides great official documentation.

This post shows how to implement user management and authentication with Symfony.

Environment

Reference

Turorial

Overview

Thanks to symfony/security-bundle, we don't have to define user entity as PHP code or database schema from the beginning, for the bundle(s) brings them, which is, of course, able to be customized.
All we have to do is run few commands, configure in some ways and write some code on view template and controller.

Here we go.

1. Preparation

1-1. Symfony project

If you have no Symfony project, create your project directory and enter it. Then run:

$ php composer create-project \      symfony/website-skeleton "."$ php composer require \      symfony/orm-pack \      symfony/serializer$ php composer require --dev \      symfony/maker-bundle

Well, symfony/orm-pack comes with doctrine/doctrine-bundle. You may need to edit .env and modify DATABASE_URL to connect to your database server or file.

1-2. Install Symfony security bundle

Ready?
Let's build the foundation:

$ composer require symfony/security-bundle

That's it :)

2. User management system

2-1. Create user storage

From now on, starts the process to create the user management system of your own.
This command line generates user entity and the surroundings resource.

$ php bin/console make:user

The output was below. Here, I chose the default at any. Actually, it's up to you.

The name of the security user class (e.g. User) [User]: >  Do you want to store user data in the database (via Doctrine)? (yes/no) [yes]: >  Enter a property name that will be the unique "display" name for the user (e.g. email, username, uuid) [email]: >  Will this app need to hash/check user passwords? Choose No if passwords are not needed or will be checked/hashed by some other system (e.g. a single sign-on server). Does this app need to hash/check user passwords? (yes/no) [yes]: >  created: src/Entity/User.php created: src/Repository/UserRepository.php updated: src/Entity/User.php updated: config/packages/security.yaml  Success!  Next Steps:   - Review your new App\Entity\User class.   - Use make:entity to add more fields to your User entity and then run make:migration.   - Create a way to authenticate! See https://symfony.com/doc/current/security.html

Update the database:

$ php bin/console make:migration$ php bin/console doctrine:migrations:migrate

2-2. Create user registration form

Next, create form for users to register. Run:

$ php bin/console make:registration-form

The output and the questions I got were below. I tended to follow the recommendations here:

 Creating a registration form for App\Entity\User Do you want to add a @UniqueEntity validation annotation on your User class to make sure duplicate accounts aren't created? (yes/no) [yes]: > 

Well, when you choose "yes" at the next question, you also have to take another installation. (I'll show it in the next "Optional" section.)

 Do you want to send an email to verify the user's email address after registration? (yes/no) [yes]: >  [WARNING] We're missing some important components. Don't forget to install these after you're finished.                           composer require symfonycasts/verify-email-bundle                                                            

The rest:

 By default, users are required to be authenticated when they click the verification link that is emailed to them. This prevents the user from registering on their laptop, then clicking the link on their phone, without having to log in. To allow multi device email verification, we can embed a user id in the verification link. Would you like to include the user id in the verification link to allow anonymous email verification? (yes/no) [no]: >     What email address will be used to send registration confirmations? (e.g. [email protected]): > mailer@(your-domain) What "name" should be associated with that email address? (e.g. Acme Mail Bot): > Acme Mail Bot Do you want to automatically authenticate the user after registration? (yes/no) [yes]: >  ! [NOTE] No Guard authenticators found - so your user won't be automatically authenticated after registering.           What route should the user be redirected to after registration?:  [0 ] _preview_error  [1 ] _wdt  [2 ] _profiler_home  [3 ] _profiler_search  [4 ] _profiler_search_bar  [5 ] _profiler_phpinfo  [6 ] _profiler_xdebug  [7 ] _profiler_search_results  [8 ] _profiler_open_file  [9 ] _profiler  [10] _profiler_router  [11] _profiler_exception  [12] _profiler_exception_css  [13] app_app > 13 updated: src/Entity/User.php updated: src/Entity/User.php created: src/Security/EmailVerifier.php created: templates/registration/confirmation_email.html.twig created: src/Form/RegistrationFormType.php created: src/Controller/RegistrationController.php created: templates/registration/register.html.twig  Success!  Next: 1) Install some missing packages:      composer require symfonycasts/verify-email-bundle 2) In RegistrationController::verifyUserEmail():    * Customize the last redirectToRoute() after a successful email verification.    * Make sure you're rendering success flash messages or change the $this->addFlash() line. 3) Review and customize the form, controller, and templates as needed. 4) Run "php bin/console make:migration" to generate a migration for the newly added User::isVerified property. Then open your browser, go to "/register" and enjoy your new form!

2-3. (Optional) Implement verifier via email

Which did you choose there?

Do you want to send an email to verify the user's email address after registration? (yes/no) [yes]:

"yes"? Me, too. In that case, we need to install the additional bundle which is required. It's none of tough work!

$ composer require symfonycasts/verify-email-bundle

The output:

Info from https://repo.packagist.org: #StandWithUkraineUsing version ^1.12 for symfonycasts/verify-email-bundle./composer.json has been updatedRunning composer update symfonycasts/verify-email-bundleLoading composer repositories with package informationUpdating dependenciesLock file operations: 1 install, 0 updates, 0 removals  - Locking symfonycasts/verify-email-bundle (v1.12.0)Writing lock fileInstalling dependencies from lock file (including require-dev)Package operations: 1 install, 0 updates, 0 removals  - Downloading symfonycasts/verify-email-bundle (v1.12.0)  - Installing symfonycasts/verify-email-bundle (v1.12.0): Extracting archiveGenerating optimized autoload files109 packages you are using are looking for funding.Use the `composer fund` command to find out more!Symfony operations: 1 recipe (c63cd854aac79ffae347ea7cceaa2e44)  - Configuring symfonycasts/verify-email-bundle (>=v1.12.0): From auto-generated recipeExecuting script cache:clear [OK]Executing script assets:install public [OK] What's next? Some files have been created and/or updated to configure your new packages.Please review, edit and commit them: these files are yours.No security vulnerability advisories found

Then update the database:

$ php bin/console make:migration$ php bin/console doctrine:migrations:migrate

Edit .env. For example (for testing):

  ###> symfony/mailer ###- # MAILER_DSN=null://null+ MAILER_DSN=null://null  ###< symfony/mailer ###

That's it!

2-4 Let's play: Your registration form in browser

Go to https://(your-domain)/register. You will see:

Image description

The form and the backend system are actually ready. Try yourself!! The user you enter will be registered in User table in your database. Also, when you user email verifier and set valid MAILER_DSN, you will receive an email which contains link to verify.

Now user management system is ready. Wonderful.
Next, let's build up user authentication system.

3. User authentication system

3-1. Create user sign-in form and sign-out route

Create Symfony controller for authentication with Maker(Bundle):

$ php bin/console make:controller Auth

The output:

 created: src/Controller/AuthController.php created: templates/auth/index.html.twig  Success!  Next: Open your new controller class and add some pages!

Create view for sign-in. First, rename the default template:

$ mv templates/auth/index.html.twig templates/auth/sign-in.html.twig

Then edit it (templates/auth/sign-in.html.twig):

  {% block body %}- # all !!+ {% if error %}+     <div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>+ {% endif %}+ + <form action="{{ path('app_sign_in') }}" method="post">+     <label for="username">Email:</label>+     <input type="text" id="username" name="_username" value="{{ last_username }}"/>+ +     <label for="password">Password:</label>+     <input type="password" id="password" name="_password"/>+ +     {# If you want to control the URL the user is redirected to on success+     <input type="hidden" name="_target_path" value="/account"/> #}+ +     <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">+ +     <button type="submit">login</button>+ </form>  {% endblock %}

Next, configure config/packages/security.yaml to activate routes of sign-in via form and sign-out (which are defined next):

  security:      # ...      firewalls:          # ...          main:              # ...+             form_login:+                 login_path: app_sign_in+                 check_path: app_sign_in+                 enable_csrf: true+             logout:+                 path: app_sign_out

Finally, edit src/AuthController.php to define routes for sign-in and sign-out:

+ use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;  # ...  class AuthController extends AbstractController  {-     #[Route('/auth', name: 'app_auth')]-     public function index(): Response-     {-         return $this->render('auth/index.html.twig', [-             'controller_name' => 'AuthController',-         ]);-     }+     #[Route('/sign-in', name: 'app_sign_in')]+     public function app_sign_in(AuthenticationUtils $authenticationUtils): Response+     {+         // get the login error if there is one+         $error = $authenticationUtils->getLastAuthenticationError();+ +         // last username entered by the user+         $lastUsername = $authenticationUtils->getLastUsername();+ +         return $this->render('auth/sign-in.html.twig', [+             'last_username' => $lastUsername,+             'error'         => $error,+         ]);+     }+ +     #[Route('/sign-out', name: 'app_sign_out')]+     public function app_sign_out(): Response+     {+         // controller can be blank: it will never be called!+         throw new \Exception('Don\'t forget to activate logout in security.yaml');+     }  }

3-2. Let's play: User authentication and access control

Let's check if user authentication works properly.
First, create a page where anonymous user can't view by editting config/packages/security.yaml. Additionally, Comment out the form_login: section in order to deactivate redirection to sign-in form:

  security:      # ...      firewalls:          # ...-         form_login:-             login_path: app_sign_in-             check_path: app_sign_in-             enable_csrf: true+         # form_login:+             # login_path: app_sign_in+             # check_path: app_sign_in+             # enable_csrf: true      # ...      access_control:          # ...+         - { path: ^/app, roles: ROLE_USER }

Open https://your-domain)/app in browser. You will be unable to access the page and see the error:

Image description

OK. Access control works.
Then, restore form_login::

  security:      # ...      firewalls:          # ...-         # form_login:-             # login_path: app_sign_in-             # check_path: app_sign_in-             # enable_csrf: true+         form_login:+             login_path: app_sign_in+             check_path: app_sign_in+             enable_csrf: true

Open, again. You will be redirected to the sign-in page:

Image description

Enter email and password of your user.
And it will be solved like...:

Image description

Now you can register users in your app and sign-in/out with them


Original Link: https://dev.to/nabbisen/symfony-6-user-authentication-4ek

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To