Authex v0.3.1 Authex behaviour View Source
Defines an auth module.
This module provides a simple set of tools for the authorization and authentication required by a typical API through use of JSON web tokens. To get started, we need to define our auth module:
defmodule MyApp.Auth do
use Authex, otp_app: :my_app
end
We must then add the auth module to our supervision tree.
children = [
MyApp.Auth
]
Configuration
While our auth module is defined, we will need to further configure it to our requirements. At a minimum, we need to add a secret from which our tokens will be signed with. There is a convenient mix task available for this:
mix authex.gen.secret
We should now add this secret to our config. In production this should be set
via an env var. We should use the init/1
callback to configure this:
defmodule MyApp.Auth do
use Authex, otp_app: :my_app
def init(config) do
secret = System.get_env("AUTH_SECRET")
config = Keyword.put(config, :secret, secret)
{:ok, config}
end
end
Any other config can either be set with the start_link/1
or init/1
callbacks,
or via application config. Below are some of the values available:
config :my_app, MyApp.Auth, [
# REQUIRED
# The secret used to sign tokens with.
secret: "mysecret",
# OPTIONAL
# A blacklist repo, or false if disabled.
blacklist: false,
# A banlist repo, or false if disabled.
banlist: false,
# The default algorithm used to sign tokens.
default_alg: :hs256,
# The default iss claim used in tokens.
default_iss: nil,
# The default aud claim used in tokens.
default_aud: nil,
# The default time to live for tokens in seconds.
default_ttl: 3600,
# The default module, function, and arg used to generate the jti claim.
jti_mfa: {UUID, :uuid4, [:hex]}
# The plug called when an unauthorized status is determined.
unauthorized: Authex.UnauthorizedPlug
# The plug called when an forbidden status is determined.
forbidden: Authex.ForbiddenPlug
]
Tokens
At the heart of Authex is the Authex.Token
struct. This struct is simply
a wrapper around the typical JWT claims. The only additional item is the
:scopes
and :meta
key. There are 3 base actions required for these tokens -
creation, signing, and verification.
Creating
We can easily create token structs using the token/2
function.
MyApp.Auth.token(sub: 1, scopes: ["admin/read"])
The above would create a token struct for a user with an id of 1 and with "admin/read" authorization.
Signing
Once we have a token struct, we can sign it using the sign/2
function to
create a compact token binary. This is what we will use for authentication and
authorization for our API.
[sub: 1, scopes: ["admin/read"]]
|> MyApp.Auth.token()
|> MyApp.Auth.sign()
Verifying
Once we have a compact token binary, we can verify it and turn it back to an
token struct using the verify/2
function.
[sub: 1, scopes: ["admin/read"]]
|> MyApp.Auth.token()
|> MyApp.Auth.sign()
|> MyApp.Auth.verify()
Serializers
Typically, we want to be able to create tokens from another source of data.
This could be something like a User
struct. We also will want to take a token
and turn it back into a User
struct.
To do this, we must create a serializer. A serializer is simply a module that
adopts the Authex.Serializer
behaviour. For more information on creating
serializers, please see the Authex.Serializer
documention.
Once we have created our serializer, we define it in our config.
config :my_app, MyApp.Auth, [
serializer: MyApp.Auth.UserSerializer,
]
We can now easily create tokens and compact tokens from our custom data using
the for_token/2
and for_compact_token/3
functions.
user = %MyApp.User{id: 1, scopes: []}
{:ok, token} = MyApp.Auth.for_token(user) # returns a token struct
{:ok, compact_token} = MyApp.Auth.for_compact_token(user) # returns a compact token
We can also turn tokens and compact tokens back into our custom data using the
from_token/2
and from_compact_token/2
functions.
user = %MyApp.User{id: 1, scopes: []}
{:ok, token} = MyApp.Auth.for_token(user)
{:ok, user} = MyApp.Auth.from_token(token)
{:ok, compact_token} = MyApp.Auth.for_compact_token(user)
{:ok, user} = MyApp.Auth.from_compact_token(compact_token)
Repositories
Usually, use of JSON web tokens requires some form of persistence to blacklist
tokens through their :jti
claim. Authex also adds the ability to ban a
token through its :sub
claim.
To do this, we must create a repository. A repository is simply a module that
adopts the Authex.Repo
behaviour. For more information on creating
repositories, please see the Authex.Repo
documention.
Once we have created our blacklist or banlist repo, we define it in our config.
config :my_app, MyApp.Auth, [
blacklist: MyApp.Auth.Blacklist,
banlist: MyApp.Auth.Banlist
]
During the verification process used by verify/2
, any blacklist or banlist
defined in our config will be checked against. Please be aware of any performance
penatly that may be incurred through use of database-backed repo's without use
of caching.
Plugs
Authex provides a number of plugs to handle the typical authentication and authorization process required by an API using your auth module.
For more information on handling authentication, please see the Authex.AuthenticationPlug
documention.
For more information on handling authorization, please see the Authex.AuthorizationPlug
documention.
Link to this section Summary
Callbacks
Bans a token subject
Checks whether a token subject is banned
Blacklists a token jti
Checks whether a token jti is blacklisted
Fetches a config value
Gets the current scopes from a Plug.Conn
Gets the current user from a Plug.Conn
Converts a resource into a compact token
Converts a resource into an Authex.Token
struct
Verifies and converts a compact token into a resource
Converts an Authex.Token
struct into a resource
A callback executed when the auth process starts
Saves the config that is currently associated with our auth module
Sets the config that is used with our auth module
Sets a single config that is used with our auth module
Signs a token, creating a compact token
Starts the auth process
Creates a new token
Unbans a token subject
Unblacklists a token jti
Verifies a compact token
Link to this section Types
alg()
View Source
alg() :: :hs256 | :hs384 | :hs512
alg() :: :hs256 | :hs384 | :hs512
signer_option() View Source
signer_options()
View Source
signer_options() :: [signer_option()]
signer_options() :: [signer_option()]
t()
View Source
t() :: module()
t() :: module()
verifier_option() View Source
verifier_options()
View Source
verifier_options() :: [verifier_option()]
verifier_options() :: [verifier_option()]
Link to this section Callbacks
ban(token)
View Source
ban(token :: Authex.Token.t()) :: :ok | :error
ban(token :: Authex.Token.t()) :: :ok | :error
Bans a token subject.
This uses the banlist repo defined in the auth config. The key is the :sub
key in the token.
Returns :ok
on success, or :error
on failure.
Example
MyApp.Auth.ban(token)
banned?(token)
View Source
banned?(token :: Authex.Token.t()) :: boolean()
banned?(token :: Authex.Token.t()) :: boolean()
Checks whether a token subject is banned.
This uses the banlist repo defined in the auth config. The key is the :sub
key in the token.
Returns a boolean.
Example
MyApp.Auth.banned?(token)
blacklist(token)
View Source
blacklist(token :: Authex.Token.t()) :: :ok | :error
blacklist(token :: Authex.Token.t()) :: :ok | :error
Blacklists a token jti.
This uses the blaclist repo defined in the auth config. The key is the :jti
key in the token.
Returns :ok
on success, or :error
on failure.
Example
MyApp.Auth.blacklist(token)
blacklisted?(token)
View Source
blacklisted?(token :: Authex.Token.t()) :: boolean()
blacklisted?(token :: Authex.Token.t()) :: boolean()
Checks whether a token jti is blacklisted.
This uses the blaclist repo defined in the auth config. The key is the :jti
key in the token.
Returns a boolean.
Example
MyApp.Auth.blacklisted?(token)
config(key, default) View Source
Fetches a config value.
current_scopes(arg0)
View Source
current_scopes(Plug.Conn.t()) :: {:ok, list()} | :error
current_scopes(Plug.Conn.t()) :: {:ok, list()} | :error
Gets the current scopes from a Plug.Conn
.
current_user(arg0)
View Source
current_user(Plug.Conn.t()) :: {:ok, term()} | :error
current_user(Plug.Conn.t()) :: {:ok, term()} | :error
Gets the current user from a Plug.Conn
.
for_compact_token(term, token_opts, signer_options)
View Source
for_compact_token(
term(),
token_opts :: Authex.Token.options(),
signer_options()
) :: {:ok, Authex.Token.compact()} | {:error, term()}
for_compact_token( term(), token_opts :: Authex.Token.options(), signer_options() ) :: {:ok, Authex.Token.compact()} | {:error, term()}
Converts a resource into a compact token.
Returns {:ok, compact_token}
or {:error, reason}
Options
Please see the options available in token/2
.
Example
{:ok, compact_token} = MyApp.Auth.for_compact_token(user)
for_token(term, options)
View Source
for_token(term(), options :: Authex.Token.options()) ::
{:ok, Authex.Token.t()} | {:error, term()}
for_token(term(), options :: Authex.Token.options()) :: {:ok, Authex.Token.t()} | {:error, term()}
Converts a resource into an Authex.Token
struct.
This uses the serializer defined in the auth config. It will invoke the
Authex.Serializer.for_token/2
callback defined in the serializer module.
Please see the Authex.Serializer
documentation for more details on implementing
a serializer.
Returns {:ok, token}
or {:error, reason}
Options
Please see the options available in token/2
.
Example
{:ok, token} = MyApp.Auth.for_token(user)
from_compact_token(compact_token, verifier_options)
View Source
from_compact_token(compact_token :: Authex.Token.compact(), verifier_options()) ::
{:ok, term()} | {:error, atom()}
from_compact_token(compact_token :: Authex.Token.compact(), verifier_options()) :: {:ok, term()} | {:error, atom()}
Verifies and converts a compact token into a resource.
Once verified, this invokes from_token/2
with the verified token. Please see
from_token/2
for additional details.
Returns {:ok, resource}
or {:error, reason}
Options
Please see the options available in verify/2
. You can also include any
additional options your serializer might need.
Example
{:ok, user} = MyApp.Auth.from_compact_token(compact_token)
from_token(token, options)
View Source
from_token(token :: Authex.Token.t(), options :: Keyword.t()) ::
{:ok, term()} | {:error, term()}
from_token(token :: Authex.Token.t(), options :: Keyword.t()) :: {:ok, term()} | {:error, term()}
Converts an Authex.Token
struct into a resource.
This uses the serializer defined in the auth config. It will invoke the
Authex.Serializer.from_token/2
callback defined in the serializer module.
Please see the Authex.Serializer
documentation for more details on implementing
a serializer.
Returns {:ok, resource}
or {:error, reason}
Options
Any additional options your serializer might need.
Example
{:ok, user} = MyApp.Auth.from_token(token)
init(config) View Source
A callback executed when the auth process starts.
This should be used to dynamically set any config during runtime - such as the secret key used to sign tokens with.
Returns {:ok, config}
Example
def init(config) do
secret = System.get_env("AUTH_SECRET")
config = Keyword.put(config, :secret, secret)
{:ok, config}
end
save_config()
View Source
save_config() :: :ok | :error
save_config() :: :ok | :error
Saves the config that is currently associated with our auth module.
save_config(keyword)
View Source
save_config(keyword()) :: :ok | :error
save_config(keyword()) :: :ok | :error
Sets the config that is used with our auth module.
save_config(atom, any) View Source
Sets a single config that is used with our auth module.
sign(token, signer_options)
View Source
sign(token :: Authex.Token.t(), signer_options()) ::
Authex.Token.compact() | no_return()
sign(token :: Authex.Token.t(), signer_options()) :: Authex.Token.compact() | no_return()
Signs a token, creating a compact token.
The compact token is a binary that can be used for authentication and authorization purposes. Typically, this would be placed in an HTTP header, such as:
Authorization: Bearer mytoken
Returns compact_token
or raises an Authex.Error
.
Options
:secret
- The secret key to sign the token with.:alg
- The algorithm to sign the token with.
Any option provided would override the default set in the config.
start_link(config)
View Source
start_link(config :: Keyword.t()) :: GenServer.on_start()
start_link(config :: Keyword.t()) :: GenServer.on_start()
Starts the auth process.
Returns {:ok, pid}
on success.
Returns {:error, {:already_started, pid}}
if the auth process is already
started or {:error, term}
in case anything else goes wrong.
Options
See the configuration in the moduledoc for options.
token(claims, options)
View Source
token(claims :: Authex.Token.claims(), options :: Authex.Token.options()) ::
Authex.Token.t()
token(claims :: Authex.Token.claims(), options :: Authex.Token.options()) :: Authex.Token.t()
Creates a new token.
A token is a struct that wraps the typical JWT claims but also adds a couple
new fields. Please see the Authex.Token
documentation for more details.
Returns an Authex.Token
struct,
Options
:time
- The base time (timestamp format) in which to use.:ttl
- The time-to-live for the token in seconds. The lifetime is based on the time provided via the options, or the current time if not provided.
Example
MyApp.Auth.token(sub: 1, scopes: ["admin/read"])
unban(token)
View Source
unban(token :: Authex.Token.t()) :: :ok | :error
unban(token :: Authex.Token.t()) :: :ok | :error
Unbans a token subject.
This uses the banlist repo defined in the auth config. The key is the :sub
key in the token.
Returns :ok
on success, or :error
on failure.
Example
MyApp.Auth.unban(token)
unblacklist(token)
View Source
unblacklist(token :: Authex.Token.t()) :: :ok | :error
unblacklist(token :: Authex.Token.t()) :: :ok | :error
Unblacklists a token jti.
This uses the blaclist repo defined in the auth config. The key is the :jti
key in the token.
Returns :ok
on success, or :error
on failure.
Example
MyApp.Auth.unblacklist(token)
verify(compact_token, options)
View Source
verify(compact_token :: Authex.Token.compact(), options :: verifier_options()) ::
{:ok, Authex.Token.t()} | {:error, term()}
verify(compact_token :: Authex.Token.compact(), options :: verifier_options()) :: {:ok, Authex.Token.t()} | {:error, term()}
Verifies a compact token.
Verification is a multi-step process that ensures:
- The token has not been tampered with.
- The current time is not before the
nbf
value. - The current time is not after the
exp
value. - The token
jti
is not included in the blacklist (if provided). - The token
sub
is not included in the banlist (if provided).
If all checks pass, the token is deemed verified.
Options
:time
- The base time (timestamp format) in which to use.:secret
- The secret key to verify the token with.:alg
- The algorithm to verify the token with:banlist
- The banlist module to verify with.:blacklist
- The blacklist module to verify with.
Any option provided would override the default set in the config.
Returns {:ok, token}
or {:error, reason}
Example
{:ok, token} = MyApp.Auth.verify(compact_token)