ProductPromotion
Logo

Elixir

made by https://0x3d.site

GitHub - ueberauth/guardian_db: Guardian DB integration for tracking tokens and ensuring logout cannot be replayed.
Guardian DB integration for tracking tokens and ensuring logout cannot be replayed. - ueberauth/guardian_db
Visit Site

GitHub - ueberauth/guardian_db: Guardian DB integration for tracking tokens and ensuring logout cannot be replayed.

GitHub - ueberauth/guardian_db: Guardian DB integration for tracking tokens and ensuring logout cannot be replayed.

Guardian.DB

Hex.pm Build Status Codecov Inline docs

Guardian.DB is an extension to Guardian that tracks tokens in your application's database to prevent playback.

Installation

Guardian.DB assumes that you are using the Guardian framework for authentication.

To install Guardian.DB, first add it to your mix.exs file:

defp deps do
  [
    {:guardian_db, "~> 2.0"}
  ]
end

Then run mix deps.get on your terminal.

Configure your application as seen in the Configuration section below prior to attempting to generate the migration or you will get an application was not loaded/started error.

Following configuration add the Guardian migration:

run mix guardian.db.gen.migration to generate a migration.

Do not run the migration yet, we need to complete our setup first.

Configuration

config :guardian, Guardian.DB,
  repo: MyApp.Repo, # Add your repository module
  schema_name: "guardian_tokens", # default
  token_types: ["refresh_token"], # store all token types if not set

To sweep expired tokens from your db you should add Guardian.DB.Sweeper to your supervision tree.

children = [
  {Guardian.DB.Sweeper, [interval: 60 * 60 * 1000]} # 1 hour
]

Guardian.DB works by hooking into the lifecycle of your Guardian module.

You'll need to add it to:

  • after_encode_and_sign
  • on_verify
  • on_refresh
  • on_revoke

For example:

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

  # snip...

  def after_encode_and_sign(resource, claims, token, _options) do
    with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
      {:ok, token}
    end
  end

  def on_verify(claims, token, _options) do
    with {:ok, _} <- Guardian.DB.on_verify(claims, token) do
      {:ok, claims}
    end
  end

  def on_refresh({old_token, old_claims}, {new_token, new_claims}, _options) do
    with {:ok, _, _} <- Guardian.DB.on_refresh({old_token, old_claims}, {new_token, new_claims}) do
      {:ok, {old_token, old_claims}, {new_token, new_claims}}
    end
  end

  def on_revoke(claims, token, _options) do
    with {:ok, _} <- Guardian.DB.on_revoke(claims, token) do
      {:ok, claims}
    end
  end
end

Now run the migration and you'll be good to go.

Custom schema name

Guardian.DB allows custom schema name in migrations, based on following configuration:

config :guardian, Guardian.DB,
  schema_name: "my_custom_schema"

And when you run the migration, it'll generate the following migration:

  create table(:my_custom_schema, primary_key: false) do
    add(:jti, :string, primary_key: true)
    add(:typ, :string)
    add(:aud, :string)
    add(:iss, :string)
    add(:sub, :string)
    add(:exp, :bigint)
    add(:jwt, :text)
    add(:claims, :map)
    timestamps()
  end

Then, run the migration and you'll be good to go.

Considerations

Guardian is already a very robust JWT solution. However, if your application needs the ability to immediately revoke and invalidate tokens that have already been generated, you need something like Guardian.DB to build upon Guardian.

In Guardian, you as a systems administrator have no way of revoking tokens that have already been generated, you can call Guardian.revoke, but in Guardian that function does not actually do anything - it just provides hooks for other libraries, such as this one, to define more specific behavior. Discarding the token after something like a log out action is left up to the client application. If the client application does not discard the token, or does not log out, or the token gets stolen by a malicious script (because the client application stores it in localStorage, for instance), the only thing you can do is wait until the token expires. Depending on the scenario, this may not be acceptable.

With Guardian.DB, records of all generated tokens are kept in your application's database. During each request, the Guardian.Plug.VerifyHeader and Guardian.Plug.VerifySession plugs check the database to make sure the token is there. If it is not, the server returns a 401 Unauthorized response to the client. Furthermore, Guardian.revoke! behavior becomes enhanced, as it actually removes the token from the database. This means that if the user logs out, or you revoke their token (e.g. after noticing suspicious activity on the account), they will need to re-authenticate.

Disadvantages

In Guardian, token verification is very light-weight. The only thing Guardian does is decode incoming tokens and make sure they are valid. This can make it much easier to horizontally scale your application, since there is no need to centrally store sessions and make them available to load balancers or other servers.

With Guardian.DB, every request requires a trip to the database, as Guardian now needs to ensure that a record of the token exists. In large scale applications this can be fairly costly, and can arguably eliminate the main advantage of using a JWT authentication solution, which is statelessness. Furthermore, session authentication already works this way, and in most cases there isn't a good enough reason to reinvent that wheel using JWTs.

In other words, once you have reached a point where you think you need Guardian.DB, it may be time to take a step back and reconsider your whole approach to authentication!

Create your own Repo

We created Guardian.DB.Adapter behaviour to allow creating other repositories for persisting JWT tokens. You need to implement the Guardian.DB.Adapter behavior working with your preferred storage.

Adapters

  1. Redis adapter - guardian_redis

Feel free to create your adapters using Guardian.DB.Adapter behavior and you are welcome to add them here.

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory