.. _2step_enrollment:

Two Step Enrollment
===================

.. index:: privacyIDEA Authenticator, twostep, 2step

Starting with version 2.21 privacyIDEA allows to enroll smartphone based tokens in a
2step enrollment.

With the rise of the smartphones and the fact that every user has a smartphone, carries it
with him all the time and cares about it a lot, using the smartphone for authentication
gets more and more attractive to IT departments.

Google came up with the Key URI [#keyuri]_ to use a QR code to easily enroll
a smartphone token, i.e. transport the OTP secret from the server to the phone.
However this bears some security issues as already pointed out [#problem]_.

This is why privacyIDEA allows to generate the OTP secret from a server component
and from a client component (generated by the smartphone). This way the enrolled
token is more tightly bound to this single smartphone and can not be copied that easily
anymore.

Workflow
--------

In a two step enrollment process the user clicks in the Web UI to enroll a token.
The server generates a QR code and the user will scan this QR code
with his smartphone app. The QR code contains the server component of the key
and the information, that a second component is needed.

The smartphone generates the second component and displays this to the
user.

The user enters this second component into the privacyIDEA Web UI.

Both the smartphone and the server calculate the OTP secret from
both components.

Two Step policies
-----------------

Two step enrollment is controlled by policies in the ``admin``/``user`` scope and
in the ``enrollment`` scope.

Thus the administrator can *allow* or *force* a user (or other administrators) to
do a two step enrollment. This way it is possible to avoid the enrollment of insecure
Google Authenticator QR codes in the complete installation. (:ref:`user_policy_2step`).

The default behaviour is to not allow a two step enrollment. Only if a corresponding
``admin`` or ``user`` policy is defined, two step enrollment is possible.

Key generation
~~~~~~~~~~~~~~

In addition the administrator can define an ``enrollment`` policy to specify
necessary parameters for the key generation.

Two step enrollment is possible for HOTP and TOTP tokens. Thus the administrator
can define token type specific policies in the scope ``enrollment``:
``hotp_2step_clientsize``, ``totp_2step_clientsize``, ``hotp_2step_difficulty``...
see :ref:`2step_parameters`.

privacyIDEA Authenticator
-------------------------

The privacyIDEA Authenticator [#authenticator]_ that is available from the
Google Play Store supports the two step enrollment.

Specification
-------------

The two step enrollment simply adds some parameters to the original Key URI.

**2step_output**

This is the resulting key size, which the smartphone should generate (in bytes).

**2step_salt**

This is the length of the client component that the smartphone should generate (in bytes).

**2step_difficulty**

This is the number of rounds for the PBKDF2 that the smartphone should use
to generate the OTP secret.

The ``secret`` parameter of the Key URI contains the server component.

The smartphone app then generates the client component, which is ``2step_salt`` random bytes.
It is then displayed in a human-readable format called ``base32check``::

    b32encode(sha1(client_component).digest()[0:4] + client_component).strip("=")

In other words, the first four bytes of the client component's SHA-1 hash are concatenated
with the actual client component. The result is encoded using base32, whereas
trailing padding characters are removed.

The second step of the enrollment process is realized as another request to the ``/token/init``
endpoint::

    POST /token/init

    serial=<token serial>
    otpkey=<base32check(client_component)>
    otpkeyformat=base32check

Server and smartphone app then use PBKDF2 to generate the final secret (see [#rfc2898]_ for parameter names)::

    secret = PBKDF2(P=hexlify(<server component>),
                    S=<client component>,
                    c=<2step_difficulty>
                    dkLen=<2step_output>)

whereas ``hexlify(<server component>)`` denotes a hex-encoding (using lowercase letters)
of the byte array which comprises the server component.

.. note::

    Please note that the two-step enrollment process is currently *not* designed to protect
    against malicious attackers. Depending on the choice of iteration count and salt size,
    an attacker who knows the server component and an OTP value may be able
    to obtain the client component with a brute-force approach.
    However, two-step enrollment is still an improvement to the status quo, as a simple copy
    of the QR code does not immediately leak the OTP secret and obtaining the OTP secret
    using brute-force is not trivial.

.. [#keyuri] https://github.com/google/google-authenticator/wiki/Key-Uri-Format
.. [#problem] https://netknights.it/en/the-problem-with-the-google-authenticator/
.. [#authenticator] https://play.google.com/store/apps/details?id=it.netknights.piauthenticator
.. [#rfc2898] https://www.ietf.org/rfc/rfc2898.txt