Closed ajstrand closed 3 years ago
Phx.gen.auth is absolutely suitable for an API for a Javascript SPA, but it might take a little customizing. It's set up to do session authentication out of the box, so if you're just starting out it would be simplest to use phx.gen.auth's HTML forms for authentication and then render your SPA once the user is authenticated.
If you generated your API using phx.gen.json
, you'll have to open up your Router and update your :api
pipeline like this:
pipeline :api do
plug :accepts, ["json"]
plug :fetch_session
plug :fetch_flash # Only needed if you pipe through [:require_authenticated_user] below
plug :fetch_current_user
end
and the put your API endpoints in a scope that pipes through the :api
pipeline and optionally :require_authenticated_user
scope "/", MyAppWeb do
pipe_through [:api, :require_authenticated_user]
resources "/posts", PostController, except: [:new, :edit]
end
Then in your controller, you should be able to access the current user using conn.assigns.current_user
.
I'm not sure if this is how your app set up, but hopefully this should get something working for you. If you wanted to take this code to production, this may not be the approach you want to take, but the generated code is able to be modified as you need. If you did end up doing session-based auth, you'd want to follow security best practices like adding CSRF protection, etc. Please let me know if this didn't answer your question.
Hi, so I followed a similar approach to what you outlined and I was able to pass back the current user to my SPA.
I had a follow up question that I'm not sure if the documentation answered.
Is there a way I could pass the user token/session cookie securely to my SPA so I would be able make a POST request with some data?
I didnt see a CSRF token in my browser at all, so I resorted to grabbing the cookie in a controller and passing that back to the frontend like so(the function is contrived, but it's just an example of what I did in as controller)
def some_method(conn, _opts) do
key = conn.cookies["_app_key"]
# other logic
json(conn, %{permissions: data, cookie: key})
end
then in my fetch request in the browser i was just planning on setting my config like this:
const config = {
method: "POST",
headers: {
"Content-Type": "application/json",
"x_csrf_token: "the_token_i_grabbed_from_the_backend"
},
body: some data,
};
would my approach be ok for a demo app that's not going to a prod environment?
@ajstrand the CSRF token is in a meta tag: https://github.com/phoenixframework/phoenix/blob/ea10baae82a9b849b9b4b4c1977dcfc344662863/installer/templates/phx_live/templates/layout/root.html.leex#L7
You can pick it up like this: https://github.com/phoenixframework/phoenix/blob/ea10baae82a9b849b9b4b4c1977dcfc344662863/installer/templates/phx_assets/app.js#L20-L21
@josevalim thanks so much for answering that question! I dont think my default phoenix application had a root.html.leex
file since I'm not using Live View. So that might have been why I couldnt find the csrf meta tag. I'll go ahead and close this issue now.
Edit: just confirmed that the csrf token worked to post some data using the steps provided.
If either of you think documentation for using phx.gen.auth as an api to an SPA could be helpful let me know and I could create another issue for discussion. I'd be willing to write some docs if that would be helpful.
Hi, First off, thanks for the great work on this project. It's made auth very simple for a project I'm working on.
I'm very new to phoenix, working on an example app. I've generated the basic auth files into my phoenix app and this library works great for basic auth tasks(like creating users).
However, I've got Preact app that's running most of the business logic in my app and I'm trying to access the "current_user" object in one of my controllers to send some data to the frontend single page app. Is there a way that I can pass around the current user object to different controllers in my app, so I could send data back to my SPA?
Currently it seems like only phoenix HTML templates can access the current user since they are server side templates.
Would my application be more suitable for an auth generator like https://github.com/riverrun/phauxth?