Session flash message fails occasionally


#1

I have 2 scenarios where I’m flashing message into session. Only the first scenario seems to be working. In the other two, I sometimes get the flashed message and most times I don’t.

This is the code for the failing scenarios:

try {
      const user = await User.findByOrFail('email', email)

      user.is_verified = true

      await user.save()

      session.flash({
        notification: {
          type: 'success',
          message: 'Verified!'
        }
      })

      return response.redirect('/login')
    } catch (error) {
      session.flash({
        notification: {
          type: 'danger',
          message: ' Invalid email.'
        }
      })

      return response.redirect('/login')
    }

Though I’m being redirected to /login but no flash message.

Also I have a notification partial which I use to display the flashed messages:

@if(flashMessage('notification'))
  <div class="notification is-{{ flashMessage('notification.type') }}">
    {{ flashMessage('notification.message') }}
  </div>
@endif


#2

I can’t help really, but I see two suprising things:

  1. $ in front of email in the first line. It’s like we are back in PHP suddenly. Cringe moment.
  2. The second message should be of type error, not success.

#3

The $ is a typo while posting the code over here.


#4

Here is the workflow:

  • Click on a link in an email sent
  • Then execute the code above

Can’t seem to figure out why this is not working as expected. Other flash messages are working just fine.


#5

Can you share more information around it.

  1. What’s the route, which invokes this controller method
  2. Is everything happening on the same host:port?

#6

Okay, there’s the full code:

Route.get('register/verify/:token', 'Auth/RegisterController.verifyEmail')
async verifyEmail ({ params, session, response }) {
    try {
      const user = await User.findBy('verification_token', params.token)

      user.verification_token = null
      user.is_verified = true

      await user.save()

      session.flash({
        notification: {
          type: 'success',
          message: 'Your email address has been verified.'
        }
      })

      return response.redirect('/login')
    } catch (error) {
      session.flash({
        notification: {
          type: 'danger',
          message: 'The token is invalid.'
        }
      })

      return response.redirect('/login')
    }
  }

Yeah, everything is happening on the same port. Here’s a sample link in the email sent:

http://127.0.0.1:3333/register/verify/R9M5tMSCC3XGz1PBnDRq4eDcvXOgdWHiukBPEuJR


#7

I believe it cookie might have been created for the nested path /register/verify/token. Can you check config/session.js file and see that path is set to /.


#8

Yeah, it is set.

cookie: {
  httpOnly: true,
  sameSite: true,
  path: '/'
},

#9

I created a sample repo. You can help me reproduce the problem https://github.com/thetutlage/reproducing-session-flash


#10

With the repo, on the first trial, it flashed the message but subsequently No flash messsage.


#11

The issue only occurs with Chrome. Tested with Safari and Firefox, and seems to be working.

I think Chrome is handling the session in a different way.


#12

Ohh then you got confused with what flash messages are.

Flash messages live only for a single request and then are removed. So doing a page refresh means a new request and hence messages are removed.

Regarding safari I would say open devtools and disable cache, since safari is not making request on the server.

Chrome behaviour is the correct one


#13

I understand that flash messages only live for a single request.


#14

Redirect to /login is the single request which I’m flashing the message to


#15

Yeah but you said that in the sample repo I shared, the message is shown for one time and disappears on the next refresh, so that’s the correct behaviour.

If behaviour in your app is different, then help me reproduce it.


#16

Sorry for the confusion, what I’m trying to say is that even with your sample repo, the message is not flashed.


#17

When you run the sample repo, is the message being flashed? Particularly with Chrome?


#18

@virk now this is totally confusing or maybe I’m doing something wrong somewhere.

If I click the link (http://127.0.0.1:3333/register/verify/some_random_token) from within the email sent (which will open in a new tab, I’m using Mailtrap for testing), I get no flash message. But if I enter the same link directly into the browser, everything works fine.

This explains why I thought it was working on other browsers because I was copy/pasting the URL directly in their address bar.


#19

1 thing I have in top of my mind is that the browser is pre-fetching the URL, before on click on it.

  1. Can you log a message every time you receive a request for the verify route and see if it prefetches when you hover on URL or not?
  2. One more thing, can you check and see if sameSite is set to false in the config file?

Auth Fails after email validation
#20

Okay sameSite: true is the problem. Chrome has this weird bug, for which sameSite: false has to be set in order to persist cookies during redirect.