View Source Guardian behaviour (Guardian v2.3.0)

Guardian provides a singular interface for authentication in Elixir applications that is token based.

Tokens should be:

  • tamper proof
  • include a payload (claims)

JWT tokens (the default) fit this description.

When using Guardian, you'll need an implementation module.

defmodule MyApp.Guardian do
  use Guardian, otp_app: :my_app

  def subject_for_token(resource, _claims), do: {:ok, to_string(resource.id)}
  def resource_from_claims(claims) do
    find_me_a_resource(claims["sub"]) # {:ok, resource} or {:error, reason}
  end
end

This module is what you will use to interact with tokens in your application.

When you use Guardian, the :otp_app option is required. Any other option provided will be merged with the configuration in the config files.

The Guardian module contains some generated functions and some callbacks.

generated-functions

Generated functions

default_token_type

default_token_type()

Overridable.

Provides the default token type for the token - "access"

Token types allow a developer to mark a token as having a particular purpose. Different types of tokens can then be used specifically in your app.

Types may include (but are not limited to):

  • "access"
  • "refresh"

Access tokens should be short lived and are used to access resources on your API. Refresh tokens should be longer lived and whose only purpose is to exchange for a shorter lived access token.

To specify the type of token, use the :token_type option in the encode_and_sign function.

Token type is encoded into the token in the "typ" field.

Return - a string.

peek-token

peek(token)

Inspect a tokens payload. Note that this function does no verification.

Return - a map including the :claims key.

config-config-key-default-nil

config(), config(key, default \\ nil)

Without argument config will return the full configuration Keyword list.

When given a key and optionally a default, config will fetch a resolved value contained in the key.

See Guardian.Config.resolve_value/1

encode_and_sign-resource-claims-opts

encode_and_sign(resource, claims \\ %{}, opts \\ [])

Creates a signed token.

Arguments:

  • resource - The resource to represent in the token (i.e. the user)
  • claims - Any custom claims that you want to use in your token
  • opts - Options for the token module and callbacks

For more information on options see the documentation for your token module.

# Provide a token using the defaults including the default_token_type
{:ok, token, full_claims} = MyApp.Guardian.encode_and_sign(user)

# Provide a token including custom claims
{:ok, token, full_claims} = MyApp.Guardian.encode_and_sign(user, %{some: "claim"})

# Provide a token including custom claims and a different token type/ttl
{:ok, token, full_claims} =
  MyApp.Guardian.encode_and_sign(user, %{some: "claim"}, token_type: "refresh", ttl: {4, :weeks})

The encode_and_sign function calls a number of callbacks on your implementation module. See Guardian.encode_and_sign/4

decode_and_verify-token-claims_to_check-opts

decode_and_verify(token, claims_to_check \\ %{}, opts \\ [])

Decodes a token and verifies the claims are valid.

Arguments:

  • token - The token to decode
  • claims_to_check - A map of the literal claims that should be matched. If any of the claims do not literally match verification fails.
  • opts - The options to pass to the token module and callbacks

Callbacks:

decode_and_verify calls a number of callbacks on your implementation module, See Guardian.decode_and_verify/4

# Decode and verify using the defaults
{:ok, claims} = MyApp.Guardian.decode_and_verify(token)

# Decode and verify with literal claims check.
# If the claims in the token do not match those given verification will fail
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{match: "claim"})

# Decode and verify with literal claims check and options.
# Options are passed to your token module and callbacks
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{match: "claim"}, some: "secret")

revoke-token-opts

revoke(token, opts \\ [])

Revoke a token.

Note: this is entirely dependent on your token module and implementation callbacks.

{:ok, claims} = MyApp.Guardian.revoke(token, some: "option")

refresh-token-opts

refresh(token, opts \ [])

Refreshes the time on a token. This is used to re-issue a token with essentially the same claims but with a different expiry.

Tokens are verified before performing the refresh to ensure only valid tokens may be refreshed.

Arguments:

  • token - The old token to refresh
  • opts - Options to pass to the Implementation Module and callbacks

Options:

  • :ttl - The new ttl. If not specified the default will be used.
{:ok, {old_token, old_claims}, {new_token, new_claims}} =
  MyApp.Guardian.refresh(old_token, ttl: {1, :hour})

See Guardian.refresh

exchange-old_token-from_type-to_type-options

exchange(old_token, from_type, to_type, options)

Exchanges one token for another of a different type. Especially useful to trade in a refresh token for an access one.

Tokens are verified before performing the exchange to ensure that only valid tokens may be exchanged.

Arguments:

  • old_token - The existing token you wish to exchange.
  • from_type - The type the old token must be. Can be given a list of types.
  • to_type - The new type of token that you want back.
  • options - The options to pass to the token module and callbacks.

Options:

Options may be used by your token module or callbacks.

  • ttl - The ttl for the new token

See Guardian.exchange

Link to this section Summary

Callbacks

An optional callback invoked after the token has been generated and signed.

An optional callback invoked after sign in has been called.

An optional callback invoked before sign out has happened.

An optional callback that allows the claims to be modified while they're being built.

An optional callback invoked when a token is exchanged.

An optional callback invoked when a token is refreshed.

An optional callback invoked when a token is revoked.

An optional callback invoked after the claims have been validated.

Fetches the resource that is represented by claims.

Fetches the subject for a token for the provided resource and claims The subject should be a short identifier that can be used to identify the resource.

An optional callback to add custom verification to claims when decoding a token.

Functions

Decodes a token using the configuration of the implementation module.

Creates a signed token for a resource.

Exchanges one token for another with different token types.

Returns an inspection of the token (at least claims) without any verification.

Refreshes a token keeping all main claims intact.

Fetch the resource and claims directly from a token.

Converts keys in a map or list of maps to strings.

Provides the current system time in seconds.

Link to this section Types

@type conditional_tuple() :: {:ok, any()} | {:error, any()}
@type options() :: Keyword.t()

Link to this section Callbacks

Link to this callback

after_encode_and_sign(resource, claims, token, options)

View Source
@callback after_encode_and_sign(
  resource :: any(),
  claims :: Guardian.Token.claims(),
  token :: Guardian.Token.token(),
  options :: options()
) :: {:ok, Guardian.Token.token()} | {:error, atom()}

An optional callback invoked after the token has been generated and signed.

Link to this callback

after_sign_in(conn, resource, token, claims, options)

View Source
@callback after_sign_in(
  conn :: Plug.Conn.t(),
  resource :: any(),
  token :: Guardian.Token.token(),
  claims :: Guardian.Token.claims(),
  options :: options()
) :: {:ok, Plug.Conn.t()} | {:error, atom()}

An optional callback invoked after sign in has been called.

By returning an error the sign in will be halted.

  • Note that if you return an error, a token still may have been generated.
Link to this callback

before_sign_out(conn, location, options)

View Source
@callback before_sign_out(
  conn :: Plug.Conn.t(),
  location :: atom() | nil,
  options :: options()
) ::
  {:ok, Plug.Conn.t()} | {:error, atom()}

An optional callback invoked before sign out has happened.

Link to this callback

build_claims(claims, resource, opts)

View Source
@callback build_claims(
  claims :: Guardian.Token.claims(),
  resource :: Guardian.Token.resource(),
  opts :: options()
) :: {:ok, Guardian.Token.claims()} | {:error, atom()}

An optional callback that allows the claims to be modified while they're being built.

This is useful to hook into the encoding lifecycle.

Link to this callback

on_exchange(old_token_and_claims, new_token_and_claims, options)

View Source
@callback on_exchange(
  old_token_and_claims :: {Guardian.Token.token(), Guardian.Token.claims()},
  new_token_and_claims :: {Guardian.Token.token(), Guardian.Token.claims()},
  options :: options()
) ::
  {:ok, {Guardian.Token.token(), Guardian.Token.claims()},
   {Guardian.Token.token(), Guardian.Token.claims()}}
  | {:error, any()}

An optional callback invoked when a token is exchanged.

Link to this callback

on_refresh(old_token_and_claims, new_token_and_claims, options)

View Source
@callback on_refresh(
  old_token_and_claims :: {Guardian.Token.token(), Guardian.Token.claims()},
  new_token_and_claims :: {Guardian.Token.token(), Guardian.Token.claims()},
  options :: options()
) ::
  {:ok, {Guardian.Token.token(), Guardian.Token.claims()},
   {Guardian.Token.token(), Guardian.Token.claims()}}
  | {:error, any()}

An optional callback invoked when a token is refreshed.

Link to this callback

on_revoke(claims, token, options)

View Source
@callback on_revoke(
  claims :: Guardian.Token.claims(),
  token :: Guardian.Token.token(),
  options :: options()
) :: {:ok, Guardian.Token.claims()} | {:error, any()}

An optional callback invoked when a token is revoked.

Link to this callback

on_verify(claims, token, options)

View Source
@callback on_verify(
  claims :: Guardian.Token.claims(),
  token :: Guardian.Token.token(),
  options :: options()
) :: {:ok, Guardian.Token.claims()} | {:error, any()}

An optional callback invoked after the claims have been validated.

Link to this callback

resource_from_claims(claims)

View Source
@callback resource_from_claims(claims :: Guardian.Token.claims()) ::
  {:ok, Guardian.Token.resource()} | {:error, atom()}

Fetches the resource that is represented by claims.

For JWT this would normally be found in the sub field.

Link to this callback

subject_for_token(resource, claims)

View Source
@callback subject_for_token(
  resource :: Guardian.Token.resource(),
  claims :: Guardian.Token.claims()
) :: {:ok, String.t()} | {:error, atom()}

Fetches the subject for a token for the provided resource and claims The subject should be a short identifier that can be used to identify the resource.

Link to this callback

verify_claims(claims, options)

View Source
@callback verify_claims(claims :: Guardian.Token.claims(), options :: options()) ::
  {:ok, Guardian.Token.claims()} | {:error, atom()}

An optional callback to add custom verification to claims when decoding a token.

Returning {:ok, claims} will allow the decoding to continue. Returning {:error, reason} will stop the decoding and return the error.

Link to this section Functions

Link to this function

decode_and_verify(mod, token, claims_to_check \\ %{}, opts \\ [])

View Source
@spec decode_and_verify(
  module(),
  Guardian.Token.token(),
  Guardian.Token.claims(),
  options()
) ::
  {:ok, Guardian.Token.claims()} | {:error, any()}

Decodes a token using the configuration of the implementation module.

This will, using that configuration, delegate to the token module.

Once the token module has decoded the token, your implementation module has an opportunity to further verify the claims contained in the token using the verify_claims callback.

lifecycle

Lifecycle

Once called, a number of callbacks will be invoked on the implementation module:

  • verify_claims - add custom claim verification, returns an error if the claims are not valid
  • on_verify - called after a successful verification

options

Options

The options will be passed through to the implementation / token modules and the appropriate callbacks.

See the documentation for your implementation / token modules for more information on which options are available.

Link to this function

encode_and_sign(mod, resource, claims \\ %{}, opts \\ [])

View Source
@spec encode_and_sign(module(), any(), Guardian.Token.claims(), options()) ::
  {:ok, Guardian.Token.token(), Guardian.Token.claims()} | {:error, any()}

Creates a signed token for a resource.

The actual encoding depends on the implementation module which should be referenced for specifics.

lifecycle

Lifecycle

Once called, a number of callbacks will be invoked on the implementation module:

  • subject_for_token - gets the subject from the resource
  • build_claims - allows the implementation module to add or modify claims before the token is created
  • after_encode_and_sign

options

Options

The options will be passed through to the implementation / token modules and the appropriate callbacks.

  • ttl - How long to keep the token alive for. If not included the default will be used.
  • token_type - The type of token to generate if different from the default.

The ttl option should take {integer, unit} where unit is one of:

  • :second | :seconds

  • :minute | :minutes

  • :hour | :hours

  • :week | :weeks

See the documentation for your implementation / token module for more information on which options are available for your implementation / token module.

Link to this function

exchange(mod, old_token, from_type, to_type, opts)

View Source

Exchanges one token for another with different token types.

The token is first decoded and verified to ensure that there is no escalation Of privileges.

Tokens must have their type included in the from_type argument.

lifecycle

Lifecycle

  • <TokenModule>.exchange - exchange the old token for the new one
  • <ImplModule>.on_exchange - will be invoked after the exchange happens

options

Options

All options are passed through all calls to the token module and appropriate callbacks.

@spec peek(module(), Guardian.Token.token()) :: %{claims: map()}

Returns an inspection of the token (at least claims) without any verification.

This should not be relied on since there is no verification.

The implementation is provided by the implementation module specified. See the documentation for your implementation / token module for full details.

Link to this function

refresh(mod, old_token, opts)

View Source

Refreshes a token keeping all main claims intact.

options

Options

  • ttl - How long to keep the token alive for. If not included the default will be used.

The ttl option should take {integer, unit} where unit is one of:

  • :second | :seconds

  • :minute | :minutes

  • :hour | :hours

  • :day | :days

  • :week | :weeks

See documentation for your token module for other options.

Link to this function

resource_from_token(mod, token, claims_to_check \\ %{}, opts \\ [])

View Source
@spec resource_from_token(
  mod :: module(),
  token :: Guardian.Token.token(),
  claims_to_check :: Guardian.Token.claims() | nil,
  opts :: options()
) :: {:ok, Guardian.Token.resource(), Guardian.Token.claims()} | {:error, any()}

Fetch the resource and claims directly from a token.

This is a convenience function that first decodes the token using Guardian.decode_and_verify/4 and then loads the resource.

Link to this function

revoke(mod, token, opts \\ [])

View Source
@spec revoke(module(), Guardian.Token.token(), options()) ::
  {:ok, Guardian.Token.claims()} | {:error, any()}

Revoke a token.

Note: This is entirely dependent on the token module and callbacks.

lifecycle

Lifecycle

  • <TokenModule>.revoke
  • <ImplModule>.on_revoke

options

Options

The options are passed through to the token module and callback so check the documentation for your token module.

@spec stringify_keys(map() | list() | any()) :: map() | list() | any()

Converts keys in a map or list of maps to strings.

@spec timestamp() :: pos_integer()

Provides the current system time in seconds.