View Source Implementation Modules
Implementation modules are the heart of how you interact with Guardian in your application. Almost all functions for using Guardian are done via your implementation module.
They encapsulate the configuration and behaviour that you specify and utilize a token backend to implement the details of the type of token you've chosen (default JWT).
Previous versions of Guardian used the Guardian module directly which was very limiting. This limitation forced only a single type of token could be used for your entire application and made customization difficult, verbose and somewhat confusing.
usage
Usage
Guardian is used to encode and decode tamper proof tokens for the purpose of authentication. For integrations see the plug guide and/or the Phoenix guide. If you're using Plug or Phoenix you probably won't need to drop down to this level but from time to time it's useful.
basics
Basics
The main functions that are useful for encoding and decoding tokens are:
# create tokens
{:ok, token, full_claims} = MyApp.TokenImpl.encode_and_sign(user)
# decoding tokens
{:ok, claims} = MyApp.TokenImpl.decode_and_verify(token_string)
# decoding token and fetching resource in one step
{:ok, user, claims} = MyApp.TokenImpl.resource_from_token(token_string)
When creating tokens, you can add custom claims to your tokens. The resulting token will be a merge (in order of application) of:
- the claims provided by your token
- the claims you pass in
- any changes you make in your
Guardian.build_claims
callback
For example:
{:ok, token, full_claims} = MyApp.TokenImpl.encode_and_sign(user, %{some: "data to store"})
basic-setup
Basic Setup
The most basic setup for an implementation module consists of use Guardian
passing the atom of your otp app. See JWT implementation for specific information about setting up for JWT.
defmodule MyApp.TokenImpl do
use Guardian, otp_app: :my_app
def subject_for_token(resource, options) do
{:ok, resource.id}
end
def resource_from_claims(claims) do
# find user from claims["sub"] or other information you stored inside claims
end
end
This setup will use your configuration and the default options.
If you want to change your token backend, you can use the :token_module
option in your configuration.
The functions subject_for_token
and resource_from_claims
are the only two functions that must be implemented. They are effectively opposites of one another.
subject_for_token
- provide the identifier to be encoded into your token that you will use inresource_from_claims
to lookup the resourceresource_from_claims
- using the identifier provided bysubject_for_token
find the associated resource
All other callbacks have a default noop in their implementations and are optional.
subject_for_token
provides the sub
field (in JWT parlance) which identifies the subject which is usually the resource to use. The subject field can be anything that helps you identify which resource is logged in. Some examples:
"User:420"
"420"
"u|420"
Some thought about what this is can be useful. If you have more than one type of struct that you want to be able to authenticate prefixing with some type of struct identifier is helpful to switch (prefix can be pattern matched, suffix cannot). Once your token is out in the wild, you will need to support all of those subject schemes until the last issued token expires or is revoked. An example of pattern matching via a prefix:
def subject_for_token(%User{uid: uid} = user, _claims) do
{:ok, "User:#{uid}"}
end
def subject_for_token(_, _), do: {:error, :unhandled_resource_type}
def resource_from_claims(%{"sub" => "User:" <> uid}) do
case Repo.get_by(User, %{uid: uid}) do
nil -> {:error, :user_not_found}
user -> {:ok, user}
end
end
def resource_from_claims(_), do: {:error, :unhandled_resource_type}
configuration
Configuration
Configuration for your implementation module can be done either in your configuration files using the same otp_app
identifier as your call to use Guardian
. Alternatively you can provide options to the use Guardian
call to put your configuration there. Configuration provided in your implementation module takes precedence over anything found in the configuration files. You can also put some parts in your config and some in your configuration files to account for different environments.
callbacks
Callbacks
Guardian provides callbacks to allow you to hook into different parts of the authentication lifecycle. These callbacks can be used for any purpose and are used by the GuardianDB package.
The most common callbacks to use are:
build_claims
verify_claims
Using the build_claims
callback you can modify the structure of the claims any way you need to. You can add, change or remove any key/value pairs added by your token module.
Using the verify_claims
callback you can implement any custom validation you require on your tokens.
There are other callbacks available.