Help With Authentication For Phoenix: Already Have Auth Setup On PHP/MySQL

Background on my website and current authentication setup (not in Phoenix): Basically, I have a small social networking site built on PHP/MySQL. The registration/login/email verifications pages are all handled by PHP/MySQL. The “members” table is already created, containing the user’s username, password, login token, profile, registration date and everything else.

So when a user successfully logs in with their username and password, our PHP page generates a random, salty “login_token”, which gets stored in the “members” table, and also on the user’s browser with a 7-day cookie. If the user’s PHP session expires (Usually after 20-40 minutes), we compare the login token from the cookie in the browser, to the “login_token” in the member’s table in the database, and restart a new PHP session and keep them logged in. It’s basically a “Keep Me Logged In” feature. We also generate a new login token at that time, replacing the old one with the new one, and update the cookie at the same time.

Goal for Phoenix: I plan on using Phoenix to develop a variety of chatrooms, instant messaging and video chat. It’s going to be used as a supplement to my existing PHP/MySQL site.

Since PHP/MySQL handles the login authentication and creates a token, I would like all logged in users to be connected to the Phoenix app automatically. However, they still need to be authenticated in Phoenix.

I’ve been searching around for a number of guides for authentication, including phx_gen_auth, but it seems that all of these guides assume that the user is submitting the username/password directly into the Phoenix app, and that registration/login is all done through Phoenix, instead of an existing PHP/MySQL site.

I’ll explain below how I’m trying to understand this. Let’s start at the first step, socket.js has this script to connect:

let socket = new Socket("/socket", {params: {token: window.userToken}})

Is window.userToken supposed to be my login_token created from PHP, or am I supposed to add two parameters, something like?:

let socket = new Socket("/socket", {params: {token: window.userToken, login_token: window.login_token}})

Second step, the plugs go in order like this:

    pipeline :browser do
       ...
       plug MyAuth
       plug :put_user_token
     end

     defp put_user_token(conn, _) do
       if current_user = conn.assigns[:current_user] do
         token = Phoenix.Token.sign(conn, "user socket", current_user.id)
         assign(conn, :user_token, token)
       else
         conn
       end
     end

I’m not sure what MyAuth is. Is that something I’m supposed to build, where the login_token gets checked with MySQL? Can anyone provide a really simple code example for my case? And if everything looks good, the put_user_token creates a new Phoenix-based token and sends it back to the browser.

According to the guide, this creates a new userToken and adds it to:

<script>window.userToken = "<%= assigns[:user_token] %>";</script>

and then it gets verified again during the same connection?:

     def connect(%{"token" => token}, socket, _connect_info) do
       # max_age: 1209600 is equivalent to two weeks in seconds
       case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
         {:ok, user_id} ->
           {:ok, assign(socket, :user, user_id)}
         {:error, reason} ->
           :error
       end
     end

There are some things here that don’t make sense to me.

If the login_token from PHP gets sent to Phoenix during a socket connect, then checked in the Phoenix backend with MySQL to authenticate/verify the user, why do I need another userToken from Phoenix sent back to the browser? If a user sends messages to people, does the userToken get sent with every message? What exactly is userToken for? If I browse to a new page, the javascript variable window.userToken disappears and has to be re-created each time anyways.

Again, I’m a total noob with Phoenix, so I’m going to need some handholding. What would your strategy be in my case? Code corrections/examples? I want to make the Phoenix auth/app as simple as possible, without minimal calls to the database.

2 Likes