From 6564b40641101135c85f25b12e1209d66e816a52 Mon Sep 17 00:00:00 2001 From: Adrian Turjak Date: Wed, 9 Jan 2019 17:53:35 +1300 Subject: [PATCH] Add documentation for Auth Receipts and MFA Adds API ref examples for TOTP and Auth receipts. Adds docs for MFA and changes some of the user options docs. Change-Id: Id5497064e580093e4a2c7d904670a58095833b3b --- api-ref/source/v3/authenticate-v3.inc | 178 +++++++++++++++++- api-ref/source/v3/parameters.yaml | 77 +++++++- .../auth/requests/project-id-totp.json | 20 ++ .../auth/responses/auth-receipt-password.json | 20 ++ .../project-scoped-password-totp.json | 67 +++++++ api-ref/source/v3/status.yaml | 8 + doc/source/admin/auth-totp.rst | 2 + .../admin/authentication-mechanisms.rst | 1 + .../admin/multi-factor-authentication.rst | 88 +++++++++ doc/source/admin/resource-options.rst | 101 ++++++++++ doc/source/admin/security-compliance.rst | 60 +----- doc/source/user/index.rst | 1 + .../user/multi-factor-authentication.rst | 130 +++++++++++++ 13 files changed, 697 insertions(+), 56 deletions(-) create mode 100644 api-ref/source/v3/samples/auth/requests/project-id-totp.json create mode 100644 api-ref/source/v3/samples/auth/responses/auth-receipt-password.json create mode 100644 api-ref/source/v3/samples/auth/responses/project-scoped-password-totp.json create mode 100644 doc/source/admin/multi-factor-authentication.rst create mode 100644 doc/source/user/multi-factor-authentication.rst diff --git a/api-ref/source/v3/authenticate-v3.inc b/api-ref/source/v3/authenticate-v3.inc index 45d3f58f85..6e3cc62abf 100644 --- a/api-ref/source/v3/authenticate-v3.inc +++ b/api-ref/source/v3/authenticate-v3.inc @@ -10,7 +10,7 @@ optionally, grants authorization on a specific project, domain, or the deployment system. The body of an authentication request must include a payload that -specifies the authentication method, which is ``password`` or +specifies the authentication methods, which are normally just ``password`` or ``token``, the credentials, and, optionally, the authorization scope. You can scope a token to a project, domain, the deployment system, or the token can be unscoped. You cannot scope a token to multiple scope targets. @@ -18,6 +18,16 @@ the token can be unscoped. You cannot scope a token to multiple scope targets. Tokens have IDs, which the Identity API returns in the ``X-Subject-Token`` response header. +In the case of multi-factor authentication (MFA) more than one authentication +method needs to be supplied to authenticate. As of v3.12 a failure due to MFA +rules only partially being met will result in an auth receipt ID being returned +in the response header ``Openstack-Auth-Receipt``, and a response body that +details the receipt itself and the missing authentication methods. Supplying +the auth receipt ID in the ``Openstack-Auth-Receipt`` header in a follow-up +authentication request, with the missing authentication methods, will result in +a valid token by reusing the successful methods from the first request. This +allows MFA authentication to be a multi-step process. + After you obtain an authentication token, you can: - Make REST API requests to other OpenStack services. You supply the @@ -74,6 +84,10 @@ These authentication errors can occur: | | - The specified ``X-Auth-Token`` header is not valid. | | | | | | - The authentication credentials are not valid. | +| | | +| | - Not all MFA rules were satisfied. | +| | | +| | - The specified ``Openstack-Auth-Receipt`` header is not valid. | +------------------------+----------------------------------------------------------------------+ | ``Forbidden (403)`` | The identity was successfully authenticated but it is not | | | authorized to perform the requested action. | @@ -621,6 +635,168 @@ Example :language: javascript +Multi-Step authentication (2-Factor Password and TOTP example) +============================================================== + +.. rest_method:: POST /v3/auth/tokens + +Authenticates an identity and generates a token. Uses the password +authentication method, then the totp method, with an auth receipt in between. + +This assumes that MFA has been enabled for the user, and a rule has been +defined requiring authentication with both password and totp. + +The first request body must at least include a payload that specifies one of +``password`` or ``totp`` authentication methods which includes the credentials +in addition to an optional scope. If only one method is supplied then an auth +receipt will be returned. Scope is not retained in the receipt and must be +resupplied in subsequent requests. + +While it is very possible to supply all the required auth methods at once, this +example shows the multi-step process which is likely to be more common. + +More than 2 factors can be used but the same process applies to those as well; +either all auth methods are supplied at once, or in steps with one or more auth +receipts in between. + +Relationship: ``https://docs.openstack.org/api/openstack-identity/3/rel/auth_tokens`` + +First Request +------------- + +Parameters +~~~~~~~~~~ + +.. rest_parameters:: parameters.yaml + + - nocatalog: nocatalog + - name: user_name + - auth: auth + - user: user + - scope: scope_string + - password: password + - id: user_id + - identity: identity + - methods: auth_methods_passwd + +Example +~~~~~~~ + +.. literalinclude:: ./samples/auth/requests/project-id-password.json + :language: javascript + +Response +-------- + +Here we are expecting a 401 status, and a returned auth receipt. + +Parameters +~~~~~~~~~~ + +.. rest_parameters:: parameters.yaml + + - Openstack-Auth-Receipt: Openstack-Auth-Receipt + - methods: auth_methods_receipt + - expires_at: receipt_expires_at + - issued_at: receipt_issued_at + - user: user + - required_auth_methods: required_auth_methods + +Status Code +~~~~~~~~~~~ + +.. rest_status_code:: success status.yaml + + - 401: auth_receipt + +.. rest_status_code:: error status.yaml + + - 400 + - 401: auth_failed + - 403 + - 404 + +Auth Receipt Example +~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: ./samples/auth/responses/auth-receipt-password.json + :language: javascript + +Second Request +-------------- + +Parameters +~~~~~~~~~~ + +.. rest_parameters:: parameters.yaml + + - Openstack-Auth-Receipt: Openstack-Auth-Receipt + - nocatalog: nocatalog + - name: user_name + - auth: auth + - user: user + - scope: scope_string + - totp: totp + - id: user_id + - identity: identity + - methods: auth_methods_totp + +Example +~~~~~~~ + +.. literalinclude:: ./samples/auth/requests/project-id-totp.json + :language: javascript + +Response +-------- + +Parameters +~~~~~~~~~~ + +.. rest_parameters:: parameters.yaml + + - X-Subject-Token: X-Subject-Token + - region_id: region_id_required + - methods: auth_methods_passwd + - roles: roles + - url: endpoint_url + - region: endpoint_region + - token: token + - expires_at: expires_at + - system: system_scope_response_body_optional + - domain: domain_scope_response_body_optional + - project: project_scope_response_body_optional + - issued_at: issued_at + - catalog: catalog + - user: user + - audit_ids: audit_ids + - interface: endpoint_interface + - endpoints: endpoints + - type: endpoint_type + - id: user_id + - name: user_name + +Status Codes +~~~~~~~~~~~~ + +.. rest_status_code:: success status.yaml + + - 201 + +.. rest_status_code:: error status.yaml + + - 400 + - 401: auth_receipt_failure + - 403 + - 404 + +Project-Scoped Password and TOTP Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. literalinclude:: ./samples/auth/responses/project-scoped-password-totp.json + :language: javascript + + Validate and show information for token ======================================= diff --git a/api-ref/source/v3/parameters.yaml b/api-ref/source/v3/parameters.yaml index 30b649e1f4..e34b425cb0 100644 --- a/api-ref/source/v3/parameters.yaml +++ b/api-ref/source/v3/parameters.yaml @@ -1,4 +1,12 @@ # variables in header +Openstack-Auth-Receipt: + description: | + The auth receipt. A partially successful authentication + response returns the auth receipt ID in this header rather than in the + response body. + in: header + required: true + type: string X-Auth-Token: description: | A valid authentication token for an @@ -477,8 +485,8 @@ auth_domain: type: object auth_methods: description: | - The authentication method, which is ``password``, - ``token``, or both methods. Indicates the accumulated set of + The authentication methods, which are commonly ``password``, + ``token``, or other methods. Indicates the accumulated set of authentication methods that were used to obtain the token. For example, if the token was obtained by password authentication, it contains ``password``. Later, if the token is exchanged by using @@ -506,6 +514,19 @@ auth_methods_passwd: in: body required: true type: array +auth_methods_receipt: + description: | + The authentication methods, which are commonly ``password``, + ``totp``, or other methods. Indicates the accumulated set of + authentication methods that were used to obtain the receipt. For + example, if the receipt was obtained by password authentication, it + contains ``password``. Later, if the receipt is exchanged by using + another authentication method one or more times, the + subsequently created receipts could contain both ``password`` and + ``totp`` in their ``methods`` attribute. + in: body + required: true + type: array auth_methods_token: description: | The authentication method. For token @@ -513,6 +534,13 @@ auth_methods_token: in: body required: true type: array +auth_methods_totp: + description: | + The authentication method. For totp + authentication, specify ``totp``. + in: body + required: true + type: array auth_token: description: | A ``token`` object. The token authentication @@ -1433,6 +1461,38 @@ projects: in: body required: true type: array +receipt_expires_at: + description: | + The date and time when the receipt expires. + + The date and time stamp format is `ISO 8601 + `_: + + :: + + CCYY-MM-DDThh:mm:ss.sssZ + + For example, ``2015-08-27T09:49:58.000000Z``. + + A ``null`` value indicates that the receipt never expires. + in: body + required: true + type: string +receipt_issued_at: + description: | + The date and time when the receipt was issued. + + The date and time stamp format is `ISO 8601 + `_: + + :: + + CCYY-MM-DDThh:mm:ss.sssZ + + For example, ``2015-08-27T09:49:58.000000Z``. + in: body + required: true + type: string region_id_not_required: description: | (Since v3.2) The ID of the region that contains @@ -1604,6 +1664,13 @@ request_service_id_registered_limit_body_not_required: in: body required: false type: string +required_auth_methods: + description: | + A list of authentication rules that may be used with the auth receipt + to complete the authentication process. + in: body + required: true + type: list of lists resource_limit: description: | The override limit. @@ -1909,6 +1976,12 @@ token: in: body required: true type: object +totp: + description: | + The ``totp`` object, contains the authentication information. + in: body + required: true + type: object user: description: | A ``user`` object. diff --git a/api-ref/source/v3/samples/auth/requests/project-id-totp.json b/api-ref/source/v3/samples/auth/requests/project-id-totp.json new file mode 100644 index 0000000000..fdfcc971e0 --- /dev/null +++ b/api-ref/source/v3/samples/auth/requests/project-id-totp.json @@ -0,0 +1,20 @@ +{ + "auth": { + "identity": { + "methods": [ + "totp" + ], + "totp": { + "user": { + "id": "ee4dfb6e5540447cb3741905149d9b6e", + "passcode": "123456" + } + } + }, + "scope": { + "project": { + "id": "a6944d763bf64ee6a275f1263fae0352" + } + } + } +} diff --git a/api-ref/source/v3/samples/auth/responses/auth-receipt-password.json b/api-ref/source/v3/samples/auth/responses/auth-receipt-password.json new file mode 100644 index 0000000000..40f64f87f9 --- /dev/null +++ b/api-ref/source/v3/samples/auth/responses/auth-receipt-password.json @@ -0,0 +1,20 @@ +{ + "receipt":{ + "expires_at":"2018-07-05T08:39:23.000000Z", + "issued_at":"2018-07-05T08:34:23.000000Z", + "methods": [ + "password" + ], + "user": { + "domain": { + "id": "default", + "name": "Default" + }, + "id": "ee4dfb6e5540447cb3741905149d9b6e", + "name": "admin" + } + }, + "required_auth_methods": [ + ["totp", "password"] + ] +} diff --git a/api-ref/source/v3/samples/auth/responses/project-scoped-password-totp.json b/api-ref/source/v3/samples/auth/responses/project-scoped-password-totp.json new file mode 100644 index 0000000000..6b84e3efe9 --- /dev/null +++ b/api-ref/source/v3/samples/auth/responses/project-scoped-password-totp.json @@ -0,0 +1,67 @@ +{ + "token": { + "audit_ids": [ + "3T2dc1CGQxyJsHdDu1xkcw" + ], + "catalog": [ + { + "endpoints": [ + { + "id": "068d1b359ee84b438266cb736d81de97", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://example.com/identity" + }, + { + "id": "8bfc846841ab441ca38471be6d164ced", + "interface": "admin", + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://example.com/identity" + }, + { + "id": "beb6d358c3654b4bada04d4663b640b9", + "interface": "internal", + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://example.com/identity" + } + ], + "type": "identity", + "id": "050726f278654128aba89757ae25950c", + "name": "keystone" + } + ], + "expires_at": "2015-11-07T02:58:43.578887Z", + "is_domain": false, + "issued_at": "2015-11-07T01:58:43.578929Z", + "methods": [ + "password", + "totp" + ], + "project": { + "domain": { + "id": "default", + "name": "Default" + }, + "id": "a6944d763bf64ee6a275f1263fae0352", + "name": "admin" + }, + "roles": [ + { + "id": "51cc68287d524c759f47c811e6463340", + "name": "admin" + } + ], + "user": { + "domain": { + "id": "default", + "name": "Default" + }, + "id": "ee4dfb6e5540447cb3741905149d9b6e", + "name": "admin", + "password_expires_at": "2016-11-06T15:32:17.000000" + } + } +} diff --git a/api-ref/source/v3/status.yaml b/api-ref/source/v3/status.yaml index 4cecc2ceb5..e026069ac5 100644 --- a/api-ref/source/v3/status.yaml +++ b/api-ref/source/v3/status.yaml @@ -27,6 +27,14 @@ 401: default: | User must authenticate before making a request. + auth_failed: | + Authentication attempt has failed. + auth_receipt: | + User has successfully supplied some auth methods, but not enough for full + authentication. + auth_receipt_failure: | + Authentication attempt has failed. Either the auth receipt has expired, or + the additional auth methods supplied were invalid. 403: default: | Policy does not allow current user to do this operation. diff --git a/doc/source/admin/auth-totp.rst b/doc/source/admin/auth-totp.rst index c3f5d1a8fc..3c331be964 100644 --- a/doc/source/admin/auth-totp.rst +++ b/doc/source/admin/auth-totp.rst @@ -11,6 +11,8 @@ License for the specific language governing permissions and limitations under the License. +.. _auth_totp: + =================================== Time-based One-time Password (TOTP) =================================== diff --git a/doc/source/admin/authentication-mechanisms.rst b/doc/source/admin/authentication-mechanisms.rst index 83b36a39c0..eb15bd4d03 100644 --- a/doc/source/admin/authentication-mechanisms.rst +++ b/doc/source/admin/authentication-mechanisms.rst @@ -8,6 +8,7 @@ user and password method. .. toctree:: :maxdepth: 2 + multi-factor-authentication auth-totp federation/federated_identity external-authentication diff --git a/doc/source/admin/multi-factor-authentication.rst b/doc/source/admin/multi-factor-authentication.rst new file mode 100644 index 0000000000..91c85c4626 --- /dev/null +++ b/doc/source/admin/multi-factor-authentication.rst @@ -0,0 +1,88 @@ +.. _multi_factor_authentication: + +=========================== +Multi-Factor Authentication +=========================== + +Configuring MFA +=============== + +MFA is configured on a per user basis via the user options +:ref:`multi_factor_auth_rules` and :ref:`multi_factor_auth_enabled`. Until +these are set the user can authenticate with any one of the enabled auth +methods. + +MFA rules +--------- + +The MFA rules allow an admin to force a user to use specific forms of +authentication or combinations of forms of authentication to get a token. + +The rules are specified as follows via the user option +:ref:`multi_factor_auth_rules`:: + + [["password", "totp"], ["password", "custom-auth-method"]] + +They are a list of lists. The elements of the sub-lists must be strings and are +intended to mirror the required authentication method names (e.g. ``password``, +``totp``, etc) as defined in the ``keystone.conf`` file in the +``[auth] methods`` option. Each list of methods specifies a rule. + +If the auth methods provided by a user match (or exceed) the auth methods in +the list, that rule is used. The first rule found (rules will not be processed +in a specific order) that matches will be used. If a user has the ruleset +defined as ``[["password", "totp"]]`` the user must provide both password and +totp auth methods (and both methods must succeed) to receive a token. However, +if a user has a ruleset defined as ``[["password"], ["password", "totp"]]`` +the user may use the ``password`` method on it's own but would be required +to use both ``password`` and ``totp`` if ``totp`` is specified at all. + +Any auth methods that are not defined in ``keystone.conf`` in the +``[auth] methods`` option are ignored when the rules are processed. Empty +rules are not allowed. If a rule is empty due to no-valid auth methods +existing within it, the rule is discarded at authentication time. If there +are no rules or no valid rules for the user, authentication occurs in the +default manner: any single configured auth method is sufficient to receive +a token. + +.. note:: + + The ``token`` auth method typically should not be specified in any MFA + Rules. The ``token`` auth method will include all previous auth methods + for the original auth request and will match the appropriate ruleset. This + is intentional, as the ``token`` method is used for rescoping/changing + active projects. + +Enabling MFA +------------ + +Before the MFA rules take effect on a user, MFA has to be enabled for that user +via the user option :ref:`multi_factor_auth_enabled`. By default this is unset, +and the rules will not take effect until configured. + +In the case a user should be exempt from MFA Rules, regardless if they are +set, the User-Option may be set to ``False``. + +Using MFA +========= + +See :ref:`multi_factor_authentication_user_guide` in the user guide for some +examples. + + +Supported multi-factor authentication methods +============================================= + +TOTP is the only suggested second factor along with password for now, but there +are plans to include more in future. + +TOTP +---- + +This is a simple 6 digit passcode generated by both the server and client from +a known shared secret. + +This used in a multi-step fashion is the most common 2-factor method used these +days. + +See: :ref:`auth_totp` diff --git a/doc/source/admin/resource-options.rst b/doc/source/admin/resource-options.rst index 23b5008686..c79aa19439 100644 --- a/doc/source/admin/resource-options.rst +++ b/doc/source/admin/resource-options.rst @@ -22,6 +22,28 @@ User Options The following options are available on user resources. If left undefined, they are assumed to be false or disabled. +These can be set either in the initial user creation (``POST /v3/users``) +or by updating an existing user to include new options +(``PATCH /v3/users/{user_id}``): + +.. code-block:: json + + { + "user": { + "options": { + "ignore_lockout_failure_attempts": true + } + } + } + +.. note:: + + User options of the ``Boolean`` type can be set to ``True``, ``False``, or + ``None``; if the option is set to ``None``, it is removed from the user's + data structure. + +.. _ignore_change_password_upon_first_use: + ignore_change_password_upon_first_use ------------------------------------- @@ -32,9 +54,21 @@ they log into keystone for the first time. This can be useful for deployments that auto-generate passwords but want to ensure a user picks a new password when they start using the deployment. +.. code-block:: json + + { + "user": { + "options": { + "ignore_change_password_upon_first_use": true + } + } + } + See the `security compliance documentation `_ for more details. +.. _ignore_password_expiry: + ignore_password_expiry ---------------------- @@ -45,9 +79,21 @@ Opt into ignoring global password expiration settings defined in option to ``True`` will allow users to continue using passwords that may be expired according to global configuration values. +.. code-block:: json + + { + "user": { + "options": { + "ignore_password_expiry": true + } + } + } + See the `security compliance documentation `_ for more details. +.. _ignore_lockout_failure_attempts: + ignore_lockout_failure_attempts ------------------------------- @@ -56,9 +102,21 @@ Type: ``Boolean`` If ``True``, opt into ignoring the number of times a user has authenticated and locking out the user as a result. +.. code-block:: json + + { + "user": { + "options": { + "ignore_lockout_failure_attempts": true + } + } + } + See the `security compliance documentation `_ for more details. +.. _lock_password: + lock_password ------------- @@ -67,9 +125,22 @@ Type: ``Boolean`` If set to ``True``, this option disables the ability for users to change their password through self-service APIs. +.. code-block:: json + + { + "user": { + "options": { + "lock_password": true + } + } + } + + See the `security compliance documentation `_ for more details. +.. _multi_factor_auth_enabled: + multi_factor_auth_enabled ------------------------- @@ -80,6 +151,20 @@ This will result in different behavior at authentication time and the user may be presented with different authentication requirements based on multi-factor configuration. +.. code-block:: json + + { + "user": { + "options": { + "multi_factor_auth_enabled": true + } + } + } + +See :ref:`multi_factor_authentication` for further details. + +.. _multi_factor_auth_rules: + multi_factor_auth_rules ----------------------- @@ -87,3 +172,19 @@ Type: ``List of Lists of Strings`` Define a list of strings that represent the methods required for a user to authenticate. + +.. code-block:: json + + { + "user": { + "options": { + "multi_factor_auth_rules": [ + ["password", "totp"], + ["password", "u2f"] + ] + } + } + } + + +See :ref:`multi_factor_authentication` for further details. diff --git a/doc/source/admin/security-compliance.rst b/doc/source/admin/security-compliance.rst index 7f9ddb8201..5246bb51f5 100644 --- a/doc/source/admin/security-compliance.rst +++ b/doc/source/admin/security-compliance.rst @@ -42,18 +42,7 @@ indefinitely until the user is explicitly enabled via the API. You can ensure specific users are never locked out. This can be useful for service accounts or administrative users. You can do this by setting -``ignore_lockout_failure_attempts`` to ``true`` via a user update API -(``PATCH /v3/users/{user_id}``): - -.. code-block:: json - - { - "user": { - "options": { - "ignore_lockout_failure_attempts": true - } - } - } +the user option for :ref:`ignore_lockout_failure_attempts`. Disabling inactive users ------------------------ @@ -85,18 +74,7 @@ authentication (first use), before being able to access any services. Prior to enabling this feature, you may want to exempt some users that you do not wish to be required to change their password. You can mark a user as exempt by setting the user options attribute -``ignore_change_password_upon_first_use`` to ``true`` via a user update API -(``PATCH /v3/users/{user_id}``): - -.. code-block:: json - - { - "user": { - "options": { - "ignore_change_password_upon_first_use": true - } - } - } +:ref:`ignore_change_password_upon_first_use`. .. WARNING:: @@ -131,18 +109,7 @@ expiration date, you would need to run a SQL script against the password table in the database to update the expires_at column. If there exists a user whose password you do not want to expire, keystone -supports setting that user's option ``ignore_password_expiry`` to ``true`` -via user update API (``PATCH /v3/users/{user_id}``): - -.. code-block:: json - - { - "user": { - "options": { - "ignore_password_expiry": true - } - } - } +supports setting that via the user option :ref:`ignore_password_expiry`. Configuring password strength requirements ------------------------------------------ @@ -225,24 +192,11 @@ Prevent Self-Service Password Changes ------------------------------------- If there exists a user who should not be able to change her own password via -the keystone password change API, keystone supports setting that user's option -``lock_password`` to ``True`` via the user update API -(``PATCH /v3/users/{user_id}``): +the keystone password change API, keystone supports setting that via the user +option :ref:`lock_password`. -.. code-block:: json - - { - "user": { - "options": { - "lock_password": true - } - } - } - -The ``lock_password`` user-option is typically used in the case where passwords -are managed externally to keystone. The ``lock_password`` option can be set to -``True``, ``False``, or ``None``; if the option is set to ``None``, it is -removed from the user's data structure. +This is typically used in the case where passwords are managed externally to +keystone. .. _Security Hardening PCI-DSS: https://specs.openstack.org/openstack/keystone-specs/specs/keystone/newton/pci-dss.html diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst index cc9a178206..a2f320f816 100644 --- a/doc/source/user/index.rst +++ b/doc/source/user/index.rst @@ -30,3 +30,4 @@ An end user can find the specific API documentation here, `OpenStack's Identity trusts.rst json_home.rst ../api_curl_examples.rst + multi-factor-authentication.rst diff --git a/doc/source/user/multi-factor-authentication.rst b/doc/source/user/multi-factor-authentication.rst new file mode 100644 index 0000000000..48de0cd45d --- /dev/null +++ b/doc/source/user/multi-factor-authentication.rst @@ -0,0 +1,130 @@ +.. _multi_factor_authentication_user_guide: + +=========================== +Multi-Factor Authentication +=========================== + +Configuring MFA +=============== + +Configuring MFA right now has to be done entirely by an admin, for how to do +that, see :ref:`multi_factor_authentication`. + +Using MFA +========= + +Multi-Factor Authentication with Keystone can be used in two ways, either you +treat it like current single method authentication and provide all the details +upfront, or you doing it as a multi-step process with auth receipts. + +Single step +----------- + +In the single step approach you would supply all the required authentication +methods in your request for a token. + +Here is an example using 2 factors (``password`` and ``totp``): + +.. code-block:: json + + { "auth": { + "identity": { + "methods": [ + "password", + "totp" + ], + "totp": { + "user": { + "id": "2ed179c6af12496cafa1d279cb51a78f", + "passcode": "012345" + } + }, + "password": { + "user": { + "id": "2ed179c6af12496cafa1d279cb51a78f", + "password": "super sekret pa55word" + } + } + } + } + } + +If all the supplied auth methods are valid, Keystone will return a token. + +Multi-Step +---------- + +In the multi-step approach you can supply any one method from the auth rules: + +Again we do a 2 factor example, starting with ``password``: + +.. code-block:: json + + { "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "id": "2ed179c6af12496cafa1d279cb51a78f", + "password": "super sekret pa55word" + } + } + } + } + } + +Provided the method is valid, Keystone will still return a ``401``, but will in +the response header ``Openstack-Auth-Receipt`` return a receipt of valid auth +method for reuse later. + +The response body will also contain information about the auth receipt, and +what auth methods may be missing: + +.. code-block:: json + + { + "receipt":{ + "expires_at":"2018-07-05T08:39:23.000000Z", + "issued_at":"2018-07-05T08:34:23.000000Z", + "methods": [ + "password" + ], + "user": { + "domain": { + "id": "default", + "name": "Default" + }, + "id": "ee4dfb6e5540447cb3741905149d9b6e", + "name": "admin" + } + }, + "required_auth_methods": [ + ["totp", "password"] + ] + } + +Now you can continue authenticating by supplying the missing auth methods, and +supplying the header ``Openstack-Auth-Receipt`` as gotten from the previous +response: + +.. code-block:: json + + { "auth": { + "identity": { + "methods": [ + "totp" + ], + "totp": { + "user": { + "id": "2ed179c6af12496cafa1d279cb51a78f", + "passcode": "012345" + } + } + } + } + } + +Provided the auth methods are valid, Keystone will now supply a token. If not +you can try again until the auth receipt expires (e.g in case of TOTP timeout).