ueberauth/guardian_backdoor

Using the backdoor creates two tokens

tarzan opened this issue · 4 comments

I am using guardian in tandem with guardian_db to persist the JWT tokens in the database. Upon writing the acceptance tests using Hound, I ran into the following issue:

  1. I followed the instructions in the README and created a hound_login() function with
{:ok, token, _claims} = MyApp.Guardian.encode_and_sign(resource)

navigate_to("/?token=#{token}")
  1. I followed the instruction for guardian_db, by implementing (among others) the following hook:
  def after_encode_and_sign(resource, claims, token, _options) do
    with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
      {:ok, token}
    end
  end
  1. I wrote an acceptance test that monitors the token is persisted and removed from the database.
  2. I observed that tokens are persisted in the database twice upon each login.

This has to do with the example implementation that guides the user to first manually encode and sign a token, while the Backdoor Plug picks up on this token, extracts the token and then calls the sign_in of the Guardian Plug, which itself encodes and signs the token again. This seems unnecessarily complex to me, isn't it possible to shortcut this somehow?

Sorry for the delays @tarzan, I've been out of the country and dealing with a family emergency. One of the @ueberauth/developers will help you soon!

@tarzan what about having a App.Test.Guardian module under your test/support files that it doesn't use Guardian.DB.

To be honest, JWT + Guardian.DB is over killing for testing, you could avoid any database interaction from Guardian if you follow this approach.

@tarzan The example assumes MyApp.Guardian.encode_and_sign/1 is free from side effects. If we extend that function to skip callbacks, we can avoid Guardian.DB issues.

MyApp.Guardian.encode_and_sign(resource, claims, skip_callback: true)

Also, my pull request #4 lets you workaround by passing claims directly instead of tokens. That should avoid double tokens too.

Eventually, we decided to write our own plug for sidestepping authentication in acceptance tests. I put it in a gist right here: https://gist.github.com/tarzan/9d2aad9bb0191587ae4a31e1ded0beb7

This just serialises a user to a JWT token and can be called by implementing a login helper in ExUnit case template:

      def login(%{id: user_id}) do
        navigate_to("/?user_id=#{user_id}")
      end