DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Understanding the Identity Bridge Framework
  • In-App Browsers in Mobile Apps: Benefits, Challenges, Solutions

Trending

  • Performance Optimization Techniques for Snowflake on AWS
  • Accelerating AI Inference With TensorRT
  • Teradata Performance and Skew Prevention Tips
  • AI's Dilemma: When to Retrain and When to Unlearn?
  1. DZone
  2. Coding
  3. Frameworks
  4. Vue.js and Symfony — User Authentication

Vue.js and Symfony — User Authentication

Authenticating users in Symfony — with Vue.js as frontend framework.

By 
Dariusz Włodarczyk user avatar
Dariusz Włodarczyk
·
May. 16, 21 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
9.4K Views

Join the DZone community and get the full member experience.

Join For Free

Symfony and Vue.js

In this article I will skip the Symfony authentication process as this can be found in the official documentation (it’s more about presenting the solutions in case of using Vue.js):

  • Symfony Authentication,
  • Symfony Login Form,
  • Symfony Guard Authentication,

JWT Token-based Authentication — Does It Have to Be This Way?

Vue.js allows us to either create a SPA (Single-Page Application) or to be used in the form of hybrid where we can inject the components into already existing code or use Vue.js as an extension of current frontend code (In which case I learned the hard way that it can become very messy — You can find more here) — as for both cases the authentication can be implemented/solved in different ways.

Personally, I didn’t even intend to test both solutions, as the hybrid one works very well — but — I’ve already had a chance to see some interesting/confusing authentication in Symfony by using JWT to validate user on Angular based frontend (in this case the solution/end goal was different than simple login form).

In general, the JWT solution does work, makes everything it should, there is no problem — so what’s the point? Since Vue.js is the first modern JS framework used on my own alongside with backend framework I wondered:

“Do I really need to use some tokens, as the Symfony auth no longer works the way it should? Is it always like this in modern JS?”

A long story short — it doesn’t need to be this way, there is actually no magical, special token required in the authentication process — although the full SPA does require special logic, it’s still 'almost' standard Symfony logic.

The Easiest Solution — Hybrid Authentication

In this case, the login form works is the only one page that is fully rendered by Twig — no JS logic is used here, thus a normal authentication process is being used.

1. Authentication Page — simple Twig based template with a login route.

Twig
 




x
15


 
1
{% extends 'user/base.twig' %} {# A base template to extend from #}
2

          
3
{% block content %}
4
    {% include 'user/components/login-form.twig' %} {# Standrad symfony generated form #}
5

          
6
    {# Links #}
7
    {% set rowStyle  = "text-align: center;display: flex;justify-content: center; height: 25px; margin-top: 10px;"%}
8
    {% set linkStyle = "text-decoration: none; color: #4a5073;text-align: center; " %}
9
    <div class="row" style="{{ rowStyle }}">
10
        <p>
11
            <i class="fab fa-github" aria-hidden="true"></i>
12
            <a href="https://github.com/Volmarg/notifier-proxy-logger" style="{{ linkStyle }}" target="_blank"> {{ 'pages.login.githubProject' | trans }}</a>
13
        </p>
14
    </div>
15
{% endblock %}



2. Authentication Route — route to return the login page.

PHP
 




x


 
1
<?php    
2

          
3
/**
4
  * @param AuthenticationUtils $authenticationUtils
5
  * @return Response
6
  */
7
 #[Route("/login", name: "login", methods: ["GET", "POST"])]
8
 public function login(AuthenticationUtils $authenticationUtils): Response
9
 {
10
     $userLoginForm = $this->application->getForms()->getUserLoginForm();
11
     $error         = $authenticationUtils->getLastAuthenticationError();
12
     $errorMessage  = "";
13

          
14
     if( !empty($error) ){
15
         $errorMessage = $error->getMessage();
16
     }
17

          
18
     $templateData = [
19
         'errorMessage'  => $errorMessage,
20
         'userLoginForm' => $userLoginForm->createView(),
21
     ];
22

          
23
   return $this->render("user/login/login.twig", $templateData);
24
 }



And that’s it (naturally assuming that project is already configured to use Symfony Authentication presented in links above), authentication works already on this step — simply add some rules to security.yaml, and everything will work as intended.

Be aware that each route added with Vue-Router must be also present in Symfony, otherwise how does the backend know what page was accessed? After all Vue.js only pushes new state in browser history, unless simple location.pathname = url is used.

Adding Vue.js Routes to Symfony

Personally, I’ve got a very simple solution for this, which is defining one method (with base twig template for it — it contains the mounting #id for Vue-App):

1. Handler in backend.

PHP
 




xxxxxxxxxx
1
29


 
1
<?php
2

          
3
namespace App\Action;
4

          
5
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
6
use Symfony\Component\HttpFoundation\Response;
7
use Symfony\Component\Routing\Annotation\Route;
8

          
9
/**
10
 * This class contains the global actions defined for Vue calls
11
 *
12
 * Class BaseAction
13
 * @package App\Action
14
 */
15
class BaseVueAction extends AbstractController
16
{
17
    #[Route("/modules/mailing/overview",        name: "modules_mailing_overview",        methods: ["GET"])]
18
    #[Route("/modules/mailing/history",         name: "modules_mailing_history",         methods: ["GET"])]
19
    #[Route("/modules/mailing/settings",        name: "modules_mailing_settings",        methods: ["GET"])]
20
    #[Route("/modules/dashboard/overview",      name: "modules_dashboard_overview",      methods: ["GET"])]
21
    #[Route("/modules/discord/history",         name: "modules_discord_history",         methods: ["GET"])]
22
    #[Route("/modules/discord/manage-webhooks", name: "modules_discord_manage_webhooks", methods: ["GET"])]
23
    #[Route("/modules/discord/test-sending",    name: "modules_discord_test_sending",    methods: ["GET"])]
24
    public function renderBaseTemplate(): Response
25
    {
26
        return $this->render('base.twig');
27
    }
28
}



2. Twig with mounting #id

Twig
 




x


 
1
<!DOCTYPE html>
2
<html lang="en">
3

          
4
<head>
5
    {% include 'head.twig' %}
6
</head>
7

          
8
<body>
9
<div id="app"></div> <!-- Vue.js is initialized for this id-->
10
<section>
11
    {% include 'footer.twig' %}
12
</section>
13
</body>
14
</html>



With this — if we open the SPA page new tab it will still work as it’s just a template, which later in the process gets rebuilt/controlled by Vue.js.

3. Mounting Vue.js

JavaScript
 




xxxxxxxxxx
1
17


 
1
const app = Vue.createApp({
2
    template: `
3
      <Sidebar/>
4
      <Main/>
5
    `,
6
    components: {
7
        Sidebar,
8
        Main
9
    }
10
})
11

          
12
// add plugins
13
app.use(router.getRouter());
14
app.use(VueAxios, axios);
15

          
16
// Mount the main app to the DOM
17
app.mount('#app');



The Tricky Solution — API Call Authentication

In this solution everything is handled in Vue.js besides the usage of base Twig template (just scroll up to 'Adding Vue.js Routes to Symfony').

1. Login Authenticator (backend)

So what’s so special in this authenticator?

The response — that’s the important thing, it’s a JsonResponse (BaseApiDTO) consumed in the frontend for each call.

PHP
 




xxxxxxxxxx
1
221


 
1
<?php
2

          
3
namespace App\Service\Security;
4

          
5
use App\Controller\Core\Form;
6
use App\Controller\Core\Services;
7
use App\Controller\UserController;
8
use App\DTO\BaseApiDTO;
9
use App\DTO\Internal\Form\Security\LoginFormDataDTO;
10
use Doctrine\ORM\EntityManagerInterface;
11
use Exception;
12
use Symfony\Component\HttpFoundation\JsonResponse;
13
use Symfony\Component\HttpFoundation\RedirectResponse;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpFoundation\Response;
16
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
17
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
18
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
19
use Symfony\Component\Security\Core\Exception\AuthenticationException;
20
use Symfony\Component\Security\Core\User\UserInterface;
21
use Symfony\Component\Security\Core\User\UserProviderInterface;
22
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
23
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
24

          
25
/**
26
 * Handles the authentication for API called by VUE
27
 * @link https://symfony.com/doc/current/security/guard_authentication.html#the-guard-authenticator-methods
28
 *
29
 * Class VueApiLoginAuthenticator
30
 * @package App\Service\Security
31
 */
32
class VueApiLoginAuthenticator extends AbstractGuardAuthenticator
33
{
34
    /**
35
     * @var EntityManagerInterface $em
36
     */
37
    private EntityManagerInterface $em;
38

          
39
    /**
40
     * @var Services $services
41
     */
42
    private Services $services;
43

          
44
    /**
45
     * @var Form $form
46
     */
47
    private Form $form;
48

          
49
    /**
50
     * @var UserController $userController
51
     */
52
    private UserController $userController;
53

          
54
    /**
55
     * @var UrlGeneratorInterface $urlGenerator
56
     */
57
    private UrlGeneratorInterface $urlGenerator;
58

          
59
    /**
60
     * @var TokenStorageInterface $tokenStorage
61
     */
62
    private TokenStorageInterface $tokenStorage;
63

          
64
    public function __construct(
65
        EntityManagerInterface $em,
66
        Services $services,
67
        Form $form,
68
        UserController $userController,
69
        UrlGeneratorInterface $urlGenerator,
70
        TokenStorageInterface $tokenStorage
71
    )
72
    {
73
        $this->userController = $userController;
74
        $this->tokenStorage   = $tokenStorage;
75
        $this->urlGenerator   = $urlGenerator;
76
        $this->services       = $services;
77
        $this->form           = $form;
78
        $this->em             = $em;
79
    }
80

          
81
    /**
82
     * Called on every request to decide if this authenticator should be
83
     * used for the request. Returning `false` will cause this authenticator
84
     * to be skipped.
85
     */
86
    public function supports(Request $request): bool
87
    {
88
        // check if is logged in, if yes then support = false
89
        if(
90
                $request->getMethod() === Request::METHOD_POST
91
            &&  $request->getRequestUri() === $this->urlGenerator->generate("login")
92
        ){
93
            return true;
94
        }
95
        return false;
96
    }
97

          
98
    /**
99
     * @param UserInterface $user
100
     * @param string $providerKey
101
     * @return PostAuthenticationGuardToken
102
     */
103
    public function createAuthenticatedToken(UserInterface $user, string $providerKey): PostAuthenticationGuardToken
104
    {
105
        return parent::createAuthenticatedToken($user, $providerKey);
106
    }
107

          
108
    /**
109
     * Called on every request. Return whatever credentials you want to
110
     * be passed to getUser() as $credentials.
111
     *
112
     * @throws Exception
113
     */
114
    public function getCredentials(Request $request)
115
    {
116
        $loginForm = $this->services->getFormService()->handlePostFormForAxiosCall($this->form->getLoginForm(), $request);
117
        if( $loginForm->isSubmitted() ) {
118
            /**@var LoginFormDataDTO $loginFormData */
119
            $loginFormData = $loginForm->getData();
120
            return $loginFormData;
121
        }
122

          
123
        return new LoginFormDataDTO();
124
    }
125

          
126
    /**
127
     * @param LoginFormDataDTO $credentials
128
     * @param UserProviderInterface $userProvider
129
     * @return UserInterface|null
130
     */
131
    public function getUser(mixed $credentials, UserProviderInterface $userProvider): ?UserInterface
132
    {
133
        if( empty($credentials->getUsername()) ){
134
            $this->services->getLoggerService()->getLogger()->warning("Username is empty");
135
            return null;
136
        }
137

          
138
        $user = $this->userController->getOneByUsername($credentials->getUsername());
139
        if( empty($user) ){
140
            $this->services->getLoggerService()->getLogger()->warning("No user was found for give username. ", [
141
                "username" => $credentials->getUsername(),
142
            ]);
143

          
144
            return null;
145
        }
146

          
147
        return $user;
148
    }
149

          
150
    /**
151
     * @param LoginFormDataDTO $credentials
152
     * @param UserInterface $user
153
     * @return bool
154
     */
155
    public function checkCredentials($credentials, UserInterface $user): bool
156
    {
157
        $validationResult = $this->services->getValidationService()->validateAndReturnArrayOfInvalidFieldsWithMessages($credentials);
158
        if( !$validationResult->isSuccess() ){
159
            $this->services->getLoggerService()->getLogger()->warning("Could not log-in, there are login form violations", [
160
                "violations" => $validationResult->getViolationsWithMessages(),
161
            ]);
162

          
163
            return false;
164
        }
165

          
166
        $isPasswordValid = $this->services->getUserSecurityService()->validatePasswordForUser($credentials->getPassword(), $user);
167
        if(!$isPasswordValid){
168
            $this->services->getLoggerService()->getLogger()->warning("Provided password is invalid");
169
            return false;
170
        }
171

          
172
        // Return `true` to cause authentication success
173
        return true;
174
    }
175

          
176
    /**
177
     * @param Request $request
178
     * @param TokenInterface $token
179
     * @param string $providerKey
180
     * @return JsonResponse
181
     */
182
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): JsonResponse
183
    {
184
        $message = $this->services->getTranslator()->trans('security.login.messages.OK');
185
        return BaseApiDTO::buildRedirectResponse('modules_dashboard_overview', $message)->toJsonResponse();
186
    }
187

          
188
    /**
189
     * @param Request $request
190
     * @param AuthenticationException $exception
191
     * @return JsonResponse|null
192
     */
193
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?JsonResponse
194
    {
195
        $message = $this->services->getTranslator()->trans('security.login.messages.UNAUTHORIZED');
196
        return BaseApiDTO::buildUnauthorizedResponse($message)->toJsonResponse();
197
    }
198

          
199
    /**
200
     * Called when authentication is needed, but it's not sent
201
     */
202
    public function start(Request $request, AuthenticationException $authException = null): Response
203
    {
204
        if( !$request->isXmlHttpRequest() ){
205
            return new RedirectResponse($this->urlGenerator->generate('login'));
206
        }
207

          
208
        $message  = $this->services->getTranslator()->trans('security.login.messages.UNAUTHORIZED');
209
        $response = BaseApiDTO::buildUnauthorizedResponse($message);
210
        $response->setRedirectRoute("login");;
211
        return $response->toJsonResponse();
212
    }
213

          
214
    /**
215
     * @return bool
216
     */
217
    public function supportsRememberMe(): bool
218
    {
219
        return false;
220
    }
221
}



2. Handling call in Vue.js (frontend)

JavaScript
 




xxxxxxxxxx
1
153


 
1
<!-- Template -->
2
<template>
3
  <main class="d-flex w-100 h-100">
4
    <div class="container d-flex flex-column">
5
      <div class="row vh-100">
6
        <div class="col-sm-10 col-md-8 col-lg-6 mx-auto d-table h-100">
7
          <div class="d-table-cell align-middle">
8

          
9
            <div class="text-center mt-4">
10
              <h1 class="h2">{{ trans('pages.security.login.form.header.main') }}</h1>
11
              <p class="lead">
12
                {{ trans('pages.security.login.form.header.sub') }}
13
              </p>
14
            </div>
15

          
16
            <div class="card">
17
              <div class="card-body">
18
                <div class="m-sm-4">
19
                  <form>
20
                    <div class="mb-3">
21
                      <label class="form-label">{{ trans('pages.security.login.form.inputs.username.label') }}</label>
22
                      <input class="form-control form-control-lg"
23
                             type="text"
24
                             name="username"
25
                             :placeholder="trans('pages.security.login.form.inputs.username.placeholder')"
26
                             ref="usernameInput"
27
                             @keypress.enter="loginFormSubmitted"
28
                      >
29
                    </div>
30
                    <div class="mb-3">
31
                      <label class="form-label">{{ trans('pages.security.login.form.inputs.password.label') }}</label>
32
                      <input class="form-control form-control-lg"
33
                             type="password"
34
                             name="password"
35
                             :placeholder="trans('pages.security.login.form.inputs.password.placeholder')"
36
                             ref="passwordInput"
37
                             @keypress.enter="loginFormSubmitted"
38
                      >
39
                    </div>
40

          
41
                    <div class="text-center mt-3">
42
                      <a href="#" class="btn btn-lg btn-primary" @click="loginFormSubmitted">{{ trans('pages.security.login.form.buttons.login') }}</a>
43
                    </div>
44
                  </form>
45
                </div>
46
              </div>
47
            </div>
48

          
49
          </div>
50
        </div>
51
      </div>
52
    </div>
53
  </main>
54
</template>
55

          
56
<!-- Script -->
57
<script>
58
import SymfonyRoutes       from "../../../../scripts/core/symfony/SymfonyRoutes";
59
import ToastifyService     from "../../../../scripts/libs/toastify/ToastifyService";
60
import TranslationsService from "../../../../scripts/core/service/TranslationsService";
61
import StringUtils         from "../../../../scripts/core/utils/StringUtils";
62
import SpinnerService      from "../../../../scripts/core/service/SpinnerService";
63

          
64
import LoggedInUserDataDto from "../../../../scripts/core/dto/LoggedInUserDataDto";
65
import LocalStorageService from "../../../../scripts/core/service/LocalStorageService";
66

          
67
let translationService = new TranslationsService();
68

          
69
export default {
70
  methods: {
71
    /**
72
     * @description handles the login form submission
73
     */
74
    loginFormSubmitted(){
75
      let data = {
76
        username : this.$refs.usernameInput.value ?? "",
77
        password : this.$refs.passwordInput.value ?? "",
78
      }
79

          
80
      /** @var BaseApiDto baseApiResponse */
81
      SpinnerService.showSpinner();
82
      this.postWithCsrf(SymfonyRoutes.getPathForName(SymfonyRoutes.ROUTE_NAME_LOGIN), data).then( (baseApiResponse) => {
83
        SpinnerService.hideSpinner();
84

          
85
        if(baseApiResponse.success){
86
          ToastifyService.showGreenNotification(baseApiResponse.message)
87

          
88
          if( StringUtils.isEmptyString(baseApiResponse.data.redirectRouteName) ){
89
            ToastifyService.showRedNotification(translationService.getTranslationForString('general.responseCodes.500'))
90
            return;
91
          }
92

          
93
          // this must be handled without Vue as the login page contains different base component (blank)
94
          location.href = SymfonyRoutes.getPathForName(baseApiResponse.data.redirectRouteName);
95
        }else{
96
          ToastifyService.showRedNotification(baseApiResponse.message);
97
        }
98

          
99
      }).catch( (response) => {
100
        SpinnerService.hideSpinner();
101
        ToastifyService.showRedNotification(translationService.getTranslationForString('general.responseCodes.500'))
102
        console.warn(response);
103
      });
104
    },
105
    /**
106
     * @description will check if user should be able to access the login page
107
     *              - if not logged in then yes,
108
     *              - if logged in then go to dashboard,
109
     */
110
    checkLoginPageAccessAttempt(){
111
      SpinnerService.showSpinner();
112
      // check if user is logged in, and if yes then go to dashboard
113
      this.axios.get(SymfonyRoutes.getPathForName(SymfonyRoutes.ROUTE_NAME_GET_LOGGED_IN_USER_DATA)).then( response => {
114

          
115
        let loggedInUserDataDto = LoggedInUserDataDto.fromAxiosResponse(response);
116
        if(
117
                !loggedInUserDataDto.success
118
            &&  401 !== loggedInUserDataDto.code
119
        ){
120
          SpinnerService.hideSpinner();
121
          ToastifyService.showRedNotification(translationService.getTranslationForString('general.responseCodes.500'))
122
          return;
123
        }
124

          
125
        if(loggedInUserDataDto.loggedIn){
126
          // already logged in and tries to enter login page
127
          if( LocalStorageService.isLoggedInUserSet() ){
128
            ToastifyService.showOrangeNotification(translationService.getTranslationForString('security.login.messages.alreadyLoggedIn'))
129
          }else{
130
            LocalStorageService.setLoggedInUser(loggedInUserDataDto);
131
          }
132

          
133
          // let user read the message
134
          setTimeout(() => {
135
            // this must be handled without Vue as the login page contains different base component (blank)
136
            location.href = SymfonyRoutes.getPathForName(SymfonyRoutes.ROUTE_NAME_MODULE_DASHBOARD_OVERVIEW);
137
          }, 1000)
138
          return;
139
        }
140

          
141
        SpinnerService.hideSpinner();
142
      }).catch( (response) => {
143
        SpinnerService.hideSpinner();
144
        ToastifyService.showRedNotification(translationService.getTranslationForString('general.responseCodes.500'))
145
        console.warn(response);
146
      });
147
    }
148
  },
149
  beforeMount(){
150
    this.checkLoginPageAccessAttempt();
151
  }
152
}
153
</script>



3. The response

Unauthorized Response

Authorized Response

4. Logout user

PHP
 




xxxxxxxxxx
1
19


 
1
<?php
2

          
3
    /**
4
     * Will return the @see LoggedInUserDataDto as the json
5
     * @return JsonResponse
6
     */
7
    #[Route("/invalidate-user", name:"invalidate_user", methods: [Request::METHOD_POST])]
8
    #[InternalActionAttribute]
9
    public function invalidateUser(): JsonResponse
10
    {
11
        try{
12
            $this->userController->invalidateUser();
13
        }catch(Exception $e){
14
            $this->services->getLoggerService()->logException($e);
15
            return BaseApiDTO::buildInternalServerErrorResponse()->toJsonResponse();
16
        }
17

          
18
        return BaseApiDTO::buildOkResponse()->toJsonResponse();
19
    }



Invalidate user

PHP
 




xxxxxxxxxx
1
43


 
1
<?php
2

          
3

          
4
namespace App\Controller;
5

          
6

          
7
use App\Entity\User;
8
use App\Repository\UserRepository;
9
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
10
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
11

          
12
/**
13
 * Class UserController
14
 * @package App\Controller
15
 */
16
class UserController extends AbstractController
17
{
18

          
19
    /**
20
     * @var UserRepository $userRepository
21
     */
22
    private UserRepository $userRepository;
23

          
24
    /**
25
     * @var TokenStorageInterface $tokenStorage
26
     */
27
    private TokenStorageInterface $tokenStorage;
28

          
29
    public function __construct(UserRepository $userRepository, TokenStorageInterface $tokenStorage)
30
    {
31
        $this->tokenStorage   = $tokenStorage;
32
        $this->userRepository = $userRepository;
33
    }
34

          
35
    /**
36
     * Will invalidate currently logged in user by cleaning up token
37
     */
38
    public function invalidateUser(): void
39
    {
40
        $this->tokenStorage->setToken(null);
41
    }
42
    
43
}



Summarizing

Both solutions work like a charm, but if I was to choose the faster one — then it’s definitely the Hybrid-one.

Do keep in mind — that for both solutions, it’s required to send the JsonResponse to the front, so it’s a good idea to use some BaseResponse which will always consist of user authentication status.

authentication Vue.js Symfony

Published at DZone with permission of Dariusz Włodarczyk. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Understanding the Identity Bridge Framework
  • In-App Browsers in Mobile Apps: Benefits, Challenges, Solutions

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!