Direction for troubleshooting session validation with Guardian

Hello again,

I have been having issues with user sessions becoming invalid and the resulting redirects and updates to the layout template are not working consistently reliably. The Guardian implementation of my app was built by a professional team that is no longer engaged. So I’m digging in to understand and troubleshoot.

Problem: User tries to place an order after having been away from the site for something more substantial than 15 minutes or so, but not necessarily weeks, and that user is bounced back to the homepage with a note indicating that their session expired (or had an error) and telling them to sign in again. Sometimes the user is not actually logged out. For example, they can still see items in their cart in the nav and the checkout page still loads the checkout section instead of the prompt that users see if they are not logged in.

Here’s my deps:

{:guardian, "~> 2.0"}

and the main guardian auth pipeline.ex:

@claims %{typ: "access"}

  use Guardian.Plug.Pipeline,
    otp_app: :oceanconnect,
    module: PreOrderApp.Guardian,
    error_handler: PreOrderAppWeb.SessionController

  plug(Guardian.Plug.VerifySession, claims: @claims)
  plug(Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer")
  plug(Guardian.Plug.LoadResource, ensure: true)

and lastly, here’s the error handler from the SessionController:

def auth_error(conn, {_type, _reason}, _opts) do
    |> PreOrderApp.Guardian.Plug.sign_out()
    |> put_flash(
      "Please sign in to proceed. If you were signed out due to an expired session, items in your basket should be unaffected by the expiration. If you were not automatically signed out, you may need to sign out and back in again."
    |> put_status(302)
    |> redirect(to: session_path(conn, :new))

This suggests that an expired token will direct the user to the sign-in page (:new), but there’s a check in the new which looks for an existing session and was redirecting to home if so, but which I’m currently showing as redirecting to the :delete, which is normally triggered when the user clicks sign-out, and which when triggered in this case results in an error page. I think that suggests that some part of the session token is getting deleted, but not everything, and different aspects of the app are looking at the different pices. Here’s that one:

def new(conn, _) do
  IO.inspect(conn, label: "@@@@@@@@@@@@@  SessionController -> new => conn", limit: :infinity, pretty: true, printable_limit: :infinity)
    if Auth.current_user(conn) do
      redirect(conn, to: session_path(conn, :delete))
      render(conn, "new.html")

Does anyone have any tips or required reading for troubleshooting Guardian? Obviously I’ve spent some time with the docs, but that doesn’t always sink well.

Thank you very much

What is the guardian config you are using - can you check ttl value in config.exs or dev.exs

Hi, Kartheek!

This is in my config.ex:

config :pre_order_app, PreOrderApp.Guardian,
  issuer: "app_name",
  secret_key: "random_key"

I don’t see anything in dev.exs. So I suspect it is using the default ttl, but I’ve yet to figure out exactly where that is happening.

the default ttl is:

 @default_ttl {4, :weeks}

Please note the ttl is counted from the time of the token issuing; so an user can still have an expiring token in the middle of interactivity.

Yup, something is breaking somewhere. The problem only happens on production, where I experience it on my mobile every day, but never on my mac. I very likely visit production on my mac every day or two, which would be within the default ttl.
Several people have reported the issue. It is predictable that I’ll be logged out overnight’ish, but I’m rarely routed to the :new to sign in again, which means that the test for whether the session already exists is passing.
I’m going to try to get the :delete to work as a priority, but I also think I’m going to have to set up some logging to see what’s happening in the tokens that pass through there. I’ll report back if I’m able to figure it out.
Thank you for taking a look at the question!

I’ve been meaning to close the loop on this topic for reference. In hindsight, I think the problem was the liveview in the nav was from an early LV version and was not disconnecting every time that the user signed out. Ultimately, I decided to completely strip out the guardian auth and put in an entirely new. This prompted me to more thoroughly understand how the auth functions and various best practices, which led me to improve the security relative to the early build by a team that I’d hired to support us. Since implementing the new auth, we haven’t observed any of the session issues that were previously plaguing us.

Thanks again for the help on it. This framework makes webapp development very fun and accessible and this community is invaluable.

1 Like