pow icon indicating copy to clipboard operation
pow copied to clipboard

WebAuthn and multi factor support

Open danschultzer opened this issue 7 years ago • 11 comments

Add two factor support to Pow with at least OTP and FIDO U2F support.

Good primer for ensuring secure and useful two factor setup: https://medium.com/@stuartschechter/before-you-turn-on-two-factor-authentication-27148cc5b9a1

Edit: Here's some security considerations: https://shahmeeramir.com/4-methods-to-bypass-two-factor-authentication-2b0075d9eb5f


MFA auth

  • WebAuthn
  • OTP/TOTP
  • Recovery codes
  • E-mail/magic link
  • Device authorization (in app)

Process

In general the MFA authentication process will go like this:

User ID & password --> MFA authorization --> Signed in

OR as passwordless:

User ID --> MFA authorization --> Signed in

This latter option could also be all on the same page for some of the above methods. The MFA methods can also be used for the registration process.

There should be a controller action for handling 2FA auth, and probably one for handling registration with 2FA. Maybe one for managing 2FA methods.

WebAuthn links

https://webauthn.guide/ https://auth0.com/blog/web-authentication-webauthn-overview-demo-tool/


Suggested Ecto schema

There're two ways to go about this. Embedded or separate table. Separate table may make it easier to not require user id, but it could be that the user id should just be set to generated_id if developers wish to login without user id with a randomly generated id that will be stored with the authenticator.

field :type, :string
field :nickname, :string
field :settings, :map

WebAuthn use case

WebAuthn allows for no user id and can be used for single authentication.

The WebAuthn will store at minimum the following data:

{
  credential_id: "credential_id",
  cose_key: "cose_key"
}

For no user id setup, the user id used for the authenticator could be a randomly generated id that's stored in the authenticator schema.

TOTP use case

TOTP can only be used for 2FA. The data stored would be the following:

{
  issuer: "My Service",
  otp_secret: "secret",
  last_otp_at: "492039"
}

danschultzer avatar Aug 24 '18 20:08 danschultzer

A WebAuthn library that could be tested with: https://github.com/tanguilp/wax

danschultzer avatar Feb 12 '19 01:02 danschultzer

WebAuthn standard has been finalized by W3C!

We should consider a pure single factor Webauthn registration/authentication process where user id and password is not required (or user id is the the webauthn credential id(s). On top of this there will also be two factor.

I do think it’s the future of web authentication, far more than provider login.

danschultzer avatar Mar 04 '19 21:03 danschultzer

From the elixirforum, there's a question on multiple user id field authentication:

I’m just a bit curious. ^^ Is it possible (or could it be) to pass a list of fields to :user_id_field , so that user can authenticate through the field of their choice?

defmodule MyApp.Users.User do
  use Ecto.Schema
  use Pow.Ecto.Schema,
    user_id_field: [:email, :pseudo, :phone]

  # ...
end

This may fit with the user id less WebAuthn setup.

danschultzer avatar Mar 29 '19 15:03 danschultzer

What's the feeling on using external libraries to make this go faster/smoother?

Specifically:

  • elixir2fa (TOTP and HOTP [which would cover recovery codes as well], plus QR codes via Google Charts API)
  • passwordless_auth (SMS-based [via Twilio] passwordless or multi-factor auth)
  • wax (for FIDO/WebAuthn)

danhunsaker avatar Aug 15 '19 17:08 danhunsaker

I don't mind using a library to do the heavy lifting at all, but I don't plan to add any more dependencies to Pow so it would have to be an adapter setup, or an extension. No matter how it will be, I believe the biggest hurdle is to refactor the code so it's flexible enough to handle a custom auth flow (independent on what auth logic is used).

danschultzer avatar Aug 15 '19 17:08 danschultzer

An extension is probably sanest, then. Refactoring is certainly quite the task.

danhunsaker avatar Aug 15 '19 17:08 danhunsaker

Yeah. I've been too busy, but now with API integration guide and out-of-the-box distributed Mnesia released soon, I believe this is probably the next thing I'll take a dig at 😄

danschultzer avatar Aug 15 '19 17:08 danschultzer

Sounds awesome! Looking forward to removing my custom-rolled 2FA stuff in favor of the official implementation. (Fewer things I can do wrong if I'm not the one doing them. :joy: )

danhunsaker avatar Aug 15 '19 18:08 danhunsaker

For sure. If you can share the code, I would be happy to see how you solved it (maybe gist or repo)!

danschultzer avatar Aug 15 '19 18:08 danschultzer

Still implementing, but an extension that hooks into before_respond/4 is my current plan.

danhunsaker avatar Aug 15 '19 18:08 danhunsaker

Any updates on how this is going? Would love to see MFA in Pow!

OldhamMade avatar Feb 04 '21 09:02 OldhamMade