You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: guides/real_time/channels.md
+26-9Lines changed: 26 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -385,7 +385,24 @@ That's all there is to our basic chat app. Fire up multiple browser tabs and you
385
385
386
386
When we connect, we'll often need to authenticate the client. Fortunately, this is a 4-step process with [Phoenix.Token](https://hexdocs.pm/phoenix/Phoenix.Token.html).
387
387
388
-
### Step 1 - Assign a Token in the Connection
388
+
### Step 1 - Enable the `auth_token` functionality in the socket
389
+
390
+
Phoenix supports a transport agnostic way to pass an authentication token to the server. To enable this, we need to pass the `:auth_token` option to the socket declaration in our `Endpoint` module and configure the `connect_info` to include the `:auth_token` key.
391
+
392
+
```elixir
393
+
defmoduleHelloWeb.Endpointdo
394
+
usePhoenix.Endpoint, otp_app::hello
395
+
396
+
socket "/socket", HelloWeb.UserSocket,
397
+
websocket: [connect_info: [:auth_token]],
398
+
longpoll:false,
399
+
auth_token:true
400
+
401
+
...
402
+
end
403
+
```
404
+
405
+
### Step 2 - Assign a Token in the Connection
389
406
390
407
Let's say we have an authentication plug in our app called `OurAuth`. When `OurAuth` authenticates a user, it sets a value for the `:current_user` key in `conn.assigns`. Since the `current_user` exists, we can simply assign the user's token in the connection for use in the layout. We can wrap that behavior up in a private function plug, `put_user_token/2`. This could also be put in its own module as well. To make this all work, we just add `OurAuth` and `put_user_token/2` to the browser pipeline.
391
408
@@ -408,7 +425,7 @@ end
408
425
409
426
Now our `conn.assigns` contains the `current_user` and `user_token`.
410
427
411
-
### Step 2 - Pass the Token to the JavaScript
428
+
### Step 3 - Pass the Token to the JavaScript
412
429
413
430
Next, we need to pass this token to JavaScript. We can do so inside a script tag in `lib/hello_web/components/layouts/root.html.heex` right above the app.js script, as follows:
414
431
@@ -417,14 +434,14 @@ Next, we need to pass this token to JavaScript. We can do so inside a script tag
417
434
<script src={~p"/assets/app.js"}></script>
418
435
```
419
436
420
-
### Step 3 - Pass the Token to the Socket Constructor and Verify
437
+
### Step 4 - Pass the Token to the Socket Constructor and Verify
421
438
422
-
We also need to pass the `:params` to the socket constructor and verify the user token in the `connect/3` function. To do so, edit `lib/hello_web/channels/user_socket.ex`, as follows:
439
+
We also need to pass the `:auth_token` to the socket constructor and verify the user token in the `connect/3` function. To do so, edit `lib/hello_web/channels/user_socket.ex`, as follows:
423
440
424
441
```elixir
425
-
defconnect(%{"token"=> token}, socket, _connect_info) do
442
+
defconnect(_params_, socket, connect_info) do
426
443
# max_age: 1209600 is equivalent to two weeks in seconds
427
-
casePhoenix.Token.verify(socket, "user socket", token, max_age:1209600) do
444
+
casePhoenix.Token.verify(socket, "user socket", connect_info[:auth_token], max_age:1209600) do
428
445
{:ok, user_id} ->
429
446
{:ok, assign(socket, :current_user, user_id)}
430
447
{:error, reason} ->
@@ -436,17 +453,17 @@ end
436
453
In our JavaScript, we can use the token set previously when constructing the Socket:
437
454
438
455
```javascript
439
-
let socket =newSocket("/socket", {params: {token:window.userToken}})
456
+
let socket =newSocket("/socket", {authToken:window.userToken})
440
457
```
441
458
442
459
We used `Phoenix.Token.verify/4` to verify the user token provided by the client. `Phoenix.Token.verify/4` returns either `{:ok, user_id}` or `{:error, reason}`. We can pattern match on that return in a `case` statement. With a verified token, we set the user's id as the value to `:current_user` in the socket. Otherwise, we return `:error`.
443
460
444
-
### Step 4 - Connect to the socket in JavaScript
461
+
### Step 5 - Connect to the socket in JavaScript
445
462
446
463
With authentication set up, we can connect to sockets and channels from JavaScript.
447
464
448
465
```javascript
449
-
let socket =newSocket("/socket", {params: {token:window.userToken}})
466
+
let socket =newSocket("/socket", {authToken:window.userToken})
0 commit comments