### Starting Phoenix Server (Shell)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
Starts the Phoenix web server, making the application accessible via a web browser at the configured port, typically 4000. This command is essential for running the web application and testing its routes.
```sh
$ mix phx.server
```
--------------------------------
### Starting Elixir Interactive Shell (Shell)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
Launches the Elixir interactive shell (iex) with the current mix project loaded. This allows developers to interact directly with application modules and functions for debugging or administrative tasks.
```sh
$ iex -S mix
```
--------------------------------
### Generating a New Phoenix Application (sh)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This command initializes a new Phoenix project named 'auth_me'. It sets up the basic directory structure and configuration files required for a Phoenix application, serving as the foundation for integrating Guardian.
```sh
$ mix phx.new auth_me
```
--------------------------------
### Specifying Guardian and Argon2 Dependencies (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir code snippet, typically found in `mix.exs`, defines the project's dependencies. It adds `guardian` for authentication and `argon2_elixir` for password hashing, specifying their recommended versions for the tutorial.
```elixir
## mix.exs
defp deps do
[
{:guardian, "~> 2.3"},
{:argon2_elixir, "~> 2.0"}
]
end
```
--------------------------------
### Migrating Ecto Database (Shell)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
Executes database migrations using Ecto to set up the necessary tables for the application, such as the users table. This command ensures the database schema is up-to-date with the application's models.
```sh
$ mix ecto.migrate
```
--------------------------------
### Creating User in Elixir (IEx)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
Creates a new user programmatically within the Elixir interactive shell using the `AuthMe.UserManager.create_user` function. This is used to set up initial user accounts without a web interface, providing a username and password.
```Elixir
iex(1)> AuthMe.UserManager.create_user(%{username: "me", password: "secret"})
```
--------------------------------
### Generating User Manager Context (sh)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This command uses Phoenix's `phx.gen.context` to create a `UserManager` context and a `User` schema with `username` and `password` fields. This generates the necessary Ecto boilerplate for user management, including migrations and model functions.
```sh
$ mix phx.gen.context UserManager User users username:string password:string
```
--------------------------------
### Creating Session View for Authentication in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module defines the `SessionView` for the authentication process. It serves as a basic view module, inheriting from `AuthMeWeb, :view`, and is used by the `SessionController` to render the associated templates.
```elixir
defmodule AuthMeWeb.SessionView do
use AuthMeWeb, :view
end
```
--------------------------------
### Configuring Guardian Secret Key (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir configuration snippet, typically found in `config.exs`, sets up the Guardian implementation module. It specifies the `issuer` for the JWT tokens and provides a placeholder for the `secret_key`, which must be populated with the value generated by `mix guardian.gen.secret` for secure token handling.
```elixir
## config.exs
config :auth_me, AuthMe.UserManager.Guardian,
issuer: "auth_me",
secret_key: "" # put the result of the mix command above here
```
--------------------------------
### Implementing Page Controller for Protected Resources in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module defines the `PageController` which handles rendering of general and protected web pages. The `protected` action demonstrates how to retrieve the currently authenticated user using `Guardian.Plug.current_resource(conn)` before rendering the protected content, while the `index` action renders a basic page.
```elixir
defmodule AuthMeWeb.PageController do
use AuthMeWeb, :controller
def protected(conn, _) do
user = Guardian.Plug.current_resource(conn)
render(conn, "protected.html", current_user: user)
end
def index(conn, _params) do
render(conn, "index.html")
end
end
```
--------------------------------
### Defining Guardian Implementation Module (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module, `AuthMe.UserManager.Guardian`, serves as Guardian's implementation. It defines how user subjects are encoded into tokens (`subject_for_token`) and how user resources are retrieved from token claims (`resource_from_claims`), establishing the core logic for Guardian to interact with the application's user model.
```elixir
## lib/auth_me/user_manager/guardian.ex
defmodule AuthMe.UserManager.Guardian do
use Guardian, otp_app: :auth_me
alias AuthMe.UserManager
def subject_for_token(user, _claims) do
{:ok, to_string(user.id)}
end
def resource_from_claims(%{"sub" => id}) do
user = UserManager.get_user!(id)
{:ok, user}
rescue
Ecto.NoResultsError -> {:error, :resource_not_found}
end
end
```
--------------------------------
### Basic Guardian Implementation Module Setup in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/introduction/implementation.md
This snippet shows the minimal setup for a Guardian implementation module. It uses `use Guardian` with the OTP application atom and defines the two mandatory callbacks: `subject_for_token` to identify the resource for the token, and `resource_from_claims` to retrieve the resource from the token's claims.
```Elixir
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
```
--------------------------------
### Implementing User Management Functions (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir code provides essential functions for managing `User` records, typically within a Phoenix context. It includes functions for listing, retrieving, creating, updating, and deleting users, along with a `change_user` function for changeset initialization, which are crucial for interacting with the user data store.
```elixir
def list_users do
Repo.all(User)
end
def get_user!(id), do: Repo.get!(User, id)
#The tutorial calls this one:
def create_user(attrs \\ %{}) do
%User{}
|> User.changeset(attrs)
|> Repo.insert()
end
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
|> Repo.update()
end
def delete_user(%User{} = user) do
Repo.delete(user)
end
#The tutorial calls this one:
def change_user(%User{} = user) do
User.changeset(user, %{})
end
```
--------------------------------
### Creating Protected Page Template with EEx
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This EEx template defines the HTML content for a page accessible only to logged-in users. It displays a message confirming access and dynamically shows the username of the currently logged-in user, demonstrating how to render user-specific data on a protected resource.
```eex
Protected Page
You can only see this page if you are logged in
You're logged in as <%= @current_user.username %>
```
--------------------------------
### Designing Login Template with EEx and Phoenix Forms
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This EEx template defines the HTML structure for the user login page. It utilizes Phoenix's `form_for` helper to create a form with input fields for username and password, along with error display tags and a submit button, facilitating user input for authentication.
```eex
Login Page
<%= form_for @changeset, @action, fn f -> %>
<%= label f, :username, class: "control-label" %>
<%= text_input f, :username, class: "form-control" %>
<%= error_tag f, :username %>
<%= label f, :password, class: "control-label" %>
<%= password_input f, :password, class: "form-control" %>
<%= error_tag f, :password %>
<%= submit "Submit", class: "btn btn-primary" %>
<% end %>
```
--------------------------------
### Implementing Session Controller for User Authentication in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module defines the `SessionController` responsible for handling user authentication flows. It includes actions for displaying the login form (`new`), processing login credentials (`login`), signing out users (`logout`), and managing login success or failure replies, leveraging `UserManager` and `Guardian.Plug` for core authentication logic.
```elixir
defmodule AuthMeWeb.SessionController do
use AuthMeWeb, :controller
alias AuthMe.{UserManager, UserManager.User, UserManager.Guardian}
def new(conn, _) do
changeset = UserManager.change_user(%User{})
maybe_user = Guardian.Plug.current_resource(conn)
if maybe_user do
redirect(conn, to: "/protected")
else
render(conn, "new.html", changeset: changeset, action: Routes.session_path(conn, :login))
end
end
def login(conn, %{"user" => %{"username" => username, "password" => password}}) do
UserManager.authenticate_user(username, password)
|> login_reply(conn)
end
def logout(conn, _) do
conn
|> Guardian.Plug.sign_out()
|> redirect(to: "/login")
end
defp login_reply({:ok, user}, conn) do
conn
|> put_flash(:info, "Welcome back!")
|> Guardian.Plug.sign_in(user)
|> redirect(to: "/protected")
end
defp login_reply({:error, reason}, conn) do
conn
|> put_flash(:error, to_string(reason))
|> new(%{})
end
end
```
--------------------------------
### Generating Guardian Secret Key (sh)
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This command uses Guardian's built-in generator to create a secure secret key. This key is essential for signing and verifying JWT tokens, ensuring the integrity and authenticity of the authentication process.
```sh
$ mix guardian.gen.secret
```
--------------------------------
### Encoding Permissions into Guardian Token (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This example illustrates how to pass defined permissions as options when encoding and signing a Guardian token. The permissions are provided as a map to the `permissions` key, which will then be processed by the `build_claims` hook configured in the Guardian module.
```Elixir
MyApp.Guardian.encode_and_sign(resource, %{}, permissions: %{user_actions: [:books, :fitness]})
```
--------------------------------
### Configuring Phoenix Router for Guardian Authentication Pipelines
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir code configures the Phoenix router to define authentication pipelines using Guardian. It sets up an `:auth` pipeline for 'maybe' authenticated routes and an `:ensure_auth` pipeline to enforce authentication, then scopes routes to apply these pipelines, ensuring proper access control for different parts of the application.
```elixir
# Our pipeline implements "maybe" authenticated. We'll use the `:ensure_auth` below for when we need to make sure someone is logged in.
pipeline :auth do
plug AuthMe.UserManager.Pipeline
end
# We use ensure_auth to fail if there is no one logged in
pipeline :ensure_auth do
plug Guardian.Plug.EnsureAuthenticated
end
# Maybe logged in routes
scope "/", AuthMeWeb do
pipe_through [:browser, :auth]
get "/", PageController, :index
get "/login", SessionController, :new
post "/login", SessionController, :login
get "/logout", SessionController, :logout
end
# Definitely logged in scope
scope "/", AuthMeWeb do
pipe_through [:browser, :auth, :ensure_auth]
get "/protected", PageController, :protected
end
```
--------------------------------
### Authenticating User Credentials with Argon2 in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir function `authenticate_user` verifies a user's credentials. It queries the database for a user by `username` and then uses `Argon2.verify_pass` to securely compare the provided `plain_text_password` against the stored hashed password. It returns `{:ok, user}` on successful authentication or `{:error, :invalid_credentials}` otherwise.
```Elixir
alias Argon2
import Ecto.Query, only: [from: 2]
def authenticate_user(username, plain_text_password) do
query = from u in User, where: u.username == ^username
case Repo.one(query) do
nil ->
Argon2.no_user_verify()
{:error, :invalid_credentials}
user ->
if Argon2.verify_pass(plain_text_password, user.password) do
{:ok, user}
else
{:error, :invalid_credentials}
end
end
end
```
--------------------------------
### Defining Guardian Authentication Pipeline in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module defines a Guardian Plug pipeline for handling authentication. It configures the pipeline to use `AuthMe.UserManager.ErrorHandler` for errors and `AuthMe.UserManager.Guardian` as the authentication module. The pipeline verifies tokens from both session and authorization headers, restricting them to "access" type claims, and then loads the associated user resource, allowing for cases where no token is present (`allow_blank: true`).
```Elixir
defmodule AuthMe.UserManager.Pipeline do
use Guardian.Plug.Pipeline,
otp_app: :auth_me,
error_handler: AuthMe.UserManager.ErrorHandler,
module: AuthMe.UserManager.Guardian
# If there is a session token, restrict it to an access token and validate it
plug Guardian.Plug.VerifySession, claims: %{"typ" => "access"}
# If there is an authorization header, restrict it to an access token and validate it
plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}
# Load the user if either of the verifications worked
plug Guardian.Plug.LoadResource, allow_blank: true
end
```
--------------------------------
### Adding Guardian Dependency to mix.exs (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/guides/introduction/installation.md
This snippet demonstrates how to add Guardian as a dependency to an Elixir project's `mix.exs` file. It specifies the `guardian` package with a version constraint of `~> 1.0`, ensuring compatibility and proper installation during dependency fetching.
```Elixir
def deps do
[
# ...
{:guardian, "~> 1.0"}
]
end
```
--------------------------------
### Ensuring Specific Permissions with Guardian Plug (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This example demonstrates how to use the `Guardian.Permissions.Bitwise` Plug to ensure that a token contains a specific set of permissions before allowing the request to proceed. This plug must be used downstream of a Guardian pipeline, typically after token verification.
```Elixir
plug Guardian.Permissions.Bitwise, ensure: %{user_actions: [:books]}
```
--------------------------------
### Testing User Creation and Update with Hashed Passwords in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
These Elixir test cases demonstrate how to verify user creation and updates when passwords are hashed. Instead of comparing plain-text passwords, they use `Argon2.check_pass` to assert that the provided plain-text password correctly matches the hashed password stored in the `User` struct, ensuring the hashing and verification process works as expected.
```Elixir
test "create_user/1 with valid data creates a user" do
assert {:ok, %User{} = user} = UserManager.create_user(@valid_attrs)
assert {:ok, user} == Argon2.check_pass(user, "some password", hash_key: :password)
assert user.username == "some username"
end
...
test "update_user/2 with valid data updates the user" do
user = user_fixture()
assert {:ok, %User{} = user} = UserManager.update_user(user, @update_attrs)
assert {:ok, user} == Argon2.check_pass(user, "some updated password", hash_key: :password)
assert user.username == "some updated username"
end
```
--------------------------------
### Interrogating Guardian Token Permissions (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet provides examples of how to interrogate permissions from a Guardian token's claims. It shows how to decode permissions using `decode_permissions_from_claims`, check if all specified permissions are present with `all_permissions?`, and verify if any of the given permissions exist using `any_permissions?`.
```Elixir
# Get the encoded permissions from the claims
found_perms = MyApp.Guardian.decode_permissions_from_claims(claims)
# Check if all permissions are present
has_all_these_things? =
claims
|> MyApp.Guardian.decode_permissions_from_claims(claims)
|> MyApp.Guardian.all_permissions?(%{user_actions: [:books]})
# Checks if any permissions are present
show_any_media_things? =
claims
|> MyApp.Guardian.decode_permissions_from_claims(claims)
|> MyApp.Guardian.any_permissions?(%{user_actions: [:books, :fitness, :music]})
```
--------------------------------
### Encoding Guardian Token with Bitwise Permissions Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This example shows how to create and sign a Guardian token, passing specific bitwise permissions as an option. The `permissions` keyword argument is used to specify the desired permissions, which are then encoded into the token claims via the `build_claims` hook defined in the Guardian module.
```Elixir
MyApp.Guardian.encode_and_sign(resource, %{}, permissions: %{user_actions: [:books, :fitness]})
```
--------------------------------
### Signing In/Out with Guardian.Plug in 0.14.x (Legacy Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet demonstrates the legacy usage of `sign_in` and `sign_out` functions in Guardian 0.14.x, which were called directly on the `Guardian.Plug` module to manage user sessions within a Plug pipeline.
```Elixir
conn = Guardian.Plug.sign_in(conn, resource, token_type, claims)
conn = Guardian.Plug.sign_out(conn, token, [claims_to_check])
```
--------------------------------
### Configuring Guardian (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet illustrates the configuration approach for Guardian in version 0.14.x, where options were set directly under the `:guardian` application key for the `Guardian` module. This global configuration method is superseded by module-specific configuration in 1.0.
```Elixir
config :guardian, Guardian,
# options
```
--------------------------------
### Configuring Guardian Implementation Module (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet demonstrates the new configuration method for Guardian 1.0, where configuration is now tied to the specific implementation module (e.g., `MyApp.Guardian`) within its OTP application. This allows for more flexible and modular configuration compared to the previous global approach.
```Elixir
config :my_app, MyApp.Guardian,
# options
```
--------------------------------
### Configuring Guardian in 1.0 (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet demonstrates the updated configuration approach for Guardian 1.0, where settings are now applied to the specific implementation module (e.g., `MyApp.Guardian`) rather than the global `Guardian` module. This allows for more flexible and modular configuration.
```Elixir
config :my_app, MyApp.Guardian,
# options
```
--------------------------------
### Adding Guardian KeyServer to Supervision Tree in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This Elixir code demonstrates how to add the `MyApp.Guardian.KeyServer` to the application's supervision tree in `lib/my_app/application.ex`. This ensures the `KeyServer` is started and managed by the supervisor, making it available to serve key requests throughout the application's lifecycle.
```Elixir
## lib/my_app/application.ex
def start(_type, _args) do
# List all child processes to be supervised
children =
[
MyAppWeb.Endpoint,
MyApp.Guardian.KeyServer
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
```
--------------------------------
### Ensuring Bitwise Permissions with Guardian Plug Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This example shows how to use `Guardian.Permissions.Bitwise` plug to ensure that a token contains specific permissions. This plug must be used downstream of a Guardian pipeline and will halt the request if the required permissions are not present in the token's claims.
```Elixir
plug Guardian.Permissions.Bitwise, ensure: %{user_actions: [:books]}
```
--------------------------------
### Pattern Matching for Subject and Resource in Guardian Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/introduction/implementation.md
This advanced example demonstrates how to use pattern matching in `subject_for_token` and `resource_from_claims` to handle different resource types or subject formats. It shows how to prefix subjects (e.g., 'User:UID') for easier identification and retrieval, improving flexibility and maintainability when dealing with various authenticated entities.
```Elixir
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}
```
--------------------------------
### Signing In/Out with Guardian Implementation Plug (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet demonstrates the updated `sign_in` and `sign_out` operations in Guardian 1.0. These functions are now called through the user-defined implementation module's Plug (`MyApp.Guardian.Plug`), accepting claims and options for more flexible session management.
```Elixir
conn = MyApp.Guardian.Plug.sign_in(conn, resource, [claims, opts])
conn = MyApp.Guardian.Plug.sign_out(conn, resource, [claims_to_check, opts])
```
--------------------------------
### Signing In/Out with Guardian.Plug in 1.0 (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
In Guardian 1.0, the `sign_in` and `sign_out` functions within the Plug integration are now called on the `Plug` module of the specific implementation (e.g., `MyApp.Guardian.Plug`). This aligns with the new module-based architecture.
```Elixir
conn = MyApp.Guardian.Plug.sign_in(conn, resource, claims, opts)
conn = MyApp.Guardian.Plug.sign_out(conn, resource, [claims_to_check, opts])
```
--------------------------------
### Implementing Guardian Authentication Error Handler in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir module implements the `Guardian.Plug.ErrorHandler` behaviour to gracefully handle authentication failures within the Guardian pipeline. The `auth_error` function receives the connection, error type, and options, then sets the response content type to "text/plain" and sends a 401 Unauthorized HTTP response with the error type as the body.
```Elixir
defmodule AuthMe.UserManager.ErrorHandler do
import Plug.Conn
@behaviour Guardian.Plug.ErrorHandler
@impl Guardian.Plug.ErrorHandler
def auth_error(conn, {type, _reason}, _opts) do
body = to_string(type)
conn
|> put_resp_content_type("text/plain")
|> send_resp(401, body)
end
end
```
--------------------------------
### Defining the Guardian Implementation Module in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
In Guardian 1.0, a dedicated module must be defined to house all authentication-related logic, replacing the previous global implementation. This module serves as the serializer and provides a place for custom hooks, requiring an `:otp_app` specification.
```Elixir
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
# ...
end
```
--------------------------------
### Generating Guardian Secret Key using Mix in Bash
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This Bash command provides a quick way to generate a secret key suitable for Guardian configuration. The output of this command should be used to set the `secret_key` in your Guardian configuration, typically for development or initial setup.
```Bash
$ mix guardian.gen.secret
```
--------------------------------
### Configuring Guardian to Use Custom SecretFetcher in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This configuration snippet updates the Guardian setup in `config/config.exs` to use the custom `MyApp.Guardian.KeyServer` as its `secret_fetcher`. It also specifies the allowed signing algorithm, `Ed25519`, and the issuer.
```Elixir
## config/config.exs
config :my_app, MyApp.Guardian,
issuer: "myapp",
allowed_algos: ["Ed25519"],
secret_fetcher: MyApp.Guardian.KeyServer
```
--------------------------------
### Encoding and Decoding Tokens in Guardian 0.14.x (Legacy Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet illustrates the legacy API for encoding and decoding tokens in Guardian 0.14.x, where functions like `encode_and_sign` and `decode_and_verify` were called directly on the global `Guardian` module.
```Elixir
Guardian.encode_and_sign(resource, [token_type, claims])
Guardian.decode_and_verify(token, [claims_to_check])
```
--------------------------------
### Configuring Guardian in 0.14.x (Legacy Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet shows the legacy method of configuring Guardian in version 0.14.x, where options were set directly for the global `Guardian` module. This approach is no longer used in Guardian 1.0.
```Elixir
config :guardian, Guardian,
# options
```
--------------------------------
### Hashing User Passwords in Elixir User Model
Source: https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md
This Elixir code defines a `changeset` function for the `User` schema, which handles casting and validating user attributes like `username` and `password`. It includes a private helper function `put_password_hash` that securely hashes the user's plain-text password using `Argon2.hash_pwd_salt` before saving it, ensuring passwords are never stored in plain text.
```Elixir
alias Argon2
def changeset(user, attrs) do
user
|> cast(attrs, [:username, :password])
|> validate_required([:username, :password])
|> put_password_hash()
end
defp put_password_hash(%Ecto.Changeset{valid?: true, changes: %{password: password}} = changeset) do
change(changeset, password: Argon2.hash_pwd_salt(password))
end
defp put_password_hash(changeset), do: changeset
```
--------------------------------
### Defining Guardian Implementation Module (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet shows how to define the new Guardian implementation module in version 1.0. This module serves as the central point for authentication-related items, replacing the single global Guardian implementation from 0.14.x. It uses `use Guardian, otp_app: :my_app` to set up the module within a specific OTP application.
```Elixir
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
# ...
end
```
--------------------------------
### Signing In/Out with Guardian Plug (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet shows how `sign_in` and `sign_out` operations were performed directly using `Guardian.Plug` in version 0.14.x. These functions modified the `conn` (connection) to manage user sessions based on resources, token types, and claims.
```Elixir
conn = Guardian.Plug.sign_in(conn, resource, [token_type, claims])
conn = Guardian.Plug.sign_out(conn, token, [claims_to_check])
```
--------------------------------
### Revoking Tokens with Guardian (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet illustrates how tokens were revoked in Guardian 0.14.x using `Guardian.revoke!`. It took the token, claims, and options, returning `:ok` upon successful revocation.
```Elixir
:ok = Guardian.revoke!(token, claims, opts)
```
--------------------------------
### Specifying Token Types in Guardian 0.14.x (Legacy Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet shows how token types were specified in Guardian 0.14.x by passing the type directly as an argument to `Guardian.encode_and_sign`. This method has been updated in Guardian 1.0.
```Elixir
Guardian.encode_and_sign(resource, "other_type")
```
--------------------------------
### Encoding and Decoding Tokens in Guardian 1.0 (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet demonstrates the updated API for token encoding and decoding in Guardian 1.0. These operations are now performed by calling `encode_and_sign` and `decode_and_verify` on the specific implementation module (e.g., `MyApp.Guardian`), with options passed as a separate argument.
```Elixir
MyApp.Guardian.encode_and_sign(resource, [claims, options])
MyApp.Guardian.decode_and_verify(token, [claims_to_check, options])
```
--------------------------------
### Refreshing Tokens with Guardian (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet shows how tokens were refreshed in Guardian 0.14.x using `Guardian.refresh!`. It took an `old_token`, claims to check, and options, returning a new token and its claims upon successful refresh.
```Elixir
{:ok, new_token, new_claims} = Guardian.refresh!(old_token, claims_to_check, options)
```
--------------------------------
### Encoding and Decoding Tokens with Guardian Implementation (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet demonstrates the updated approach for encoding and decoding tokens in Guardian 1.0. Instead of direct `Guardian` module calls, operations are now performed via the user-defined implementation module (e.g., `MyApp.Guardian`), accepting claims and options for greater flexibility.
```Elixir
MyApp.Guardian.encode_and_sign(resource, [claims, options])
MyApp.Guardian.decode_and_verify(token, [claims_to_check, options])
```
--------------------------------
### Defining a Secret Key Fetcher Module for Guardian in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This Elixir module, `MySecretKey`, defines a `fetch` function responsible for retrieving a secret key from an external source, specifically Redix. It illustrates how to establish a connection, fetch a key, convert it to a JOSE.JWK format, and then close the connection. While functional, the snippet explicitly notes that starting and stopping a connection per fetch is bad practice and suggests using an established connection or caching.
```Elixir
defmodule MySecretKey do
def fetch do
# Bad practice for example purposes only.
# An already established connection should be used and possibly cache the value locally.
{:ok, conn} = Redix.start_link
rsa_jwk = conn
|> Redix.command!(["GET my-rsa-key"])
|> JOSE.JWK.from_binary
Redix.stop(conn)
rsa_jwk
end
end
```
--------------------------------
### Configuring Guardian with a JOSE.JWK File-Based Secret Key Fetcher in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This configuration snippet demonstrates how Guardian can be set up to retrieve its secret key from a file using a module and function. Similar to the Redix example, the `secret_key` is a tuple `{MySecretKey, :fetch, []}`, which calls `MySecretKey.fetch/0` to load the key from an encrypted JSON file, allowing for flexible and secure key management.
```Elixir
config :my_app, MyApp.Guardian,
allowed_algos: ["Ed25519"],
secret_key: {MySecretKey, :fetch, []}
```
--------------------------------
### Adding Custom Claims to Guardian Tokens in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/introduction/implementation.md
This example illustrates how to include custom data (claims) when encoding a token using `MyApp.TokenImpl.encode_and_sign`. Custom claims are merged with default claims and those from the `Guardian.build_claims` callback, allowing for flexible data storage within the token.
```Elixir
{:ok, token, full_claims} = MyApp.TokenImpl.encode_and_sign(user, %{some: "data to store"})
```
--------------------------------
### Setting Token TTL in Guardian 0.14.x (Legacy Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet illustrates how Time-To-Live (TTL) for tokens was configured in Guardian 0.14.x by including a `ttl` key directly within the claims map passed to `Guardian.encode_and_sign`.
```Elixir
Guardian.encode_and_sign(resource, %{ttl: {1, :hour}})
```
--------------------------------
### Encoding and Decoding Tokens with Guardian (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet illustrates how tokens were encoded and decoded directly using the `Guardian` module in version 0.14.x. `encode_and_sign` and `decode_and_verify` were the primary functions for token creation and validation, accepting resource, token type, and claims.
```Elixir
Guardian.encode_and_sign(resource, [token_type, claims])
Guardian.decode_and_verify(token, [claims_to_check])
```
--------------------------------
### Exchanging Tokens with Guardian Implementation (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet demonstrates the updated `exchange` function in Guardian 1.0. The call is now made through the implementation module (`MyApp.Guardian.exchange`), and it returns a tuple containing both old and new token/claims pairs, providing more comprehensive output.
```Elixir
{:ok, {old_token, old_claims}, {new_token, new_claims}} =
MyApp.Guardian.exchange(old_token, ["refresh"], "access")
```
--------------------------------
### Defining Guardian Authentication Pipeline in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This Elixir module defines a Guardian Plug pipeline for authentication. It specifies the Guardian module, an error handler, and a sequence of plugs to verify session/header tokens, ensure authentication, and load the associated resource. It's designed to be used in a Phoenix router.
```Elixir
defmodule MyApp.Guardian.AuthPipeline do
@claims %{typ: "access"}
use Guardian.Plug.Pipeline, otp_app: :my_app,
module: MyApp.Guardian,
error_handler: MyApp.Guardian.AuthErrorHandler
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: false
end
```
--------------------------------
### Configuring a Custom Guardian Plug Pipeline in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This Elixir configuration snippet associates the custom MyApp.AuthAccessPipeline with a specific Guardian implementation module (MyApp.Guardian) and an error handler (MyApp.AuthErrorHandler) within the :my_app OTP application. This setup ensures the pipeline uses the correct backend logic and error handling.
```Elixir
config :my_app, MyApp.AuthAccessPipeline,
module: MyApp.Guardian,
error_handler: MyApp.AuthErrorHandler
```
--------------------------------
### Specifying Token Type with Guardian Implementation (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet demonstrates how to specify a token type in Guardian 1.0. The `token_type` is now passed within an options map to the `MyApp.Guardian.encode_and_sign` function, providing a more structured way to handle token-specific configurations.
```Elixir
MyApp.Guardian.encode_and_sign(resource, %{}, token_type: "other_type")
```
--------------------------------
### Implementing Serializer Functions in Guardian 1.0 (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
In Guardian 1.0, the serializer functions `from_token` and `for_token` have been renamed to `subject_for_token` and `resource_from_claims`, respectively, and are now part of the implementation module. These functions handle the conversion between resources and token subjects, receiving more comprehensive arguments.
```Elixir
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
def subject_for_token(resource, _claims) do
{:ok, to_string(resource.id)}
end
def subject_for_token(_, _) do
{:error, :reason_for_error}
end
def resource_from_claims(claims) do
{:ok, find_me_a_resource(claims["sub"])}
end
def resource_from_claims(_claims) do
{:error, :reason_for_error}
end
end
```
--------------------------------
### Defining a Guardian Authentication Pipeline in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This Elixir module defines a Guardian Plug pipeline for authentication. It configures the Guardian module and error handler, then chains several plugs to verify tokens from sessions or headers, ensure authentication, and load the associated resource. The @claims variable specifies that only "access" type tokens are considered.
```Elixir
defmodule MyApp.Guardian.AuthPipeline do
@claims %{typ: "access"}
use Guardian.Plug.Pipeline, otp_app: :my_app,
module: MyApp.Guardian,
error_handler: MyApp.Guardian.AuthErrorHandler
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.VerifyHeader, claims: @claims, realm: "Bearer"
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, ensure: true
end
```
--------------------------------
### Setting Token TTL with Guardian (0.14.x)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet illustrates how the Time-To-Live (TTL) for a token was set in Guardian 0.14.x by including a `ttl` key directly in the claims map passed to `Guardian.encode_and_sign`. This approach has been revised in 1.0 to use a dedicated option.
```Elixir
Guardian.encode_and_sign(resource, %{ttl: {1, :hour}})
```
--------------------------------
### Allowing One of Multiple Permission Sets with Guardian Plug (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet illustrates the `one_of` feature of the `Guardian.Permissions.Bitwise` Plug. It allows the request to continue if the token contains any of the specified permission configurations, providing flexibility for access control where multiple permission sets grant access.
```Elixir
plug Guardian.Permissions.Bitwise, one_of: [
%{default: [:public_profile], user_actions: [:books]},
%{default: [:public_profile], user_actions: [:music]}
]
```
--------------------------------
### Encoding and Signing Tokens with Custom Options - Guardian - Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This section demonstrates how to encode and sign JWT tokens using `MyApp.Guardian.encode_and_sign` with various custom options. Examples include adding custom claims, specifying a token type, setting a custom time-to-live (TTL), customizing the secret key, and requiring an `auth_time` claim.
```Elixir
# Add custom claims to a token
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{some: "claim"})
# Create a specific token type (i.e. "access"/"refresh" etc)
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{}, token_type: "refresh")
# Customize the time to live (ttl) of the token
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{}, ttl: {1, :minute})
# Customize the secret
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{}, secret: "custom")
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{}, secret: {SomeMod, :some_func, ["some", "args"]})
# Require an "auth_time" claim to be added.
{:ok, token, claims} = MyApp.Guardian.encode_and_sign(resource, %{}, auth_time: true)
```
--------------------------------
### Implementing Guardian Serializer Functions (1.0)
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet shows the new `subject_for_token` and `resource_from_claims` functions required in the Guardian 1.0 implementation module. These functions replace `from_token` and `for_token` from 0.14.x, providing clearer naming and more complete arguments for handling resource serialization and deserialization based on token claims.
```Elixir
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
def subject_for_token(resource, _claims) do
{:ok, to_string(resource.id)}
end
def subject_for_for_token(_, _) do
{:error, :reason_for_error}
end
def resource_from_claims(claims) do
{:ok, find_me_a_resource(claims["sub"])}
end
def resource_from_claims(_claims) do
{:error, :reason_for_error}
end
end
```
--------------------------------
### Decoding and Verifying Tokens - Guardian - Elixir
Source: https://github.com/ueberauth/guardian/blob/master/README.md
This section illustrates how to decode and verify JWT tokens using `MyApp.Guardian.decode_and_verify`. Examples include verifying specific literal claims (e.g., token type), using a custom secret for verification, and enforcing a maximum age based on the `auth_time` claim.
```Elixir
# Check some literal claims. (i.e. this is an access token)
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{"typ" => "access"})
# Use a custom secret
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{}, secret: "custom")
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{}, secret: {SomeMod, :some_func, ["some", "args"]})
# Specify a maximum age (since end user authentication time). If the token has an
# `auth_time` claim and it is older than the `max_age` allows, the token will be invalid.
{:ok, claims} = MyApp.Guardian.decode_and_verify(token, %{}, max_age: {2, :hours})
```
--------------------------------
### Guardian Phoenix Socket Integration (0.14.x) in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This Elixir code shows the integration of Guardian with Phoenix Sockets in version 0.14.x. It uses `use Guardian.Phoenix.Socket` to automatically handle authentication and provides an `id` function to identify the socket based on the current resource.
```Elixir
defmodule MyApp.UserSocket do
use Phoenix.Socket
use Guardian.Phoenix.Socket
## Channels
channel "user:*", MyApp.UserChannel
## Transports
transport :websocket, Phoenix.Transports.WebSocket
# transport :longpoll, Phoenix.Transports.LongPoll
def connect(_params, _socket) do
:error
end
def id(socket), do: "users_socket:#{current_resource(socket).id}"
end
```
--------------------------------
### Decoding and Checking Bitwise Permissions Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This snippet illustrates how to retrieve and check bitwise permissions from Guardian token claims. It demonstrates decoding permissions, checking if all specified permissions are present (`all_permissions?`), and checking if any of the specified permissions are present (`any_permissions?`). These functions operate on the decoded claims.
```Elixir
# Get the encoded permissions from the claims
found_perms = MyApp.Guardian.decode_permissions_from_claims(claims)
# Check if all permissions are present
has_all_these_things? =
claims
|> MyApp.Guardian.decode_permissions_from_claims(claims)
|> MyApp.Guardian.all_permissions?(%{user_actions: [:books]})
# Checks if any permissions are present
show_any_media_things? =
claims
|> MyApp.Guardian.decode_permissions_from_claims(claims)
|> MyApp.Guardian.any_permissions?(%{user_actions: [:books, :fitness, :music]})
```
--------------------------------
### Configuring Bitwise Permissions in Guardian Module (Elixir)
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This snippet demonstrates how to configure bitwise permissions within your Guardian implementation module. It shows defining permissions as a map with bit locations and utilizing the `build_claims` hook to encode these permissions into the token claims using `encode_permissions_into_claims!`, based on options passed during token creation.
```Elixir
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app,
permissions: %{
user_actions: %{
books: 0b1,
fitness: 0b100,
music: 0b1000,
}
}
use Guardian.Permissions.Bitwise
# snip
def build_claims(claims, _resource, opts) do
claims =
claims
|> encode_permissions_into_claims!(Keyword.get(opts, :permissions))
{:ok, claims}
end
end
end
```
--------------------------------
### Guardian Phoenix Socket Integration (1.0) in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/guides/upgrading/v1.0.md
This Elixir code demonstrates the updated Guardian 1.0 integration with Phoenix Sockets. Instead of a `use` macro, it explicitly calls `Guardian.Phoenix.Socket.authenticate` in the `connect` function to handle token verification and set the token, claims, and resource on the socket. The `id` function also uses the new `Guardian.Phoenix.Socket.current_resource` helper.
```Elixir
defmodule MyApp.UserSocket do
use Phoenix.Socket
## Channels
channel "user:*", MyApp.UserChannel
## Transports
transport :websocket, Phoenix.Transports.WebSocket
# transport :longpoll, Phoenix.Transports.LongPoll
def connect(%{"guardian_token" => token}, socket) do
case Guardian.Phoenix.Socket.authenticate(socket, MyApp.Guardian, token) do
{:ok, authed_socket} ->
{:ok, authed_socket}
{:error, _} ->
:error
end
end
def connect(_params, _socket) do
:error
end
def id(socket), do: "users_socket:#{Guardian.Phoenix.Socket.current_resource(socket).id}"
end
```
--------------------------------
### Configuring Phoenix User Socket with Guardian (0.14.x) in Elixir
Source: https://github.com/ueberauth/guardian/blob/master/upgrade_guides/0.14.to.1.0.md
This Elixir module shows the configuration of a Phoenix User Socket using Guardian 0.14.x. It includes `use Guardian.Phoenix.Socket` for Guardian integration, defines channels and transports, and provides a `connect` function that always returns `:error` and an `id` function to identify the socket based on the current resource.
```Elixir
defmodule MyApp.UserSocket do
use Phoenix.Socket
use Guardian.Phoenix.Socket
## Channels
channel "user:*", MyApp.UserChannel
## Transports
transport :websocket, Phoenix.Transports.WebSocket
# transport :longpoll, Phoenix.Transports.LongPoll
def connect(_params, _socket) do
:error
end
def id(socket), do: "users_socket:#{current_resource(socket).id}"
end
```