Comments (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.
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.
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.
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.
That makes total sense. I'll keep that in mind, thank you.
from pow.
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:
- live view page does not mount if not logged in
- 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.
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)
- ecto_sql 3.8.0 gives compilation error for generated user schema HOT 4
- Replacing Phoenix.Token with JWT-based for signing and verifiying of tokens HOT 1
- Unable to logout user in Pow API HOT 2
- Feature Request: Apple Passkeys HOT 1
- Pow.Plug.authenticate_user/1 performance HOT 2
- Reset password - test fails issue HOT 1
- Upgrading to Phoenix 1.7 HOT 5
- Create account without email/password using some unique ID?
- Phoenix 1.7 compilers warning HOT 1
- Maintain case when storing emails HOT 2
- Permissions issues with mnesia backend for Pow HOT 16
- Improve mix tasks
- Crash @missing_field? in Schema.ex HOT 1
- Inject values on registration HOT 2
- users_context seems to be ignored HOT 1
- Upgrading POW from 1.6 to 1.7 HOT 12
- Changeset errors into view HOT 1
- POW & LiveView - best way to implement `assigns.current_user` ? HOT 7
- Elixir 1.15 deprecation warnings HOT 1
- Persistence of stale session ids in MnesiaCache HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pow.