Coder Social home page Coder Social logo

zanderxyz / veil Goto Github PK

View Code? Open in Web Editor NEW
165.0 4.0 14.0 67 KB

Simple passwordless authentication for your Phoenix apps

License: MIT License

Elixir 88.25% HTML 11.75%
elixir elixir-lang elixir-library elixir-phoenix phoenix phoenix-application phoenix-elixir elixir-language

veil's Introduction

Veil

Simple passwordless authentication for your Phoenix apps.

Installation

  1. Create a new Phoenix project, and change to the working directory:
$ mix phx.new your_app
$ cd your_app
  1. Add veil to your list of dependencies in mix.exs:
def deps do
  [{:veil, "~> 0.2"}]
end
  1. Fetch dependencies, and install Veil using the default task:
$ mix deps.get
$ mix veil.add
  1. Update the Veil configuration in your config.exs file to add an API key for your preferred email service (for more details on the email options, please refer to the Swoosh Documentation).
config :veil, YourAppWeb.Veil.Mailer,
  adapter: Swoosh.Adapters.Sendgrid,
  api_key: "your-api-key"
  1. Launch your server and open http://localhost:4000/ in your browser.
$ mix ecto.migrate
$ mix phx.server

If you click the sign-in link in the top right and enter your email address, you'll be sent an email with a sign-in button. Click this to re-open the website and you'll see you are now authenticated.

Configuration

The full configuration section added to your config/config.exs looks like this:

config :veil,
  site_name: "Your Website Name",
  email_from_name: "Your Name",
  email_from_address: "[email protected]",
  sign_in_link_expiry: 12 * 3_600, # How long should emailed sign-in links be valid for?
  session_expiry: 86_400 * 30, # How long should sessions be valid for?
  refresh_expiry_interval: 86_400,  # How often should existing sessions be extended to session_expiry
  sessions_cache_limit: 250, # How many recent sessions to keep in cache (to reduce database operations)
  users_cache_limit: 100 # How many recent users to keep in cache


config :veil, YourApp.Veil.Scheduler,
  jobs: [
    # Runs every midnight to delete all expired requests and sessions
    {"@daily", {YourApp.Veil.Clean, :expired, []}}
  ]

config :veil, YourAppWeb.Veil.Mailer,
  adapter: Swoosh.Adapters.Sendgrid,
  api_key: "your-api-key"

You should move the third part of this to a file that is not under version control, or save your API key as an environment variable instead.

Why Passwordless?

Most users choose insecure passwords, and for most use cases it's safer and easier to have them click a link in an email to authenticate themselves. An added advantage is that the lack of a password prevents the website leaking user passwords in the event of a data breach/hack. Furthermore, if a website offers a password reset link it is effectively just a more clumsy version of authentication by email.

The username/password paradigm is going to gradually die and the sooner the web can move past this for simple websites the better - Veil is my attempt to help speed this process up.

Authenticating Routes & Customising Veil

Virtually all of Veil's code is copied directly into your project when you run mix veil.add, so you can customise it to your heart's content.

By default Plugs.Veil.UserId is added to your default Router paths, which assigns the client's user_id to conn.assigns[:veil_user_id]. Additionally Plugs.Veil.User is also added, and assigns the full Veil.User struct to conn.assigns[:veil_user]. Veil.User objects are cached so this doesn't require database requests each time. You can easily extend the Veil.User struct to add additional fields, just make sure you use the Veil.update_user function to make any updates, so that these are also updated in the cache.

Authentication can either be handled using scopes in the Router, or in your Controllers. On adding Veil to your project, it adds the following block to your Router. Paths in this block will only be accessible to logged in users.

# Add your routes that require authentication in this block.
# Alternatively, you can use the default block and authenticate in the controllers.
# See the Veil README for more.
scope "/", YourAppWeb do
  pipe_through([:browser, YourAppWeb.Plugs.Veil.Authenticate])
end

To restrict access in controllers, you can add Plugs.Veil.Authenticate like so:

defmodule YourAppWeb.Controller
  use YourAppWeb, :controller

  plug YourAppWeb.Plugs.Veil.Authenticate when action in [:new, :create]

  # ...

This would restrict access to the new and create paths to logged in users only.

Security

The sign-in/auth process works as follows:

  1. User requests to sign-in using their email address. If they didn't previously have an account, one is created.

  2. An email is then sent to the user with a sign-in link. The email and website response is identical whether or not they previously had an account - this is to avoid leaking information to attackers.

  3. The link contains a Base32 encoded request id that is stored in a database by the server. When the user clicks the link, the server checks in the database to find out which user made the request, and how long it has been since they first tried to sign-in (default sign_in_link_expiry is 12 hours).

  4. If the link hasn't expired, a new session is created for the user along with a new Base32 encoded session id, and this is saved to a cookie. The browser sends the session id to the server for each web request, and the server checks it hasn't expired. If it is older than the refresh_expiry_interval (default 1 day), then the session is extended until the session_expiry (default 30 days).

  5. Request/Session ids are generated by concatenating together the following, calculating the SHA256 hash and then encoding to Base32. This should give sufficient entropy and length to be unguessable by an attacker.

  • A random string of bytes
  • The user's IP address
  • The user's user-agent string
  • A timestamp
  • A server secret that resets on startup

If you have any suggestions or questions about this process, please let me know.

Phoenix APIs

Veil works for Phoenix APIs as well, although in order for it to work seamlessly you would need to use it as the backend to a mobile app where you can deep link the sign-in link sent via email to cause the app to open on the client's mobile device. That app can then post the request id to the server and receive a session id in return. The session id can then be sent along with future API requests by the mobile app.

Note that by default Sendgrid changes links to redirect via their domain, so you would need to change mail adaptor or set up whitelabelling in order for deep links to work.

If your phoenix app was created with the --no-html flag, then Veil will install it's own no-html version.

Example

$ curl --data "[email protected]" http://localhost:4000/veil/users/
{"ok":true}

Email is sent containing the following URL: http://localhost:4000/veil/sessions/new/DK6VNMHPNRVDVEFLVTYAGXKSHBXEIXK5WTY7O2RG6RC3STDQLAZA====

Your mobile app intercepts this URL after the user taps it, strips out the request id and then posts it back to the server to receive a session id in return:

$ curl --data "request_id=DK6VNMHPNRVDVEFLVTYAGXKSHBXEIXK5WTY7O2RG6RC3STDQLAZA====" \
http://localhost:4000/veil/sessions/new/
{"session_id":"BICJZMZHQY3UOL7SVUJNHGBJYUI2ZSE47MV2T6NZZNQUJ3UHIPCQ===="}

The session id will then need to be sent for future requests to protected api routes.

Any thoughts on how this could be easily extended to work better for APIs out-of-the-box are welcome.

But I need something more full-featured!

Use Pow, Coherence or Guardian.

License

Veil is Copyright (c) 2018 Zander Khan

The source is released under the MIT License.

Check LICENSE for more information.

veil's People

Contributors

alkx avatar hassan avatar jayjun avatar lostkobrakai avatar optikfluffel avatar ream88 avatar zanderxyz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

veil's Issues

Clicking the Sign In link via local adapter causes Beam.smp to max out my CPU

Hi

Locally, the following happens:

  1. Click sign in
  2. fill out sign in form, e.g. [email protected]
  3. go to dev/mailbox
  4. click 'Open preview in separate tab`
  5. Click 'Sign In'
  6. I've sign in to my app, BUT I also notice that my CPU process 'beam.smp' jumps to 100+% and stays there.

I was expecting my CPU not to jump at all.

No other action on my site seems to cause a CPU spike.

I'm not even sure how to go about debugging this? Do you have any ideas?

I'm following this blog post https://elixircasts.io/passwordless-authentication-with-veil .

My config.exs file:

# //

# -- Veil Configuration    Don't remove this line
config :veil,
  site_name: "makeawesomeworkshop",
  email_from_name: "David Langford",
  email_from_address: "[email protected]",
  sign_in_link_expiry: 12 * 3_600, # How long should emailed sign-in links be valid for?
  session_expiry: 86_400 * 30, # How long should sessions be valid for?
  refresh_expiry_interval: 86_400,  # How often should existing sessions be extended to session_expiry
  sessions_cache_limit: 250, # How many recent sessions to keep in cache (to reduce database operations)
  users_cache_limit: 100 # How many recent users to keep in cache

config :veil, Veil.Scheduler,
  jobs: [
    # Runs every midnight to delete all expired requests and sessions
    {"@daily", {Maw.Veil.Clean, :expired, []}}
  ]

# This is in dev.config and prod.secrect.config ~ David
# config :veil, MawWeb.Veil.Mailer,
#   adapter: Swoosh.Adapters.Sendgrid,
#   api_key: "your-api-key"

# -- End Veil Configuration

My config/dev.exs file

# //

# Passwordless Authentication
config :veil, MawWeb.Veil.Mailer,
  adapter: Swoosh.Adapters.Local

# //

My mix.exs file:

      elixir: "~> 1.5",
 {:phoenix, "~> 1.4.3"},
{:veil, github: "zanderxyz/veil"},
  def project do
    [
      app: :maw,
      version: "0.1.0",
      elixir: "~> 1.5",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()
    ]
  end

  def application do
    [
      mod: {Maw.Application, []},
      extra_applications: [:logger, :runtime_tools]
    ]
  end

  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  defp deps do
    [
      {:bamboo, "~> 1.5"},
      {:phoenix, "~> 1.4.3"},
      {:phoenix_pubsub, "~> 1.1"},
      {:phoenix_ecto, "~> 4.0"},
      {:ecto_sql, "~> 3.0"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.11"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"},
      # Passwordless Authentication
      {:veil, github: "zanderxyz/veil"},
      # Waffle stuff below
      {:waffle, "~> 1.1.1"},
      {:ex_aws, "~> 2.1.2"},
      {:ex_aws_s3, "~> 2.0"},
      {:hackney, "~> 1.9"},
      {:sweet_xml, "~> 0.6"},
      {:waffle_ecto, "~> 0.0.9"}
      # Waffle stuff above
    ]
  end

  defp aliases do
    [
      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate", "test"],
      releases: releases()
    ]
  end

  defp releases() do
    [
      hexpm: [
        include_executables_for: [:unix]
      ]
    ]
  end

BUG : protocol Enumerable not implemented

Hi, i'm trying veil, the no-html version

Got this error :

Protocol.UndefinedError at POST /veil/users
protocol Enumerable not implemented for "QBDTRBWJX7AXK3L4EER7PVJHXLEUD4LYTGZKDHDGJNKTKHSRX4GQ====". This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Stream

Any idea ?

Thanks

Concrete example on how to reference the veil_user?

You wrote:

If you extend the Veil.User schema, you may want to add Plugs.Veil.User as well, which will assign the full Veil.User struct to conn.assigns[:veil_user]

Could you elaborate on exactly how this would be done?

Right now we can do <%= veil_user_id %> to grab the user id, but how would you set things up so that we can do <%= veil_user.email %> or access any attribute on the user that's logged in?

Umbrella support

It would be nice to have support for phoenix projects using the --umbrella option.

Phoenix 1.4 support?

This library sounds like exactly what I'm looking for, but I'm having a bit of trouble getting the setup instructions to work with a new Phoenix 1.4 project. I had a few compile-time errors like this:

== Compilation error in file lib/elm_phx_web/controllers/veil/session_controller.ex == ** (CompileError) lib/elm_phx_web/controllers/veil/session_controller.ex:20: undefined function page_path/2

and

== Compilation error in file lib/[project_name]_web/controllers/veil/session_controller.ex == ** (CompileError) lib/[project_name]_web/controllers/veil/session_controller.ex:39: undefined function user_path/2

Which I think are down to the changes in the routing in 1.4. I managed to fix them by adding the appropriate aliases, but when I boot up mix phx.server, the page at localhost:4000 doesn't seem to show the sign-in link in the top right mentioned in the readme.

I'm also getting a couple of Dialyzer warnings in lib/[project_name]_web/templates/veil/user/form.html.eex:

Function 'form.html'/1 has no local return

and

The call 'Elixir.Phoenix.HTML.Form':form_for(any(),any(),fun((_) -> {'safe',[any(),...]})) will never return since it differs in the 3rd argument from the success typing arguments: any(),any(),maybe_improper_list())

Which I guess may be related to this issue, but are beyond me to work out at the moment.

undefined function html?/0

Just saw your post about this project on the elixir forums and thought I'd give it a go.

Following the install instructions using phoenix 1.3.3 gives me this compile error though.

== Compilation error in file lib/testin/veil/veil.ex ==
** (CompileError) lib/testin/veil/veil.ex:62: undefined function html?/0
(stdlib) lists.erl:1338: :lists.foreach/2
(stdlib) erl_eval.erl:677: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

Ignoring unmatched topic "pos" in TestVailWeb.UserSocket

I have configured the email to SMTP with my webhost and I running it locally and it works but I am getting this in the log.

[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket
[warn] Ignoring unmatched topic "pos" in TestVailWeb.UserSocket

Fresh install gets quite a few warnings and deprecations

Greetings, really impressed with the concept of "Veil" and trying it out as a relatively new person to Phoenix and Elixir. Using Phoenix 1.5.8 and Elixir 1.11.3/ Erlang/OTP 23 sitting in an docker container on Alpine.

Maybe these warnings and deprecations should be disregarded, however I am raising this out of uncertainty. Would like to be more confident before building Veil in to the core of my project.

Using the instructions and all good until mix veil.add which produced more feedback than anticipated:

~/qimp $ mix veil.add
==> jumper
Compiling 1 file (.ex)
Generated jumper app
==> gen_state_machine
Compiling 3 files (.ex)
Generated gen_state_machine app
==> unsafe
Compiling 3 files (.ex)
Generated unsafe app
===> Fetching rebar3_hex v6.10.3
===> Downloaded package, caching at /apps/.cache/rebar3/hex/hexpm/packages/rebar3_hex-6.10.3.tar
===> Fetching hex_core v0.7.1
===> Downloaded package, caching at /apps/.cache/rebar3/hex/hexpm/packages/hex_core-0.7.1.tar
===> Fetching verl v1.0.2
===> Downloaded package, caching at /apps/.cache/rebar3/hex/hexpm/packages/verl-1.0.2.tar
===> Compiling verl
===> Compiling hex_core
===> Compiling rebar3_hex
===> Rebar3 detected a lock file from a newer version. It will be loaded in compatibility mode, but important information may be missing or lost. It is recommended to upgrade Rebar3.
===> Compiling sleeplocks
==> gen_stage
Compiling 10 files (.ex)
Generated gen_stage app
==> eternal
Compiling 5 files (.ex)
Generated eternal app
==> cachex
Compiling 54 files (.ex)
warning: unknown compiler variable "__" (expected one of __MODULE__, __ENV__, __DIR__, __CALLER__, __STACKTRACE__)
  lib/cachex/router.ex:238: Cachex.Router.configure_remote/4

warning: Unsafe.Generator.__before_compile__/1 defined in application :unsafe is used by the current application but the current application does not depend on :unsafe. To fix this, you must do one of:

  1. If :unsafe is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs

  2. If :unsafe is a dependency, make sure it is listed under "def deps" in your mix.exs

  3. In case you don't want to add a requirement to :unsafe, you may optionally skip this warning by adding [xref: [exclude: [Unsafe.Generator]]] to your "def project" in mix.exs

  lib/cachex.ex:1: Cachex

warning: Unsafe.Generator.__using__/1 defined in application :unsafe is used by the current application but the current application does not depend on :unsafe. To fix this, you must do one of:

  1. If :unsafe is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs

  2. If :unsafe is a dependency, make sure it is listed under "def deps" in your mix.exs

  3. In case you don't want to add a requirement to :unsafe, you may optionally skip this warning by adding [xref: [exclude: [Unsafe.Generator]]] to your "def project" in mix.exs

  lib/cachex.ex:36: Cachex

warning: Supervisor.Spec.worker/3 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/cachex/services/incubator.ex:37: Cachex.Services.Incubator.spec/2

warning: Supervisor.Spec.worker/3 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/cachex/services/informant.ex:148: Cachex.Services.Informant.spec/1

warning: Supervisor.Spec.supervise/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/cachex.ex:363: Cachex.init/1

warning: Supervisor.Spec.supervisor/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
Found at 6 locations:
  lib/cachex/services.ex:33: Cachex.Services.app_spec/0
  lib/cachex/services.ex:34: Cachex.Services.app_spec/0
  lib/cachex/services.ex:102: Cachex.Services.incubator_spec/1
  lib/cachex/services.ex:110: Cachex.Services.informant_spec/1
  lib/cachex/services.ex:132: Cachex.Services.limit_spec/1
  lib/cachex/services.ex:153: Cachex.Services.table_spec/1

warning: Supervisor.Spec.worker/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
Found at 3 locations:
  lib/cachex/services.ex:94: Cachex.Services.courier_spec/1
  lib/cachex/services.ex:119: Cachex.Services.janitor_spec/1
  lib/cachex/services.ex:143: Cachex.Services.locksmith_spec/1

warning: Supervisor.Spec.supervisor/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/cachex/services/overseer.ex:47: Cachex.Services.Overseer.start_link/0

warning: Supervisor.Spec.worker/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/cachex/services/overseer.ex:46: Cachex.Services.Overseer.start_link/0

Generated cachex app
==> crontab
Compiling 7 files (.ex)
Generated crontab app
==> libring
Compiling 5 files (.ex)
Generated libring app
==> swarm
Compiling 1 file (.erl)
Compiling 10 files (.ex)
warning: System.stacktrace/0 is deprecated, use __STACKTRACE__ instead
  lib/swarm/tracker/tracker.ex:828

warning: System.stacktrace/0 is deprecated, use __STACKTRACE__ instead
  lib/swarm/tracker/tracker.ex:1314

warning: System.stacktrace/0 is deprecated, use __STACKTRACE__ instead
  lib/swarm/tracker/tracker.ex:1408

warning: Supervisor.Spec.supervise/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/swarm/app.ex:16: Swarm.App.init/1

warning: Supervisor.Spec.supervisor/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
  lib/swarm/app.ex:11: Swarm.App.init/1

warning: Supervisor.Spec.worker/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
Found at 2 locations:
  lib/swarm/app.ex:12: Swarm.App.init/1
  lib/swarm/app.ex:13: Swarm.App.init/1

Generated swarm app
==> quantum
Compiling 38 files (.ex)
warning: Code.ensure_compiled?/1 is deprecated. Use Code.ensure_compiled/1 instead (see the proper disclaimers in its docs)
  lib/quantum/date_library/calendar.ex:1

warning: Code.ensure_compiled?/1 is deprecated. Use Code.ensure_compiled/1 instead (see the proper disclaimers in its docs)
  lib/quantum/date_library/timex.ex:1

warning: Quantum.DateLibrary.Timex.tz_to_utc!/2 is undefined (module Quantum.DateLibrary.Timex is not available or is yet to be defined)
  lib/quantum/date_library.ex:40: Quantum.DateLibrary.to_utc!/2

warning: Quantum.DateLibrary.Timex.utc_to_tz!/2 is undefined (module Quantum.DateLibrary.Timex is not available or is yet to be defined)
  lib/quantum/date_library.ex:47: Quantum.DateLibrary.to_tz!/2

Generated quantum app
==> swoosh
Compiling 32 files (.ex)
Generated swoosh app
==> phoenix_swoosh
Compiling 1 file (.ex)
warning: Phoenix.View.render_to_string/3 defined in application :phoenix is used by the current application but the current application does not depend on :phoenix. To fix this, you must do one of:

  1. If :phoenix is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs

  2. If :phoenix is a dependency, make sure it is listed under "def deps" in your mix.exs

  3. In case you don't want to add a requirement to :phoenix, you may optionally skip this warning by adding [xref: [exclude: [Phoenix.View]]] to your "def project" in mix.exs

  lib/phoenix_swoosh.ex:159: Phoenix.Swoosh.do_render_body/4

Generated phoenix_swoosh app
==> veil
Compiling 6 files (.ex)
warning: Mix.Phoenix.inflect/1 defined in application :phoenix is used by the current application but the current application does not depend on :phoenix. To fix this, you must do one of:

  1. If :phoenix is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs

  2. If :phoenix is a dependency, make sure it is listed under "def deps" in your mix.exs

  3. In case you don't want to add a requirement to :phoenix, you may optionally skip this warning by adding [xref: [exclude: [Mix.Phoenix]]] to your "def project" in mix.exs

  lib/mix/tasks/veil/add.ex:56: Mix.Tasks.Veil.Add.config_names/1

warning: Mix.Phoenix.otp_app/0 defined in application :phoenix is used by the current application but the current application does not depend on :phoenix. To fix this, you must do one of:

  1. If :phoenix is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs

  2. If :phoenix is a dependency, make sure it is listed under "def deps" in your mix.exs

  3. In case you don't want to add a requirement to :phoenix, you may optionally skip this warning by adding [xref: [exclude: [Mix.Phoenix]]] to your "def project" in mix.exs

  lib/mix/tasks/veil/add.ex:54: Mix.Tasks.Veil.Add.config_names/1

warning: Supervisor.Spec.worker/2 is deprecated. Use the new child specifications outlined in the Supervisor module instead
Found at 2 locations:
  lib/veil.ex:13: Veil.start/2
  lib/veil.ex:14: Veil.start/2

Generated veil app
==> qimp

Adding Veil to your project...

* amended config/config.exs - Veil config added
* creating lib/qimp/veil/clean.ex
* creating lib/qimp/veil/request.ex
* creating lib/qimp/veil/session.ex
* creating lib/qimp/veil/user.ex
* creating lib/qimp/veil/veil.ex
* creating lib/qimp_web/controllers/veil/fallback_controller.ex
* creating lib/qimp_web/controllers/veil/session_controller.ex
* creating lib/qimp_web/controllers/veil/user_controller.ex
* creating lib/qimp_web/emails/veil/login_email.ex
* creating lib/qimp_web/emails/veil/mailer.ex
* creating lib/qimp_web/plugs/veil/authenticate.ex
* creating lib/qimp_web/plugs/veil/user_id.ex
* creating lib/qimp_web/plugs/veil/user.ex
* creating lib/qimp_web/views/veil/email_view.ex
* creating lib/qimp_web/views/veil/error_view.ex
* creating lib/qimp_web/views/veil/session_view.ex
* creating lib/qimp_web/views/veil/user_view.ex
* creating lib/qimp_web/templates/veil/email/login.html.eex
* creating lib/qimp_web/templates/veil/user/form.html.eex
* creating lib/qimp_web/templates/veil/user/new.html.eex
* creating lib/qimp_web/templates/veil/user/show.html.eex
* creating priv/repo/migrations/20210302115654_add_veil.exs
* skipping lib/qimp_web/templates/layout/app.html.eex - already customised
* amended lib/qimp_web/router.ex - UserId & User plugs added to html pipeline
* amended lib/qimp_web/router.ex - Veil routes added

If your default layout page (`templates/layout/app.html.eex`) was already
modified or replaced, e.g. you see
`* skipping lib/sunrise_web/templates/layout/app.html.eex`
above then you'll need to manually add link markup similar to this:

  <%= if veil_user_id = assigns[:veil_user_id] do %>
    Authenticated as <%= veil_user_id %>
    <a href="<%= session_path(@conn, :delete, @session_unique_id) %>">Sign out</a>
  <% else %>
    <a href="<%= user_path(@conn, :new) %>">Sign in</a>
  <% end %>


Final steps:

Update the Veil configuration in your `config.exs` file to add an API key for your
preferred email service (for more details on the email options, please refer to the
[Swoosh Documentation](https://github.com/swoosh/swoosh)).

  config :veil, QimpWeb.Veil.Mailer,
    adapter: Swoosh.Adapters.Sendgrid,
    api_key: "your-api-key"

Launch your server and open http://localhost:4000/ in your browser.

  mix phx.server
  mix ecto.migrate

If you click the sign-in link in the top right and enter your email address, you'll be
sent an email with a sign-in button. Click this to re-open the website and you'll see
you are now authenticated.

For reference the output of mix deps.get command that preceded this is as follows:

~/qimp $ mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  connection 1.1.0
  cowboy 2.8.0
  cowboy_telemetry 0.3.1
  cowlib 2.9.1
  db_connection 2.3.1
  decimal 2.0.0
  ecto 3.5.8
  ecto_sql 3.5.4
  file_system 0.2.10
  gettext 0.18.2
  jason 1.2.2
  mime 1.5.0
  phoenix 1.5.8
  phoenix_ecto 4.2.1
  phoenix_html 2.14.3
  phoenix_live_dashboard 0.4.0
  phoenix_live_reload 1.3.0
  phoenix_live_view 0.15.4
  phoenix_pubsub 2.0.0
  plug 1.11.0
  plug_cowboy 2.4.1
  plug_crypto 1.2.1
  postgrex 0.15.8
  ranch 1.7.1
  telemetry 0.4.2
  telemetry_metrics 0.6.0
  telemetry_poller 0.5.1
New:
  cachex 3.3.0
  crontab 1.1.10
  eternal 1.2.2
  gen_stage 1.1.0
  gen_state_machine 2.1.0
  jumper 1.0.1
  libring 1.5.0
  phoenix_swoosh 0.2.0
  quantum 2.4.0
  sleeplocks 1.1.1
  swarm 3.4.0
  swoosh 0.25.6
  unsafe 1.0.1
  veil 0.2.0
* Getting veil (Hex package)
* Getting cachex (Hex package)
* Getting phoenix_swoosh (Hex package)
* Getting quantum (Hex package)
* Getting swoosh (Hex package)
* Getting crontab (Hex package)
* Getting gen_stage (Hex package)
* Getting swarm (Hex package)
* Getting gen_state_machine (Hex package)
* Getting libring (Hex package)
* Getting eternal (Hex package)
* Getting jumper (Hex package)
* Getting sleeplocks (Hex package)
* Getting unsafe (Hex package)

no function clause matching in Veil.verify/2

Hi.
I followed veil's official instruction an this to adding it in my project but for verification section it throws this error
no function clause matching in Veil.verify/2
an I tried create a new phoenix project for testing veil and I do it without any additional work! but I gave this error another time
so this is phoenix error page details:
%Plug.Conn{adapter: {Plug.Cowboy.Conn, :...}, assigns: %{}, before_send: [#Function<0.41104819/1 in Plug.CSRFProtection.call/2>, #Function<2.64052486/1 in Phoenix.Controller.fetch_flash/2>, #Function<0.54074652/1 in Plug.Session.before_send/2>, #Function<0.110189767/1 in Plug.Telemetry.call/2>, #Function<0.126136900/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{}, cookies: %{"_project_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYMDZ5NktPU0l6NUxFRGdVX0J1TmxuZzd1.Ka1I86vHSWu3oi2ZW9mvUO1KaLzwsuwKqp4l6pQcDOc", "session_unique_id" => "OTHCZF3R6PCBTTKTKOKQOSKQJPCXHMHCI53TUQVLP5BUIJ42GF7Q===="}, halted: false, host: "localhost", method: "GET", owner: #PID<0.32758.0>, params: %{"request_id" => "56VOVSQX4TCBUHPI45GVWOTWVKXUVRPB4QPQ5OMPLXYMMUKXUIZQ===="}, path_info: ["veil", "sessions", "new", "56VOVSQX4TCBUHPI45GVWOTWVKXUVRPB4QPQ5OMPLXYMMUKXUIZQ%3D%3D%3D%3D"], path_params: %{"request_id" => "56VOVSQX4TCBUHPI45GVWOTWVKXUVRPB4QPQ5OMPLXYMMUKXUIZQ===="}, port: 4000, private: %{ProjectWeb.Router => {[], %{}}, :phoenix_endpoint => ProjectWeb.Endpoint, :phoenix_flash => %{}, :phoenix_format => "html", :phoenix_router => ProjectWeb.Router, :plug_session => %{"_csrf_token" => "06y6KOSIz5LEDgU_BuNlng7u"}, :plug_session_fetch => :done}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %{"_project_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYMDZ5NktPU0l6NUxFRGdVX0J1TmxuZzd1.Ka1I86vHSWu3oi2ZW9mvUO1KaLzwsuwKqp4l6pQcDOc", "session_unique_id" => "OTHCZF3R6PCBTTKTKOKQOSKQJPCXHMHCI53TUQVLP5BUIJ42GF7Q===="}, req_headers: [{"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"}, {"accept-encoding", "gzip, deflate, br"}, {"accept-language", "en-US,en;q=0.9"}, {"connection", "keep-alive"}, {"cookie", "_project_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYMDZ5NktPU0l6NUxFRGdVX0J1TmxuZzd1.Ka1I86vHSWu3oi2ZW9mvUO1KaLzwsuwKqp4l6pQcDOc; session_unique_id=OTHCZF3R6PCBTTKTKOKQOSKQJPCXHMHCI53TUQVLP5BUIJ42GF7Q===="}, {"host", "localhost:4000"}, {"sec-fetch-mode", "navigate"}, {"sec-fetch-site", "cross-site"}, {"sec-fetch-user", "?1"}, {"upgrade-insecure-requests", "1"}, {"user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"}], request_path: "/veil/sessions/new/56VOVSQX4TCBUHPI45GVWOTWVKXUVRPB4QPQ5OMPLXYMMUKXUIZQ%3D%3D%3D%3D", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "Fbl--3GwlqVY6UwAAAYi"}, {"x-frame-options", "SAMEORIGIN"}, {"x-xss-protection", "1; mode=block"}, {"x-content-type-options", "nosniff"}, {"x-download-options", "noopen"}, {"x-permitted-cross-domain-policies", "none"}, {"cross-origin-window-policy", "deny"}], scheme: :http, script_name: [], secret_key_base: :..., state: :unset, status: nil} {:ok, %Project.Veil.Session{__meta__: #Ecto.Schema.Metadata<:loaded, "veil_sessions">, id: 3, inserted_at: ~N[2019-08-10 07:25:18], ip_address: "127.0.0.1", phoenix_token: "SFMyNTY.g3QAAAACZAAEZGF0YWECZAAGc2lnbmVkbgYAkddqemwB.PV8Kcnq8qhFBsoyv2Cjuq68O4Dz7TSw9-HEmtagJKkc", unique_id: "OTHCZF3R6PCBTTKTKOKQOSKQJPCXHMHCI53TUQVLP5BUIJ42GF7Q====", updated_at: ~N[2019-08-10 07:25:18], user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 2}}

image
image

what should I do?
thanks

The authenticate.ex plug has a placeholder project name

After running mix veil.add a bunch of folders and files were created as expected.

Inside most of those files, your task correctly changed PhoenixExampleWeb to my real project's name.

But plugs/veil/authenticate.ex on line 15 reads Phoenix.Controller.redirect(conn, to: PhoenixExampleWeb.Router.Helpers.user_path(conn, :new)).

I would have expected PhoenixExampleWeb to become my project name like the others automatically?

Texting instead of emailing?

Nice project, I love how simple it is!

I was wondering how complex it would be to text the secure link to some users instead of emailing them? Each user should be able to either login with its email or phone number

Should Veil expect the email address along with the verification string to complete authentication?

I recently had to work on an auth solution using Firebase Password-less authentication which is why I'm curious to raise this question about Veil:

If you look at Firebases' security concerns they suggest that the verification string should always be accompanied by the email address at the time of sign in:

To prevent a sign-in link from being used to sign in as an unintended user or on an unintended device, Firebase Auth requires the user's email address to be provided when completing the sign-in flow. For sign-in to succeed, this email address must match the address to which the sign-in link was originally sent.

I'm curious what you think about this requirement and whether that's something Veil should support?

Advice on test startup times

First off, thanks for veil! It's pretty much exactly what I need for this project.

One sticky point is that Quantum adds a significant delay to starting up the app when in test mode. I'm seeing upwards of 5s just to boot Quantum up. I'm wondering if you have any suggestions as to how to alleviate that?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.