Demo web app with Plug, Bandit, Joken and Htmx, with JWT authentication of protected routes (no Phoenix).
-
Authentication using
Json Web Tokenestablished in acookiewhose duration we have set to 60s (the same as the expiration time of theJWT) only for educational purposes, although it can be modified to more realistic values. We used theJokenlibrary to generate and sign the token, as well as to validate it, as it allows for easy configuration and use. -
Two
middlewares(orplugs, in Elixir terminology) have been created. One of them (lib/elixir_jwt_auth_protected_route/web/user/auth.ex) handles accessibility to the protected page of the application, verifying the access token (if any) and setting the current user, if applicable, in theassignsfield of the%Plug.Conn{}structure, which represents the connection that travels through the plug pipeline through which the servers are implemented in the Elixir world. The otherplugormiddleware(lib/elixir_jwt_auth_protected_route/web/user/message.ex) intercepts the connection to check if the authentication route controller has set a temporary cookie with the message to be displayed (the cookie contains abase64encoded map with the message itself and its type). If applicable, it inserts the message and its type in theassignsfield and passes theConnstructure to the route expected by the controller. -
Storage is obtained through a lightweight database, for greater convenience in a demo application, such as
SQLite3managed by theEctolibrary. -
The minimalist yet interactive UI is achieved through the JS library
Htmx(and minimal use ofHyperscriptfor automatic Flash message removal). The use ofHtmxis very useful with the template engines of backend languages, as it allows for the creation of lightweight yet fully interactive web applications without having to resort to frameworks as good as, but "heavyweight" as,Phoenix. (See the considerations I make here on this subject.)
-
Prerequisites: Obviously, you'll need to install
ElixirandErlang/OTP(because you'll need to use its virtual machine). I recommend doing this throughasdf. This will allow you to have multiple versions of Elixir installed and easily switch between them per project or set a global version for the system. Likewise,asdfwill also allow you to installNodeJS(and, similarly, manage its different versions), which is required to install theTailwind CSSanddaisyUIJavaScript packages.I advise you to follow the recommendations made here to create a more complete Erlang/OTP installation that will give you more options when developing with Elixir/Erlang.
-
Usage: Clone the repository and run the following command in a terminal at the project root. This command installs the JS dependencies, generates the CSS in the
priv/static/assets/css/directory, installs the Elixir dependencies, creates theSqlite3database, and runs the migrations on that database:$ mix setupYou can now start the
Banditserver with:$ mix run --no-haltOr if you want, use the Elixir shell (IEx):
$ iex -S mixNow, if you visit the address
http://localhost:4000in your browser you will be redirected tohttp://localhost:4000/auth/registerautomatically and use the application.Alternatively, you can pass an environment variable to either of the above 2 commands that specifies a different listening port:
$ PORT=5000 mix run --no-haltFinally, you can compile the application for production as an
Elixir release, which will include everything the application needs to run in a single folder: theruntime, theBEAM VM, the resulting binaries, and even theassets. Before doing so, however, you'll need to modify the application's configuration to adapt it to your specific requirements. You can find the documentation on this here and here.Note: I've added the
ExSynclibrary (dev mode only) that enableshot reloadingwhen you make code changes in your editor and save it. While editing, you'll need to have two terminals open, one runningnpm run watch-cssto monitor changes to CSS in your.html.eextemplate files withTailwind CSS, and the other running Elixir'sBanditserver (mix run --no-halt). Of course, you'll need to reload your browser to see these changes in the UI.
- Official website: https://elixir-lang.org/
- Elixir Docs: https://hexdocs.pm/elixir/introduction.html
- Elixir School: https://elixirschool.com/
- Elixir Forum: https://elixirforum.com/
- Ecto: https://hexdocs.pm/ecto/3.13.3/getting-started.html
- Ecto SQL: https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.html
- Ecto (Phoenix Guide): https://hexdocs.pm/phoenix/ecto.html
- Plug: https://hexdocs.pm/plug/readme.html
- Bandit: https://hexdocs.pm/bandit/Bandit.html
- Joken: https://hexdocs.pm/joken/readme.html
- JWT Auth in Elixir with Joken: https://elixirschool.com/blog/jwt-auth-with-joken
- Authentication Middleware in Elixir: https://yuriktech.com/2019/07/03/Authentication-Middleware-In-Elixir/
- Htmx: https://htmx.org/
- Hyperscript: https://hyperscript.org/