Code Monkey home page Code Monkey logo

Comments (7)

danschultzer avatar danschultzer commented on May 20, 2024 7

@thiagomajesk I agree, and apologize for not having been more proactive on this. Now with Phoenix 1.7 being this liveview heavy it is more pressing than ever. I’ve been transitioning Pow to support 1.7, and will get to a second look on the sockets soon.

The pointers I got on auth socket handling are;

  • Phoenix bypasses any plug conn handling for sockets, this makes it so that using Plug.Session is required (but 99% of users will depend on Plug.Session anyhow)
  • Session cookie headers MUST be http only. JS can not read or write them. This requires session rotation happens on a regular http request:
    • A http ping being send every X seconds
    • A regular HTTP request triggered when navigating every once in a while
  • Socket connection only have to be authenticated when connecting the first time and reconnecting after interruption. Only application authorization is necessary while socket is active. The process needs to listen to session invalidation to force close the socket connection.

For Pow this means a few changes:

  • Surface session invalidation from TTL (this goes in hand with my plan on full observability for session lifecycle)
  • Native support for WebSocket that can be used for LiveView as well (though live view already has live_session macro)

FWIW there’s no OWASP guidelines here, and Pow being very industry standards heavy makes it more tricky to decide what is the most appropriate solution.

I’ve been guiding a larger organization to use Elixir. Time has been extremely limited due to this and personal life. The good news is that I’m finally getting to a position where I can dogfood Pow again. That means I can put a lot more time into this.

It’ll still be some weeks before I get to this, so I will appreciate any help with docs/guides or PR’s to Pow.

from pow.

thiagomajesk avatar thiagomajesk commented on May 20, 2024 1

Hi @brecke I'm glad that helped... The main "problem" with Pow and LV so far I think, is the lifespan of the session. Pow has a very aggressive session expiration policy and since a WebSocket is a stateful connection, we don't have a way to guarantee those sessions are in sync.

In practice, this means that once a user is authenticated in a LiveView, he can stay there forever even if his session is no longer valid for other parts of the app (HTTP). This might not be desirable for a number of reasons and for authorization, it might be an even bigger problem.

Other concerns like security and the session expiration were also pointed out in the initial issue: #271 by @danschultzer.

from pow.

thiagomajesk avatar thiagomajesk commented on May 20, 2024

Hi @danschultzer! Would you happen to have any updates on bringing WebSocket support to Pow for the foreseeable future?

It's been quite some time since we had any news on this. BTW, you have done amazing work with Pow thus far, however, not having a clear roadmap or ETA on the efforts to this issue, makes choosing Pow for new projects a tuff decision.

So, I think it would be useful to close the old issues which contain a lot of mixed information on the subject, and replace them with some official guidance. Perhaps compiling new findings on the alternatives or at least, providing a clear path on the types of contributions necessary to make this happen, WDYT?

from pow.

brecke avatar brecke commented on May 20, 2024

Just wanted to pop in and thank @thiagomajesk for that code snippet above. I'm on a greenfield 1.7 project trying to use both traditional and live views and it just saved my day. I think I have it all working for a basic authentication mechanism thanks to that.

For reference, here are the important snippets:

  alias APPWeb.SocketCredentials

  def mount(_params, session, socket) do
    current_user = SocketCredentials.get_current_user(socket, session)
    socket = assign(current_user: current_user)
    {:ok, socket}
  end

and don't forget to adapt def get_current_user(socket, %{"COOKIE_NAME_AUTH" => signed_token}) do in socket_credentials.ex.

Is there anything you might have found that needs patching @thiagomajesk? Considering this workaround, I'm not sure why anyone would think pow is not suitable for new projects. Am I missing something?

from pow.

brecke avatar brecke commented on May 20, 2024

That makes total sense. I'll keep that in mind, thank you.

from pow.

brecke avatar brecke commented on May 20, 2024

Hi @thiagomajesk I've been thinking about this and doing some experiments about what you said and I think there's a hack that may be helpful. I'm very new to elixir so bear with me.

If I understand correctly the main scenario here is how to deal with the LV connection when the cookie is gone, right? That could be via either signing out or expiration. So I did this test: two windows side by side, one on / http-served homepage and another on /profile live view, with a handle_info handler for the : tick event:

on_mount({SocketCredentials, :default})

  def mount(_params, session, socket) do
    # Just debugging
    if connected?(socket) do
      :timer.send_interval(1000, self(), :tick)
    end

    socket =
      assign(socket,
        seconds: 0,
        session: session
      )

    {:ok, socket}
  end

...

  def handle_info(:tick, socket) do
    current_session = SocketCredentials.get_current_user(socket, socket.assigns.session)
    if is_nil(current_session) do
      {:halt, redirect(socket, to: "/login")}
    else
      {:noreply, assign(socket, seconds: socket.assigns.seconds + 1)}
    end
  end

In a nutshell, two things are happening here:

  1. live view page does not mount if not logged in
  2. live view page checks for valid cookie session every second, and exits if not logged in

Having two browser windows side by side seems to work this way: if you sign out on the http one, the live one exits after ~1s. Now I'll assume this ain't pretty, and that sending a :tick every second might be asking for trouble, but this kind of seems one hacky way to solve this.

A better one would be to have live views subscribe to some no_session event via Phoenix.PubSub but I'm not sure how that would go.

from pow.

thiagomajesk avatar thiagomajesk commented on May 20, 2024

I personally wouldn't do something like this in a production application, not just because of performance, but security as well. Effectively, you will always have a "renew window" of 1s that can be exploited. BTW, if you are only reading the session cookie, I guess you also lose the ability to implement sliding expiration for LiveViews, unless you explicitly renew the session manually every time on each LV.

A better one would be to have live views subscribe to some no_session event via Phoenix.PubSub but I'm not sure how that would go.

Yes, ideally Pow should allow us to know beforehand when a user session expires so we can broadcast a disconnect to all LiveViews, but I'm not sure about the specifics of how this should be done internally. I think it would probably require a process to monitor users' sessions from time to time, but I'm surely overly simplifying the problem 😅.

The approach we are talking about is documented here: https://hexdocs.pm/phoenix_live_view/0.19.3/security-model.html#disconnecting-all-instances-of-a-live-user.

from pow.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.