Packages
phoenix
1.0.5
1.8.9
1.8.8
1.8.7
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.8.0-rc.4
1.8.0-rc.3
1.8.0-rc.2
1.8.0-rc.1
1.8.0-rc.0
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.7.0-rc.3
1.7.0-rc.2
1.7.0-rc.1
1.7.0-rc.0
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.15
1.5.14
1.5.13
1.5.12
1.5.11
1.5.10
1.5.9
1.5.8
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.0
1.4.18
1.4.17
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0-rc.3
1.3.0-rc.2
1.3.0-rc.1
1.3.0-rc.0
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.1
1.2.0-rc.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
Productive. Reliable. Fast. A productive web framework that does not compromise speed or maintainability.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/phoenix/token.ex
defmodule Phoenix.Token do
@moduledoc """
Tokens provide a way to generate, verify bearer
tokens for use in Channels or API authentication.
## Basic Usage
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(endpoint, "user", user_id)
iex> Phoenix.Token.verify(endpoint, "user", token)
{:ok, 1}
In that example we have a user's id, we generate a token and send
it to the client. We could 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
When using it with a socket a typical example might be:
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 be sending up the token
in the connect command.
`Phoenix.Token` can also be used for validating APIs, handling
password resets, e-mail confirmation and more.
"""
import Phoenix.Utils, only: [now_ms: 0]
alias Plug.Crypto.KeyGenerator
alias Plug.Crypto.MessageVerifier
@doc """
Signs your data into 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';
"""
def sign(context, salt, data, opts \\ []) when is_binary(salt) do
secret = get_endpoint(context) |> get_secret(salt, opts)
message = %{
data: data,
signed: now_ms(),
} |> :erlang.term_to_binary()
MessageVerifier.sign(message, secret)
end
@doc """
Decrypts the token into the originaly present data.
## 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';
"""
def verify(context, salt, token, opts \\ [])
def verify(context, salt, token, opts) when is_binary(salt) and is_binary(token) do
secret = get_endpoint(context) |> get_secret(salt, opts)
max_age_ms = if max_age_secs = opts[:max_age], do: trunc(max_age_secs * 1000)
case MessageVerifier.verify(token, secret) do
{:ok, message} ->
%{data: data, signed: signed} = :erlang.binary_to_term(message)
if max_age_ms && (signed + max_age_ms) < now_ms() do
{:error, :expired}
else
{:ok, data}
end
:error ->
{:error, :invalid}
end
end
def verify(_context, salt, nil, _opts) when is_binary(salt) do
{:error, :missing}
end
defp get_endpoint(%Plug.Conn{} = conn), do: Phoenix.Controller.endpoint_module(conn)
defp get_endpoint(%Phoenix.Socket{} = socket), do: socket.endpoint
defp get_endpoint(endpoint) when is_atom(endpoint), do: endpoint
# Gathers configuration and generates the key secrets and signing secrets.
defp get_secret(endpoint, salt, opts) do
secret_key_base = endpoint.config(:secret_key_base)
iterations = Keyword.get(opts, :key_iterations, 1000)
length = Keyword.get(opts, :key_length, 32)
digest = Keyword.get(opts, :key_digest, :sha256)
key_opts = [iterations: iterations,
length: length,
digest: digest,
cache: Plug.Keys]
KeyGenerator.generate(secret_key_base, salt, key_opts)
end
end