### 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 ```