Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request FIDO2 #1109

Open
MaSven opened this issue Jan 17, 2022 · 6 comments
Open

Feature request FIDO2 #1109

MaSven opened this issue Jan 17, 2022 · 6 comments

Comments

@MaSven
Copy link

MaSven commented Jan 17, 2022

I saw that hex.pm can do 2FA, but only with OTP. A new and better option would be to also allow 2FA with FIDO2. The advantage is, that fido2 is phishing resistant. Is this the correct place to make such a feature request?

I would be open in trying to implement this.

@ericmj
Copy link
Member

ericmj commented Jan 18, 2022

Yes, you made the feature request in the correct place and thanks for offering to implement it. FIDO2 is definitely an improvement over our current 2FA.

It's hard to say if we want to add this without a knowing how complex it would be. Can you list the changes required you expect or make a prototype PR if that's easier?

Is it possible to use FIDO2 in Elixir/Erlang CLI applications?

@MaSven
Copy link
Author

MaSven commented Jan 19, 2022

Yes, sure. I will describe the details here until next Sunday.

@MaSven
Copy link
Author

MaSven commented Jan 30, 2022

Just a heads-up. I'm still working on this. FIDO2 is a bigger spec than I expected, and I wanted to understand it fully before suggesting changes here.

@MaSven
Copy link
Author

MaSven commented Feb 1, 2022

So, I think I have gathered enough information for this. First, I would like to provide a form of clarification of what FIDO2 is.

Nouns

FIDO2 is a set of specifications by the Fast IDentity Online Alliance hence the name FIDO.
We have this parts in it.

  • UAF (Universal Authentication Framework)
  • U2F (Universal Second Factor) formerly known as CTAP1
  • Webauthn (Web Authentication Framework)
  • CTAP1/2 (Client to Authenticator Protocols) Basically the protocol to talk to the hardware key device.

Specifications are here https://fidoalliance.org/specifications/download

What do we need

For hex only UAF and U2F are relevant as webauthn is an api implemented by the browser. U2F is the part for implementing 2FA. UAF is for passwordless authentication. For now, I would focus on U2F.

For U2F there is already a package on hex which implements this for the browser WAX. This also includes a demo app wax_demo. We need to update the depdencies but overall the project looks good.

The client side is a bit trickier. There are currently no elixir libraries implementing this, as we have to read the hardware key, which comes in multiple forms. There is a c library by yubikey https://developers.yubico.com/libfido2/ that we can use in a nif wrapper. This is a widely used project, for example openssh uses this https://github.com/openssh/openssh-portable#dependencies.

Another possible solution would be to leverage the browser from the cli.

How to integrate

We need to edit the lib/hexpm_web/templates/tfa_auth/show.html.eex template. The view should ask for the hardware device first. The user should have an option to use TOTP instead if he wants to. Only show the question for hardware device if one is registered. The lib/hexpm_web/controllers/tfa_auth_controller.ex has to submit some extra information for the view. This looks like this in the wax_demo.

      conn
      |> put_session(:authentication_challenge, challenge)
      |> render("credential.html",
        login: login,
        with_webauthn: true,
        challenge: Base.encode64(challenge.bytes),
        rp_id: challenge.rp_id,
        user: login,
        cred_ids: Enum.map(cred_ids, fn {_login, cred_id, _cose_key} -> cred_id end)
      )

We edit the render_show and create functions for this. A new controller for the cli would make sense here.

For the registration we need to edit the lib/hexpm_web/controllers/dashboard/tfa_setup_controller.ex and lib/hexpm_web/templates/dashboard/tfa_auth_setup/index.html.eex to allow the registration of a hardware device.
Example from the demo

conn
        |> put_session(:challenge, challenge)
        |> render("register_key.html",
          login: get_session(conn, :login),
          challenge: Base.encode64(challenge.bytes),
          rp_id: challenge.rp_id,
          user: login
        )

With a new validation

  def validate(conn, %{
        "key" => %{
          "attestationObject" => attestation_object_b64,
          "clientDataJSON" => client_data_json,
          "rawID" => raw_id_b64,
          "type" => "public-key"
        }
      }) do
    challenge = get_session(conn, :challenge)

    attestation_object = Base.decode64!(attestation_object_b64)

    case Wax.register(attestation_object, client_data_json, challenge) do
      {:ok, {authenticator_data, result}} ->
        Logger.debug(
          "Wax: attestation object validated with result #{inspect(result)} " <>
            " and authenticator data #{inspect(authenticator_data)}"
        )

        user = get_session(conn, :login)

        WaxDemo.User.register_new_cose_key(
          user,
          raw_id_b64,
          authenticator_data.attested_credential_data.credential_public_key
        )

        conn
        |> put_flash(:info, "Key registered")
        |> redirect(to: "/me")

      {:error, _} = error ->
        Logger.debug("Wax: attestation object validation failed with error #{inspect(error)}")

        conn
        |> put_flash(:error, "Key registration failed")
        |> index(%{})
    end
  end

At the end, we will save a new credential_id and a cose key for the user. Best practice is to allow multiple keys. Because we want to avoid locking someone out if you lose one key.

I Probably forgot something to tell here, so please ask if you have questions.

@MaSven
Copy link
Author

MaSven commented Feb 1, 2022

Next step for me would be to make a POC. Maybe things get clearer after that.

@MaSven
Copy link
Author

MaSven commented Feb 26, 2022

@ericmj what do you think should i do a POC?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants