ExCrypto v0.10.0 ExCrypto.Token
Use ExCrypto.Token
to create unforgeable HMAC tokens that expire after a TTL.
Tokens created with this module have the following properties:
- unforgeable
- expire after a given TTL
- may contain useful information in the payload (e.g. user_id or permissions)
- safe to use in HTTP headers or URLs (encoded with
Base.url_encode64/1
)
Basic usage
Often it's convenient to include a JSON Object as the payload. That way the data in the payload is available after the token is verified like this:
iex> payload = %{"user_id" => 12345}
iex> encoded_payload = Poison.encode!(payload)
iex> {:ok, secret} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, token} = ExCrypto.Token.create(encoded_payload, secret)
iex> ttl = (15 * 60) # 15 minute TTL (in seconds)
iex> {:ok, verified_payload} = ExCrypto.Token.verify(token, secret, ttl)
iex> decoded_verified_payload = Poison.decode!(verified_payload)
iex> assert(decoded_verified_payload == payload)
iex> Map.get(decoded_verified_payload, "user_id")
12345
Notes
- the payload is not encrypted, only base64 encoded, do not include secrets in the payload
- do not create a new secret each time, it must be stored and kept secret
- do not include the secret in the payload
- store the secret in the config for your app if using one global secret
- store the secret on a given record (e.g. user record) if using a unique secret for each user
Link to this section Summary
Functions
Generate a signed token that carries of timestamp of when it was signed
Like create/3
but raises an exception on error
Check if a given binary has the correct structure to be a token
Update the signature on an existing token
Verify a token. Ensure the signature is no older than the ttl
Like verify/4
but raises an exception on error
Link to this section Types
option()
options()
options() :: [option()]
options() :: [option()]
payload()
payload() :: binary()
payload() :: binary()
token()
token() :: binary()
token() :: binary()
Link to this section Functions
create(payload, secret, opts \\ [])
Generate a signed token that carries of timestamp of when it was signed.
Examples
iex> payload = "my binary payload"
iex> {:ok, secret} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, token} = ExCrypto.Token.create(payload, secret)
iex> ExCrypto.Token.is_token?(token)
true
create!(payload, secret, opts \\ [])
Like create/3
but raises an exception on error.
is_token?(token)
is_token?(binary()) :: true | false
is_token?(binary()) :: true | false
Check if a given binary has the correct structure to be a token.
This does not mean it is a valid token, only that it has all the parts of a token.
Examples
iex> payload = "my binary payload"
iex> {:ok, secret} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, token} = ExCrypto.Token.create(payload, secret)
iex> ExCrypto.Token.is_token?(token)
true
update(token, secret, ttl, opts \\ [])
Update the signature on an existing token.
This is useful if you want to have a token that expires quickly, but only if it is not being used.
For example, if you use these tokens in a cookie for authentication in a web app, you can update the token each time the user makes a request, and send the updated cookie in the response.
This way a user can be logged out after N minutes of inactivity without requiring the user to supply credentials every N minutes.
This is also useful if the payload is expensive to create in the first place.
Another important benefit is that since the token is rotated with each request stealing a token becomes much less valuable. It's not impossible, but because the token changes with each request old tokens are only good until their TTL expires.
Examples
iex> payload = "my binary payload"
iex> {:ok, secret} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, token} = ExCrypto.Token.create(payload, secret)
iex> ExCrypto.Token.is_token?(token)
true
iex> ttl = (15 * 60) # 15 minute TTL (in seconds)
iex> {:ok, {update_token, update_payload}} = ExCrypto.Token.update(token, secret, ttl)
iex> update_payload == payload
true
iex> {:ok, verified_payload} = ExCrypto.Token.verify(update_token, secret, ttl)
iex> verified_payload == payload
true
verify(token, secret, ttl, opts \\ [])
Verify a token. Ensure the signature is no older than the ttl
.
Examples
iex> payload = "my binary payload"
iex> {:ok, secret} = ExCrypto.generate_aes_key(:aes_256, :bytes)
iex> {:ok, token} = ExCrypto.Token.create(payload, secret)
iex> ExCrypto.Token.is_token?(token)
true
iex> ttl = (15 * 60) # 15 minute TTL (in seconds)
iex> {:ok, verified_payload} = ExCrypto.Token.verify(token, secret, ttl)
iex> verified_payload == payload
true
verify!(token, secret, ttl, opts \\ [])
Like verify/4
but raises an exception on error.