Phoenix v1.2.4 Phoenix.Token

Tokens provide a way to generate and verify bearer tokens for use in Channels or API authentication.

The data can be read by clients, but the message is signed to prevent tampering.

Example

When generating a unique token for usage in an API or Channel it is advised to use a unique identifier for the user typically the id from a database. For example:

iex> user_id = 1
iex> token = Phoenix.Token.sign(MyApp.Endpoint, "user", user_id)
iex> Phoenix.Token.verify(MyApp.Endpoint, "user", token)
{:ok, 1}

In that example we have a user’s id, we generate a token and verify it using the secret key base configured in the given endpoint.

The first argument to both sign/4 and verify/4 can be one of:

  • the module name of a Phoenix endpoint (shown above) - where the secret key base is extracted from the endpoint
  • Plug.Conn - where the secret key base is extracted from the endpoint stored in the connection
  • Phoenix.Socket - where the secret key base is extracted from the endpoint stored in the socket
  • a string, representing the secret key base itself. We recommend a key base with at least 20 characters to provide enough entropy

Usage

Once a token is signed, we can send it to the client in multiple ways.

One is via the meta tag:

<%= tag :meta, name: "channel_token",
               content: Phoenix.Token.sign(@conn, "user", @current_user.id) %>

Or an endpoint that returns it:

def create(conn, params) do
  user = User.create(params)
  render conn, "user.json",
         %{token: Phoenix.Token.sign(conn, "user", user.id), user: user}
end

Once the token is sent, the client may now send it back to the server as an authentication mechanism. For example, we can use it to authenticate a user on a Phoenix channel:

defmodule MyApp.UserSocket do
  use Phoenix.Socket

  def connect(%{"token" => token}, socket) do
    # Max age of 2 weeks (1209600 seconds)
    case Phoenix.Token.verify(socket, "user", token, max_age: 1209600) do
      {:ok, user_id} ->
        socket = assign(socket, :user, Repo.get!(User, user_id))
        {:ok, socket}
      {:error, _} ->
        :error
    end
  end
end

In this example, the phoenix.js client will send the token in the connect command which is then validated by the server.

Phoenix.Token can also be used for validating APIs, handling password resets, e-mail confirmation and more.

Summary

Functions

Encodes data and signs it resulting in a token you can send down to clients

Decodes the original data from the token and verifies its integrity

Functions

sign(context, salt, data, opts \\ [])

Encodes data and signs it resulting in a token you can send down to clients.

Options

  • :key_iterations - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000;
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32;
  • :key_digest - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to `:sha256’;
verify(context, salt, token, opts \\ [])

Decodes the original data from the token and verifies its integrity.

Options

  • :max_age - verifies the token only if it has been generated “max age” ago in seconds. A reasonable value is 2 weeks (1209600 seconds);
  • :key_iterations - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 1000;
  • :key_length - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to 32;
  • :key_digest - option passed to Plug.Crypto.KeyGenerator when generating the encryption and signing keys. Defaults to `:sha256’;