dwyl / dwyl/technology-stack

Quick test Deepseek

Open
#152 5 comments 1 reaction 0 assignees View on GitHub
Dominant language
JavaScript
Stars
291
Forks
25
PR merge metrics
No merged PRs in 30d

Description

[Image](https://www.deepseek.com/)

Image

## Example

Me:

> With Phoenix Liveview, you have a "mount" callback. I can pass the "user_id" assign via the session via the router. The connection starts with a HTTP request, before being upgraded into a WebSocket. It can therefor be saved into the LiveView state, and still be available when the connection is upgraded into a WebSocket "LiveSocket". How could I use HTTP-only cookies with LiveView?

Response:

Using **HTTP-only cookies** with **Phoenix LiveView** is a secure way to manage user sessions, as HTTP-only cookies are not accessible via JavaScript, reducing the risk of XSS (Cross-Site Scripting) attacks. Here's how you can implement HTTP-only cookies in your LiveView application:

---

### **1. Setting the HTTP-Only Cookie**
You can set the HTTP-only cookie in your Phoenix controller or plug before the LiveView is mounted. For example, when a user logs in, you can set the cookie like this:

```elixir
defmodule SolidyjsWeb.UserController do
use SolidyjsWeb, :controller

def login(conn, %{"user_id" => user_id}) do
conn
|> put_resp_cookie("user_id", user_id, http_only: true, secure: true) # Set HTTP-only cookie
|> redirect(to: "/map") # Redirect to the LiveView page
end
end
```

- **`http_only: true`**: Ensures the cookie is not accessible via JavaScript.
- **`secure: true`**: Ensures the cookie is only sent over HTTPS (recommended for production).

---

### **2. Accessing the Cookie in the LiveView Mount**
In the LiveView `mount` function, you can access the HTTP-only cookie from the connection (`conn`) using `Plug.Conn.get_req_cookie/2`. However, since LiveView operates over WebSockets after the initial render, you need to pass the cookie value to the LiveView during the initial HTTP request.

Here’s how you can do it:

#### **a. Pass the Cookie to the LiveView via the Session**
Modify your LiveView router to pass the cookie value to the session during the initial HTTP request:

```elixir
defmodule SolidyjsWeb.Router do
use SolidyjsWeb, :router

pipeline :browser do
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :put_user_id_in_session # Custom plug to add user_id to the session
end

scope "/", SolidyjsWeb do
pipe_through :browser

live "/map", MapLive
end

# Custom plug to extract user_id from the HTTP-only cookie and add it to the session
defp put_user_id_in_session(conn, _opts) do
user_id = Plug.Conn.get_req_cookie(conn, "user_id")
if user_id do
put_session(conn, :user_id, user_id)
else
conn
end
end
end
```

#### **b. Access the Session in the LiveView Mount**
In your LiveView, the `user_id` will now be available in the session during the `mount` function:

```elixir
defmodule SolidyjsWeb.MapLive do
use SolidyjsWeb, :live_view

@impl true
def mount(_params, session, socket) do
user_id = session["user_id"] # Access user_id from the session
if connected?(socket) do
# Subscribe to PubSub or perform other WebSocket-related setup
end

{:ok, assign(socket, :user_id, user_id)}
end
end
```

---

### **3. Handling WebSocket Connections**
Once the LiveView is mounted, the `user_id` is available in the socket assigns and can be used throughout the LiveView lifecycle. Since the cookie is HTTP-only, it won't be accessible directly in the LiveView hook or JavaScript code, which is a security benefit.

---

### **4. Refreshing or Updating the Cookie**
If you need to refresh or update the cookie (e.g., when the user logs out or their session is renewed), you can do so in a controller or plug:

```elixir
def logout(conn, _params) do
conn
|> delete_resp_cookie("user_id") # Delete the cookie
|> redirect(to: "/")
end
```

---

### **5. Security Considerations**
- **CSRF Protection**: Ensure you have CSRF protection enabled in your LiveView (it is enabled by default in Phoenix).
- **Secure Cookies**: Always use `secure: true` for cookies in production to ensure they are only sent over HTTPS.
- **SameSite Attribute**: Consider setting the `same_site` attribute for cookies to prevent CSRF attacks:
```elixir
put_resp_cookie(conn, "user_id", user_id, http_only: true, secure: true, same_site: "Strict")
```

---

### **6. Example Workflow**
1. **User Logs In**:
- The `login` controller action sets an HTTP-only cookie with the `user_id`.
- The user is redirected to the LiveView page.

2. **Initial HTTP Request**:
- The `put_user_id_in_session` plug extracts the `user_id` from the cookie and adds it to the session.
- The LiveView `mount` function accesses the `user_id` from the session and assigns it to the socket.

3. **WebSocket Connection**:
- The `user_id` is available in the socket assigns and can be used for PubSub subscriptions, event handling, etc.

4. **User Logs Out**:
- The `logout` controller action deletes the HTTP-only cookie, ending the session.

---

By using HTTP-only cookies and passing the `user_id` via the session, you ensure that sensitive information (like the `user_id`) is not exposed to client-side JavaScript, improving the security of your application.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.