Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firefox: Amber Session Not Saving Data Between Requests. #1020

Closed
westonganger opened this issue Jan 5, 2019 · 8 comments

Comments

Projects
None yet
2 participants
@westonganger
Copy link
Contributor

commented Jan 5, 2019

After following the default amber authentication guide I am unable to login. The session appears to get removed upon the next request. Can someone please point me in the right direction?

Here is an example request log. As you can see the session[:user_id] gets set after the sign in POST request. The following redirect request never goes to the specified redirect path. Instead seems to reload the current page/sign in page without the new session variable.

Status: 302 Method: POST  Pipeline: web Format: html
06:57:53 Request    | Requested Url: /session
06:57:53 Request    | Time Elapsed: 848.48ms
06:57:53 Headers    | Host: ["0.0.0.0:3000"]
06:57:53 Headers    | User-Agent: ["Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0"]
06:57:53 Headers    | Accept: ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"]
06:57:53 Headers    | Accept-Language: ["en-US,en;q=0.5"]
06:57:53 Headers    | Accept-Encoding: ["gzip, deflate"]
06:57:53 Headers    | Referer: ["http://0.0.0.0:3000/signin"]
06:57:53 Headers    | Content-Type: ["application/x-www-form-urlencoded"]
06:57:53 Headers    | Content-Length: ["149"]
06:57:53 Headers    | DNT: ["1"]
06:57:53 Headers    | Connection: ["keep-alive"]
06:57:53 Headers    | Cookie: ["amber.session=eyJjc3JmLnRva2VuIjoiVFFwUEROUEtFVTFJNnVMdktzYWl1U0VVa2dQS3dKNTJna2JoTlVDRVlpOCIsIl9mbGFzaCI6Int9In0%3D--aa9g9HnBKV6cOqDC7nmpIMJRzrc%3D; amber_craigslist_scraper.session=eyJjc3JmLnRva2VuIjoidnpMWXdtdWROcEhFOU5DNlphTWlDaEV2UUNSX09sYzVNcW02U2ZiYm00cyIsIl9mbGFzaCI6Int9In0%3D--8FicmHlLmiJnSDH5T47tBITrPUw%3D"]
06:57:53 Headers    | Upgrade-Insecure-Requests: ["1"]
06:57:53 Cookies    | amber.session: #<HTTP::Cookie:0x7fb0e17c2a80>
06:57:53 Params     | _csrf: 0aAr7KZupbA_1pvSn7lzViIOdHTJWImt_FsHYps55ZdukvMuzfOTIfsiS2j6GlFcMyE0ULZi3pTO8r0rbeJ-HA==
06:57:53 Params     | email: FILTERED
06:57:53 Params     | password: FILTERED
06:57:53 Session    | csrf.token: vzLYwmudNpHE9NC6ZaMiChEvQCR_Olc5Mqm6Sfbbm4s
06:57:53 Session    | _flash: {"notice":"Successfully logged in"}
06:57:53 Session    | user_id: 3

06:57:53 Request    | Started 2019-01-04 18:57:53 -08:00
06:57:53 Request    | Status: 200 Method: GET  Pipeline: web Format: html
06:57:53 Request    | Requested Url: /signin
06:57:53 Request    | Time Elapsed: 217.0µs
06:57:53 Headers    | Host: ["0.0.0.0:3000"]
06:57:53 Headers    | User-Agent: ["Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0"]
06:57:53 Headers    | Accept: ["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"]
06:57:53 Headers    | Accept-Language: ["en-US,en;q=0.5"]
06:57:53 Headers    | Accept-Encoding: ["gzip, deflate"]
06:57:53 Headers    | DNT: ["1"]
06:57:53 Headers    | Connection: ["keep-alive"]
06:57:53 Headers    | Cookie: ["amber.session=eyJjc3JmLnRva2VuIjoiVFFwUEROUEtFVTFJNnVMdktzYWl1U0VVa2dQS3dKNTJna2JoTlVDRVlpOCIsIl9mbGFzaCI6Int9In0%3D--aa9g9HnBKV6cOqDC7nmpIMJRzrc%3D; amber_craigslist_scraper.session=eyJjc3JmLnRva2VuIjoidnpMWXdtdWROcEhFOU5DNlphTWlDaEV2UUNSX09sYzVNcW02U2ZiYm00cyIsIl9mbGFzaCI6Int9In0%3D--8FicmHlLmiJnSDH5T47tBITrPUw%3D"]
06:57:53 Headers    | Upgrade-Insecure-Requests: ["1"]
06:57:53 Headers    | Cache-Control: ["max-age=0"]
06:57:53 Cookies    | amber.session: #<HTTP::Cookie:0x7fb0e17ca000>
06:57:53 Session    | csrf.token: vzLYwmudNpHE9NC6ZaMiChEvQCR_Olc5Mqm6Sfbbm4s
06:57:53 Session    | _flash: {}

Here is my current setup.

class HTTP::Server::Context
  property current_user : User?
end

class Authenticate < Amber::Pipe::Base

  def call(context)
    user_id = context.session["user_id"]?

    if user_id
      user = User.query.where({id: user_id.to_i}).first
    end

    if user
      context.current_user = user
      call_next(context)
    else
      return call_next(context) if public_path?(context.request.path)
      context.flash[:warning] = "Please Sign In"
      context.response.headers.add "Location", "/signin"
      context.response.status_code = 302
    end
  end

  #PUBLIC_PATHS = ["/", "/signin", "/session", "/signup", "/registration"]
  PUBLIC_PATHS = ["/signin", "/session", "/signup", "/registration"]

  private def public_path?(path)
    PUBLIC_PATHS.includes?(path)

    # Different strategies can be used to determine if a path is public
    # Example, if /admin/* paths are the only private paths
    # return false if path.starts_with?("/admin")
    #
    # Example, if only a few private paths exist
    # return false if ["/secret", "/super/secret", "/private"].includes?(path)
  end
end

Amber::Server.configure do
  pipeline :web, :authorized do
    # Plug is the method to use connect a pipe (middleware)
    # A plug accepts an instance of HTTP::Handler
    #plug Amber::Pipe::PoweredByAmber.new
    # plug Amber::Pipe::ClientIp.new(["X-Forwarded-For"])
    plug Citrine::I18n::Handler.new
    plug Amber::Pipe::Error.new
    plug Amber::Pipe::Logger.new
    plug Amber::Pipe::Session.new
    plug Amber::Pipe::Flash.new
    plug Amber::Pipe::CSRF.new
  end

  pipeline :authorized do
    plug Authenticate.new
  end

  routes :web do
    get "/signin", SessionController, :new
    post "/session", SessionController, :create
    get "/signup", RegistrationController, :new
    post "/registration", RegistrationController, :create
  end

  routes :authorized do
    get "/profile", UserController, :show
    get "/profile/edit", UserController, :edit
    patch "/profile", UserController, :update
    get "/signout", SessionController, :delete

    get "/", ItemsController, :index
  end
end

class SessionController < ApplicationController
  def new
    user = User.new
    render("new.slang")
  end

  def create
    user = User.query.find({email: params["email"].to_s})

    if user && user.authenticate(params["password"].to_s)
      session[:user_id] = user.id
      flash[:notice] = "Successfully logged in"
      redirect_to "/"
    else
      flash[:alert] = "Invalid email or password"
      user = User.new
      render("new.slang")
    end
  end

  def delete
    session.delete(:user_id)
    flash[:alert] = "Succesfully logged out"
    redirect_to "/"
  end
end

@westonganger westonganger changed the title Amber Session not saving data by default Amber Session Not Saving Data Betwen Requests Jan 5, 2019

@drujensen

This comment has been minimized.

Copy link
Member

commented Jan 5, 2019

Hi @westonganger I think the Authenticate plugin where is not working. Try this in the src/middleware/authenticate.cr:

class HTTP::Server::Context
  property current_user : User?
end

class Authenticate < Amber::Pipe::Base
  def call(context)
    user_id = context.session["user_id"]?
    if user = User.find user_id
      context.current_user = user
      call_next(context)
    else
      context.flash[:warning] = "Please Sign In"
      context.response.headers.add "Location", "/signin"
      context.response.status_code = 302
    end
  end
end

Also, If you use the pipelines to filter the routes, you don't need the logic in the plugin to perform it as well, so you can remove that.

@drujensen

This comment has been minimized.

Copy link
Member

commented Jan 5, 2019

@westonganger Sorry, just realized, you are not using Granite. Is this Jennifer?

@westonganger

This comment has been minimized.

Copy link
Contributor Author

commented Jan 5, 2019

No I am not using Granite. I was using Jennifer.cr but had too many problems, so now I've settled on Clear. The where query was working fine.

As the log shows, the request to SessionController#create is returning successful

session[:user_id] = user.id
flash[:notice] = "Successfully logged in"
redirect_to "/"

and in the logs all is well

06:57:53 Session    | _flash: {"notice":"Successfully logged in"}
06:57:53 Session    | user_id: 3

Then regardless of what happens next the session["user_id"] should not disappear. The redirect to the GET request shows the flash is empty, the session["user_id"] is gone, and incorrectly sent me to the "/signin" page:

06:57:53 Session    | _flash: {}
@drujensen

This comment has been minimized.

Copy link
Member

commented Jan 5, 2019

The user id is properly being set in the Session#create:

06:57:53 Session    | user_id: 3

But when you reach the Authenticate.cr pipe, it fails to lookup the user and redirects to the '/signin':

06:57:53 Request    | Requested Url: /signin

It could be that the session is being dropped as you are suggesting so the lookup fails:

user_id = context.session["user_id"]?

See if you can add a log message and verify the user_id is not being retrieved correctly. Also spit out the contents of the session.

@westonganger

This comment has been minimized.

Copy link
Contributor Author

commented Jan 6, 2019

So I decided to test out on a different browser, Safari and the login worked fine. I guess the problem is only with Firefox (that I know of so far). Could it be because there are different headers attached? Notably I see this one in Firefox only which according to the Do Not Track spec shouldnt do anything by default.

06:57:53 Headers    | DNT: ["1"]
@drujensen

This comment has been minimized.

Copy link
Member

commented Jan 6, 2019

@westonganger Thanks for reporting this. I am seeing some strange behavior in FF with navigation in general. Sometimes I click on a link but it refreshes and stays on the current page.

@drujensen drujensen changed the title Amber Session Not Saving Data Betwen Requests Firefox: Amber Session Not Saving Data Between Requests. Navigation failing. Jan 6, 2019

@drujensen

This comment has been minimized.

Copy link
Member

commented Jan 6, 2019

It looks like the navigation issue is related to the auto-reload in FF. When I disable it, the navigation works for me.

@drujensen drujensen changed the title Firefox: Amber Session Not Saving Data Between Requests. Navigation failing. Firefox: Amber Session Not Saving Data Between Requests. Jan 6, 2019

@westonganger

This comment has been minimized.

Copy link
Contributor Author

commented Jan 6, 2019

Awesome thanks for figuring that one out for me I was so confused. Since this is solved now I will close this issue in favor of your newly created issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.