{"id":15462823,"url":"https://github.com/dwyl/auth_plug","last_synced_at":"2025-04-06T14:12:18.913Z","repository":{"id":36965378,"uuid":"47450969","full_name":"dwyl/auth_plug","owner":"dwyl","description":"🟢 auth_plug lets you seamlessly add authentication to your Phoenix App with ONE Environment Variable™  in less than 2 minutes! 🚀","archived":false,"fork":false,"pushed_at":"2025-03-10T18:47:13.000Z","size":415,"stargazers_count":33,"open_issues_count":3,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-30T10:35:03.051Z","etag":null,"topics":["auth0","authentication","elixir","jwt","phoenix","phoenix-framework"],"latest_commit_sha":null,"homepage":"https://auth-plug.fly.dev/","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dwyl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-12-05T10:01:50.000Z","updated_at":"2025-03-10T18:47:15.000Z","dependencies_parsed_at":"2023-10-03T16:53:01.228Z","dependency_job_id":"a5c01c6b-df07-45e7-800f-ecdf8baa08ef","html_url":"https://github.com/dwyl/auth_plug","commit_stats":{"total_commits":334,"total_committers":10,"mean_commits":33.4,"dds":0.6077844311377245,"last_synced_commit":"7cd5238f2fdb34d83fbaa81f4ea557d21a5337ed"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Fauth_plug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Fauth_plug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Fauth_plug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Fauth_plug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dwyl","download_url":"https://codeload.github.com/dwyl/auth_plug/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247492557,"owners_count":20947545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth0","authentication","elixir","jwt","phoenix","phoenix-framework"],"created_at":"2024-10-02T00:05:06.963Z","updated_at":"2025-04-06T14:12:18.888Z","avatar_url":"https://github.com/dwyl.png","language":"Elixir","readme":"\u003cdiv align=\"center\"\u003e\n\n# `auth_plug`\n\nThe Elixir Plug that _seamlessly_ handles\nall your authentication/authorization needs.\n\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/dwyl/auth_plug/ci.yml?label=build\u0026style=flat-square\u0026branch=main)\n[![codecov.io](https://img.shields.io/codecov/c/github/dwyl/auth_plug/master.svg?style=flat-square)](http://codecov.io/github/dwyl/auth_plug?branch=main)\n[![Hex.pm](https://img.shields.io/hexpm/v/auth_plug?color=brightgreen\u0026style=flat-square)](https://hex.pm/packages/auth_plug)\n[![HitCount](http://hits.dwyl.com/dwyl/auth_plug.svg)](http://hits.dwyl.com/dwyl/auth_plug)\n[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat-square)](https://github.com/dwyl/auth_plug/issues)\n\n\u003c!--\n[![Libraries.io dependency status](https://img.shields.io/librariesio/release/hex/auth_plug?logoColor=brightgreen\u0026style=flat-square)](https://libraries.io/hex/auth_plug)\n--\u003e\n\u003c/div\u003e\n\u003cbr /\u003e\n\n- [`auth_plug`](#auth_plug)\n  - [Why? 🤷](#why-)\n  - [What? 🔐](#what-)\n  - [Who? 👥](#who-)\n- [How? 💡](#how-)\n  - [1. Installation 📝](#1-installation-)\n  - [2. Get Your `AUTH_API_KEY` 🔑](#2-get-your-auth_api_key-)\n    - [2.1 Save it as an Environment Variable](#21-save-it-as-an-environment-variable)\n  - [3. Add `AuthPlug` to Your `router.ex` file to Protect a Route 🔒](#3-add-authplug-to-your-routerex-file-to-protect-a-route-)\n      - [_Explanation_](#explanation)\n  - [4. Attempt to view the protected route to test the authentication! 👩‍💻](#4-attempt-to-view-the-protected-route-to-test-the-authentication-)\n  - [That's it!! 🎉](#thats-it-)\n  - [_Optional_ Auth](#optional-auth)\n  - [Using with `LiveView`](#using-with-liveview)\n  - [Using with an `API`](#using-with-an-api)\n- [Documentation](#documentation)\n- [Development](#development)\n  - [Clone](#clone)\n  - [Available information](#available-information)\n- [Testing / CI](#testing--ci)\n- [Recommended / Relevant Reading](#recommended--relevant-reading)\n\n\n## Why? 🤷\n\n\u003c!--\nYou want a way to add authentication\nto your Elixir/Phoenix App\nin the fewest steps and least code.\nWe did too. So we built `auth_plug`.\n--\u003e\n\n**_Frustrated_** by the **complexity**\nand **incomplete docs/tests**\nin **_existing_ auth solutions**,\nwe built **`auth_plug`** to **simplify** our lives. \u003cbr /\u003e\n\nWe needed a way to **_minimise_**\nthe steps\nand **code** required\nto add auth to our app(s).\nWith **`auth_plug`** we can **setup**\nauth in any Elixir/Phoenix\nApp in **_less_ than 2 minutes**\nwith only **5 lines** of config/code\nand **_one_ environment variable**.\n\n![true](https://user-images.githubusercontent.com/194400/80473192-b1f73500-893d-11ea-87c1-edf4fec53da2.jpg)\n\n\u003c!-- revisit or remove this section\n### Pain 😧\n\nWe try to maintain a\n[\"beginner's mind\"](https://en.wikipedia.org/wiki/Shoshin)\nin everything we do.\n\nThere are virtually infinite options\nfor 3rd party Authentication.\nMost are complex and unfriendly to beginners.\nThey require understanding the difference\nbetween an authentication scheme, strategy or implementation.\nWe have used everything from\n[black box](https://en.wikipedia.org/wiki/Black_box)\n(closed source)\nservices that promise the world but are consistently\npainful to setup, to open source projects that\nare woefully undocumented and lack automated tests\nso we cannot _rely_ on them.\nWe got tired of compromising on the UX of auth,\nso we built _exactly_ what we wanted\nas the \"users\" of our own product.\n\n--\u003e\n\n## What? 🔐\n\nAn Elixir Plug (_HTTP Middleware_)\nthat a _complete_ beginner can use to add auth to a\nPhoenix App\nand _understand_ how it works. \u003cbr /\u003e\nNo macros/behaviours to `use` (_confuse_).\nNo complex configuration or \"implementation\".\nJust a basic plug that uses Phoenix Sessions\nand standards-based JSON Web Tokens (JWT).\nRefreshingly simple. The way auth _should_ be done.\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.com/\"\u003e\n    \u003cimg src=\"https://user-images.githubusercontent.com/194400/80484054-0060ff80-894f-11ea-80fc-537c1a9779a6.png\" alt=\"auth_plug diagram\" width=\"800\"\u003e\n  \u003c/a\u003e\n\nEdit this diagram:\n[docs.google.com/presentation/d/1PUKzbRQOEgHaOmaEheU7T3AHQhRT8mhGuqVKotEJkM0](https://docs.google.com/presentation/d/1PUKzbRQOEgHaOmaEheU7T3AHQhRT8mhGuqVKotEJkM0/edit#slide=id.g841dc8bc44_0_5)\n\n\u003c/div\u003e\n\n**`auth_plug`** protects any routes in your app\nthat require authentication. \u003cbr /\u003e\n\n**`auth_plug`** is just\n[57 lines](https://codecov.io/gh/dwyl/auth_plug/tree/master/lib)\nof (_significant_)\n[code](https://github.com/dwyl/auth_plug/tree/master/lib);\nthe rest is comprehensive comments\nto help _everyone understand_ how it works.\nAs with _all_ our code,\nit's meant to be as beginner-friendly as possible.\nIf you get stuck or have any questions,\nplease [**_ask_**!](https://github.com/dwyl/auth_plug/issues)\n\n## Who? 👥\n\nWe built this plug for use in _our_ products/services.\nIt does _exactly_ what we want it to and nothing more.\nIt's tested, documented and open source the way _all_ our code is.\nIt's **not _yet_** a **general purpose** auth solution\nthat _anyone_ can use.\nIf after reading through this you feel that\nthis is something you would like to have\nin your own Elixir/Phoenix project,\n[**_tell us_**!](https://github.com/dwyl/auth_plug/issues)\n\n# How? 💡\n\n_Before_ you attempt to use the **`auth_plug`**,\ntry the Heroku example version so you know what to expect: \u003cbr /\u003e\nhttps://auth-plug-example.herokuapp.com/admin\n\n![auth_plug_example](https://user-images.githubusercontent.com/194400/80765920-154eb600-8b3c-11ea-90d4-a64224d31a5b.png)\n\nNotice how when you first visit the\n[`auth-plug-example.herokuapp.com/admin`](https://auth-plug-example.herokuapp.com/admin)\npage, your browser is _redirected_ to:\nhttps://dwylauth.herokuapp.com/?referer=https://auth-plug-example.herokuapp.com/admin\u0026auth_client_id=etc.\nThe auth service handles the actual authentication\nand then transparently redirects back to\n[`auth-plug-example.herokuapp.com/admin?jwt=etc.`](https://auth-plug-example.herokuapp.com/admin)\nwith a JWT session.\n\nFor more detail on how the `Auth` service works,\nplease see: https://github.com/dwyl/auth\n\nIf you get stuck during setup,\nclone and run our fully working example:\nhttps://github.com/dwyl/auth_plug_example#how\n\n\u003cbr /\u003e\n\n## 1. Installation 📝\n\nAdd **`auth_plug`**\nto your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:auth_plug, \"~\u003e 1.5\"}\n  ]\nend\n```\n\nOnce you've saved the `mix.exs` file,\ndownload the dependency with:\n\n```sh\nmix deps.get\n```\n\n\u003cbr /\u003e\n\n## 2. Get Your `AUTH_API_KEY` 🔑\n\nVisit: \n[https://authdemo.fly.dev/](https://authdemo.fly.dev/apps/new)\nand create a **New App**.\nOnce you have an App,\nyou can export an `AUTH_API_KEY` environment variable.\ne.g:\n\n![dwyl-auth-app-api-key-setup](https://user-images.githubusercontent.com/194400/93143513-0712c800-f6e0-11ea-9020-c253805d66df.gif)\n\n### 2.1 Save it as an Environment Variable\n\nCreate a file called `.env` in the root directory of your app\nand add the following line:\n\n```txt\nexport AUTH_API_KEY=2cfxNaWUwJBq1F4nPndoEHZJ5Y/2cfxNadrhMZk3iaT1L5k6Wt67c9ScbGNP/dwylauth.herokuapp.com\n```\n\nThe run the following command in your terminal:\n\n```\nsource .env\n```\n\nThat will export the environment variable AUTH_API_KEY.\n\nRemember to add `.env` to your [`.gitignore`](https://github.com/dwyl/auth_plug/blob/1ebb60938487da7e740a79b2a4639b29f2ba44ac/.gitignore#L52) file.\ne.g:\n\n```\necho \".env\" \u003e\u003e .gitignore\n```\n\n\u003cbr /\u003e\n\n## 3. Add `AuthPlug` to Your `router.ex` file to Protect a Route 🔒\n\nOpen the `lib/app_web/router.ex` file and locate the section:\n\n```elixir\n  scope \"/\", AppWeb do\n    pipe_through :browser\n\n    get \"/\", PageController, :index\n  end\n```\n\nImmediately below this add the following lines of code:\n\n```elixir\n  pipeline :auth, do: plug(AuthPlug)\n\n  scope \"/\", AppWeb do\n    pipe_through :browser\n    pipe_through :auth\n    get \"/admin\", PageController, :admin\n  end\n```\n\n\u003e E.g:\n\u003e [`/lib/app_web/router.ex#L23-L29`](https://github.com/dwyl/auth_plug_example/blob/8ce0f10e656b94a93b8f02af240b3897ce23c006/lib/app_web/router.ex#L23-L29)\n\n#### _Explanation_\n\nThere are two parts to this code:\n\n1. Create a new pipeline called `:auth` which will execute the `AuthPlug`.\n2. Create a new scope where we `pipe_through`\n   both the `:browser` and `:auth` pipelines.\n\nThis means that the `\"/admin\"` route is protected by `AuthPlug`.\n\n\u003e **Note**: Ensure the route you are protecting works _without_ `AuthPlug`.\n\u003e If in doubt simply comment out the line `pipe_through :auth` to check.\n\n\u003cbr /\u003e\n\n## 4. Attempt to view the protected route to test the authentication! 👩‍💻\n\nNow that the `/admin` route is protected by **`auth_plug`**,\nattempt to view it in your browser e.g: http://localhost:4000/admin\n\nIf you are not already authenticated,\nyour browser will be redirected to:\nhttps://dwylauth.herokuapp.com/?referer=http://localhost:4000/admin\u0026auth_client_id=etc\n\nOnce you have successfully authenticated with your GitHub or Google account,\nyou will be redirected back to `localhost:4000/admin`\nwhere the `/admin` route will be visible.\n\n![admin-route](https://user-images.githubusercontent.com/194400/80760439-d23b1580-8b30-11ea-8941-160ece8a4a5f.png)\n\n\u003cbr /\u003e\n\n## That's it!! 🎉\n\nYou just setup auth in a Phoenix app using **`auth_plug`**!\n\nIf you got stuck or have any questions,\nplease\n[open an issue](https://github.com/dwyl/auth_plug/issues),\nwe are here to help!\n\n## _Optional_ Auth\n\nThe use case shown above is protecting an endpoint\nthat you don't want people to see if they haven't authenticated.\nIf you're building an app that has routes\nwhere you want to show generic content to people who have _not_ authenticated,\nbut then show more detail/custom actions to people who _have_ authenticated,\nthat's where _Optional_ Auth comes in.\n\nTo use _optional_ auth it's even _easier_ than required auth.\n\nOpen your `lib/app_web/router.ex` file and add the following line\nabove the routes you want show optional data on:\n\n```elixir\npipeline :authoptional, do: plug(AuthPlugOptional, %{})\n```\n\ne.g:\n[`/lib/app_web/router.ex#L13`](https://github.com/dwyl/auth_plug_example/blob/f4c79e540ed8ef2d4c587647b31e93fec9855f59/lib/app_web/router.ex#L13)\n\nThen add the following line to your main router scope:\n\n```elixir\npipe_through :authoptional\n```\n\ne.g:\n[`/lib/app_web/router.ex#L17`](https://github.com/dwyl/auth_plug_example/blob/f4c79e540ed8ef2d4c587647b31e93fec9855f59/lib/app_web/router.ex#L17)\n\nThat's it now you can check for `conn.assigns.person` in your templates\nand display relevant info/actions to the person if they are logged in.\n\n```html\n\u003c%= if Map.has_key?(@conn.assigns, :person) do %\u003e Hello \u003c%=\n@conn.assigns.person.givenName %\u003e! \u003c% end %\u003e\n```\n\ne.g:\n[`/lib/app_web/templates/page/optional.html.eex#L2-L3`](https://github.com/dwyl/auth_plug_example/blob/f4c79e540ed8ef2d4c587647b31e93fec9855f59/lib/app_web/templates/page/optional.html.eex#L2-L3)\n\n\u003cbr /\u003e\nTry it: http://auth-plug-example.herokuapp.com/optional\n\n\u003cbr /\u003e\n\n## Using with `LiveView`\n\nIf you are using **`LiveView`**,\nhaving socket assigns with this info\nis useful for conditional rendering.\nFor this, you can use the \n`assign_jwt_to_socket/3` function\nto add the `jwt` information to the socket,\ne.g:\n\n```elixir\nsocket = socket\n  |\u003e AuthPlug.assign_jwt_to_socket(\u0026Phoenix.Component.assign_new/3, jwt)\n```\n\nThis will add a `person` object with information\nabout the authenticated person. \nHere is the assigns should look like\nafter calling this function.\n\n```elixir\nsocket #=\u003e #Phoenix.LiveView.Socket\u003c\n  id: 123,\n  ...\n  assigns: %{\n    __changed__: %{loggedin: true, person: true},\n    loggedin: true,\n    person: %{\n      aud: \"Joken\",\n      email: \"person@dwyl.com\",\n      exp: 1701020233,\n      iat: 1669483233,\n      iss: \"Joken\",\n      jti: \"2slj49u49a3f3896l8000083\",\n      nbf: 1669483233,\n      session: 1,\n      username: \"username\",\n      givenName: \"Test Smith\",\n      username: \"dwyl_username\"\n    }\n  },\n  transport_pid: nil,\n  ...\n\u003e\n```\n\n## Using with an `API`\n\nAlthough you'll probably use this package\nin scopes that are piped through\n`:browser` pipelines,\nit can still be used in APIs - \nusing a pipeline that only accepts `json` requests.\nLike so:\n\n```elixir\n  pipeline :api do\n    plug :accepts, [\"json\"]\n  end\n\n  scope \"/api\", AppWeb do\n    pipe_through [:api]\n\n    resources \"/items\", ItemController, only: [:create, :update]\n  end\n```\n\nYou may create a pipeline using `auth_plug`,\neither be it for normal or optional authentication.\nHowever, this pipeline \n**has to to use the [`fetch_session`](https://hexdocs.pm/plug/Plug.Conn.html#fetch_session/2) plug**\nfor `auth_plug` to work.\n\nFor example,\nif you wanted to pipe your API scope \ninside your `router.ex` file\nwith `:authOptional`...\n\n```elixir\n  scope \"/api\", AppWeb do\n    pipe_through [:api, :authOptional]\n\n    resources \"/items\", ItemController, only: [:create, :update]\n  end\n```\n\nit should be defined as such:\n\n```elixir\n  pipeline :authOptional do\n    plug :fetch_session\n    plug(AuthPlugOptional)\n  end\n```\n\n\n\n\n\n# Documentation\n\nFunction docs are available at:\nhttps://hexdocs.pm/auth_plug. \u003cbr /\u003e\n\nAs always, we attempt to comment our code as much as possible,\nbut if _anything_ is unclear,\nplease open an issue:\n[github.com/dwyl/**auth_plug/issues**](https://github.com/dwyl/auth_plug/issues)\n\n\n# Development\n\nIf you want to _contribute_ to this project,\nthat's _great_! \n\nPlease ensure you create an issue \nto discuss your idea/plan\n_before_ working on a feature/update\nto avoid any wasted effort. \n\n## Clone\n\n```sh\ngit clone git@github.com:dwyl/auth_plug.git\n```\n\nCreate a `.env` file:\n\n```sh\ncp .env_sample .env\nsource .env\n```\n\nRun the test with coverage:\n\n```sh\nmix c\n```\n\n\n\u003cbr /\u003e\n\n## Available information\n\nBy default using the \n[`auth`](https://github.com/dwyl/auth)\nauthentication service,\n`auth_plug` makes the following information available in `conn.assigns`:\n\n```\njwt :: string()\nperson :: %{\n  id :: integer() # This stays unique across providers\n  auth_provider :: string()\n  email :: string()\n  givenName :: string()\n  picture :: string()\n\n  # Also includes standard jwt metadata you may find useful:\n  aud, exp, iat, iss\n}\n```\n\n\u003cbr /\u003e\n\n# Testing / CI\n\nIf you are using `GitHub CI`\nto _test_ your Auth Controller code\nthat invokes any of the `AuthPlug.Token` functions - \nand you should be ... -\nthen you will need to make the \n`AUTH_API_KEY` accessible to `@dependabot`.\n\nVisit: `https://github.com/{org}/{project}/settings/secrets/dependabot`\ne.g: https://github.com/dwyl/mvp/settings/secrets/dependabot\n\nAnd add the `AUTH_API_KEY` environment variable, \ne.g: \n\n![github-settings-dependabot-secrets](https://user-images.githubusercontent.com/194400/213398407-7f66ed6e-a7bd-4920-b4c0-27a635c6d98d.png)\n\nThanks to: [@danielabar](https://github.com/danielabar)\nfor her excellent/succinct post on this topic:\n[danielabaron.me/blog/dependabot-secrets](https://danielabaron.me/blog/dependabot-secrets/)\n\n\u003cbr /\u003e\n\n# Recommended / Relevant Reading\n\nIf you are new to Elixir Plug,\nwe recommend following:\n[github.com/dwyl/elixir-plug-tutorial](https://github.com/dwyl/elixir-plug-tutorial).\n\nTo understand JSON Web Tokens,\nread:\n[https://github.com/dwyl/learn-json-web-tokens](https://github.com/dwyl/learn-json-web-tokens).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdwyl%2Fauth_plug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdwyl%2Fauth_plug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdwyl%2Fauth_plug/lists"}