Skip to main content

Remote Two-factor Protected Services
draft-santesson-r2ps-00

Document Type Active Internet-Draft (individual)
Authors Stefan Santesson , Peter Altmann
Last updated 2026-06-25
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-santesson-r2ps-00
Network Working Group                                       S. Santesson
Internet-Draft                                           IDsec Solutions
Intended status: Standards Track                              P. Altmann
Expires: 17 December 2026                                          SIROS
                                                            15 June 2026

                  Remote Two-factor Protected Services
                        draft-santesson-r2ps-00

Abstract

   This document defines a generic service exchange protocol where
   service exchange data is protected and bound to a physical user using
   1 or 2 factors (1FA and 2FA).  The protocol facilitates registration
   and verification of either a knowledge-factor or a biometric factor
   in addition to a possession factor as means of achieving 2 factor
   protection.

About This Document

   This note is to be removed before publishing as an RFC.

   Status information for this document may be found at
   https://datatracker.ietf.org/doc/draft-santesson-r2ps/.

   Source for this draft and an issue tracker can be found at
   https://github.com/Razumain/r2ps-ietf-draft.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 17 December 2026.

Santesson & Altmann     Expires 17 December 2026                [Page 1]
Internet-Draft                    R2PS                         June 2026

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
     1.1.  Applicability for EU trust frameworks . . . . . . . . . .   3
   2.  Conventions and Definitions . . . . . . . . . . . . . . . . .   4
     2.1.  Definitions . . . . . . . . . . . . . . . . . . . . . . .   4
   3.  Basic structure . . . . . . . . . . . . . . . . . . . . . . .   5
     3.1.  Bootstrapping the protocol  . . . . . . . . . . . . . . .   6
     3.2.  Protection modes and sessions . . . . . . . . . . . . . .   6
   4.  R2PS Protocol Components  . . . . . . . . . . . . . . . . . .   7
     4.1.  Outer JWE object  . . . . . . . . . . . . . . . . . . . .   7
       4.1.1.  1FA mode  . . . . . . . . . . . . . . . . . . . . . .   7
       4.1.2.  2FA mode  . . . . . . . . . . . . . . . . . . . . . .   8
     4.2.  Inner JWS object  . . . . . . . . . . . . . . . . . . . .   9
       4.2.1.  Request data  . . . . . . . . . . . . . . . . . . . .   9
       4.2.2.  Response data . . . . . . . . . . . . . . . . . . . .  10
     4.3.  Second factor establishment and session creation  . . . .  11
       4.3.1.  Request parameters  . . . . . . . . . . . . . . . . .  12
       4.3.2.  Response parameters . . . . . . . . . . . . . . . . .  12
       4.3.3.  Member presence . . . . . . . . . . . . . . . . . . .  13
       4.3.4.  Service types . . . . . . . . . . . . . . . . . . . .  14
       4.3.5.  Defined authentication protocols  . . . . . . . . . .  17
   5.  Hardening of knowledge factors  . . . . . . . . . . . . . . .  24
   6.  Definition of service types . . . . . . . . . . . . . . . . .  24
   7.  Security Considerations . . . . . . . . . . . . . . . . . . .  24
   8.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  24
   9.  Normative References  . . . . . . . . . . . . . . . . . . . .  24
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  25
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  26

Santesson & Altmann     Expires 17 December 2026                [Page 2]
Internet-Draft                    R2PS                         June 2026

1.  Introduction

   Password-Authenticated Key Exchange (PAKE) protocols let two parties
   derive a shared key from a low-entropy password without disclosing
   it, while resisting offline guessing.  An augmented PAKE (aPAKE)
   further protects against server compromise.

   This document complements the capabilities of PAKE protocols by
   defining a service exchange protocol that can be used to:

   *  exchange data for a selected PAKE protocol, or any other protocol
      that validates a user knowledge or biometric factor, to establish
      a shared session key; and

   *  exchange service data protected under that session key.

   This document uses the OPAQUE aPAKE [RFC9807] as its RECOMMENDED
   mechanism for verifying a knowledge factor without exposing it to the
   server.

1.1.  Applicability for EU trust frameworks

   EU has defined a level of assurance framework for user authentication
   based on an eID [1502].  On the highest assurance level (LoA High)
   the key used to authenticate the user must be protected by tamper
   resistant hardware (HSM) that protects against an adversary with high
   attack potential.  This framework further specifies that access to
   the protected authentication key must be protected by 2-factor
   authentication.

   The EU Digital Identity Wallet (EUDI Wallet) defined by the new eIDAS
   regulation [{add ref}] specifies that HSM protection when the wallet
   provides authentication on LoA High, must be realized by a Wallet
   Secure Cryptographic Application (WSCA) that includes a Wallet Secure
   Cryptographic Device (WSCD).

   The WSCA is a software module responsible for controlling access to
   keys protected by the hardware module (WSCD).

   Some wallet actions, such as presenting a Verifiable Presentation on
   LoA High, requires the user to provide a knowledge-factor or a
   biometric factor together with a possession factor to access
   necessary keys.  This action may require one or more service request
   to a backend service such as the WSCA.

   This protocol is designed as a framework for such service exchanges
   based on two-factor user authentication that allows the client and
   server to use any suitable mechanism for user authentication.

Santesson & Altmann     Expires 17 December 2026                [Page 3]
Internet-Draft                    R2PS                         June 2026

2.  Conventions and Definitions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

2.1.  Definitions

   The following terms have a defined meaning in this document:

   *  context: A security scope, cryptographically separated from other
      contexts by a unique set of context keys held at the client and
      the server.  The client-side context keys also represent the
      user's possession factor in two-factor protection modes.

   *  context key: A public/private key pair.  Each context is bound to
      one context key-agreement key and one context signing key, at both
      the server and the client.

   *  protection mode: This document defines two protection modes, one-
      factor protection (1FA) and two-factor protection (2FA). 1FA
      provides protection based on one user factor (the possession
      factor); 2FA provides protection based on two user factors (the
      possession factor together with a knowledge or biometric factor).

   *  session: A scope bound to a session key derived from two-factor
      authentication of the user, which requires the user to be present
      to provide a knowledge or biometric factor.  A session MAY be
      bound to a specific task.

   *  service type: A defined message type, with its own data structure,
      that can be exchanged using R2PS.

   *  task: Defines what a session is to achieve before it is
      terminated.  A task MAY be negotiated when creating a session and
      lets the client and the server terminate the session as soon as
      the task completes or fails, even before the session timeout is
      reached.

   *  first factor: The user's possession factor, which corresponds to a
      set of client context keys.

   *  second factor: The user's knowledge factor or biometric factor.

Santesson & Altmann     Expires 17 December 2026                [Page 4]
Internet-Draft                    R2PS                         June 2026

3.  Basic structure

   R2PS is a stateless request/response protocol.  Each request and each
   response is carried as a JSON Web Encryption (JWE) object [RFC7516]
   in compact serialization, providing end-to-end encryption between the
   client and the backend server that provides the service.  The JWE
   payload is a JSON Web Signature (JWS) object [RFC7515] in compact
   serialization, signed by the sender, that carries a request or
   response structure common to all exchanges together with service data
   identified by a service type.

   The backend server determines the protection mode from the JWE
   protected header.  R2PS defines two protection modes: 1FA,
   authenticated by a possession factor (the device key); and 2FA,
   authenticated additionally by the user's second factor.  The service
   type identifier carried in the inner JWS determines the structure of
   the service data, the operations performed, and the required
   protection mode.

   +-----------------------------------------------------------------+
   | JWE  (compact serialization)                                    |
   |   protected header: typ (r2ps-1fa | r2ps-2fa), alg, enc         |
   |                                                                 |
   | +-----------------------------------------------------------+   |
   | | JWS  (compact serialization)                              |   |
   | |   protected header:                                       |   |
   | |     typ (r2ps-request+jwt | r2ps-response+jwt),           |   |
   | |     alg=ES256, kid                                        |   |
   | |                                                           |   |
   | |   payload:                                                |   |
   | |     ver, nonce, iat       (common to all exchanges)       |   |
   | |     type, jwe_hash        (requests only)                 |   |
   | |     data { service-specific request or response }         |   |
   | +-----------------------------------------------------------+   |
   +-----------------------------------------------------------------+

              Figure 1: R2PS outer JWE and inner JWS structure

   The protocol allows the client and server to agree on any number of
   service type identifiers, each having its own defined data structure
   for request and response data.

   While the base protocol structure has no state, the inner service
   data structure may be used in a process that requires state.  This is
   defined by each service type.

   This specification defines a set of default service types.  Other
   service types MAY be defined by other documents.

Santesson & Altmann     Expires 17 December 2026                [Page 5]
Internet-Draft                    R2PS                         June 2026

3.1.  Bootstrapping the protocol

   The protocol is designed to serve the need for service exchange with
   many different server resources, each cryptographically separated
   from the others.

   This is achieved by means of separate "context keys" at the client
   and server.  A security context is a named scope identified by a
   context id, under which a set of service types is offered with a
   common security and key-management policy.  Each security context has
   its own context key set (a signing key and a key-agreement key) and
   is cryptographically separated from all other security contexts.

   The manner through which the client and server share trusted context
   keys is out of scope of this specification.

   Initial registration of a user's 2nd factor may need authorization
   data that was provided to the user by out-of-band means.  This MAY be
   a one-time password or other authorization data that asserts that the
   user factor is provided by the intended user.  The protocol
   facilitates exchange of such authorization data in the registration
   process, but the composition of this data and the means for providing
   this data to the user is out of scope for this specification.

3.2.  Protection modes and sessions

   The main purpose of this protocol is to exchange service data that is
   protected and authenticated under two user factors: a possession
   factor (the device key) and a user-bound factor (knowledge or
   biometric).  Establishing the user-bound factor must complete before
   a two-factor protected exchange can take place, so the protocol also
   provides a one-factor protection mode, protected by the possession
   factor alone.

   The one-factor protection mode MAY be used:

   *  to register or verify a user's knowledge or biometric factor; and

   *  for exchanges with lower protection requirements that are
      permitted without the user presenting a second factor.

Santesson & Altmann     Expires 17 December 2026                [Page 6]
Internet-Draft                    R2PS                         June 2026

   The two-factor protection mode is used within a session bound to the
   user having presented a second factor, as typically required when the
   user signs a transaction or presents an identity.  A session MAY be
   bound to a task, which in turn MAY bind to a sequence of service
   exchanges, each identified by a service type.  This session lets both
   client and server track the task's progress within the session and
   terminate the session as soon as the task completes or the session
   times out.

4.  R2PS Protocol Components

4.1.  Outer JWE object

   The outer JWE object [RFC7516] provides end-to-end encryption of the
   exchanged service data.  It is used in one of two protection modes:

   *  1FA, where the Content Encryption Key (CEK) is derived from a
      static recipient key and an ephemeral sender key.

   *  2FA, where the session key derived from authentication of the
      user's two factors is used directly as the CEK.  This mode
      provides forward secrecy.

   The recipient determines the mode from the typ parameter of the JWE
   protected header.  The JWE protected header is the only header used;
   per-recipient and unprotected headers are not used.

   This document defines the following typ parameters:

   *  r2ps-1fa : identifies the 1FA mode defined in this document.

   *  r2ps-2fa : identifies the 2FA mode defined in this document.

   Deployments MAY define and agree on alternative protection modes
   identified by other typ parameter values.

4.1.1.  1FA mode

   In 1FA mode the CEK is derived using ECDH-ES [RFC7518].  The JWE
   protected header MUST contain:

   *  typ: MUST be r2ps-1fa.

   *  alg: MUST be ECDH-ES.

   *  enc: MUST be A256GCM.

   *  epk: the sender's ephemeral public key.

Santesson & Altmann     Expires 17 December 2026                [Page 7]
Internet-Draft                    R2PS                         June 2026

   *  kid: identifies the recipient's static key-agreement key: the
      server's static ECDH key in a request, the client's agreement key
      (CAK) in a response.

   *  apu: MUST be the client_id in a request and the context in a
      response.

   *  apv: MUST be the context in a request and the client_id in a
      response.

   *  cty: MUST be JWT.

   where context identifies the security context and client_id is the
   client's identifier within that context.

   The resulting compact serialization is
   <header>..<iv>.<ciphertext>.<tag>; the encrypted-key field is empty,
   as ECDH-ES uses direct key agreement.  The sender MUST destroy the
   ephemeral private key and the CEK as soon as the JWE has been
   constructed.

4.1.2.  2FA mode

   In 2FA mode the session key, derived from authentication of the
   user's two factors, is used directly as the CEK (dir, direct
   encryption).  The JWE protected header MUST contain:

   *  typ: MUST be r2ps-2fa.

   *  alg: MUST be dir.

   *  enc: MUST be A256GCM.

   *  kid: the 2FA session identifier.

   *  cty: MUST be JWT.

   The IV MUST be a freshly generated 96-bit random value for each
   message.  The resulting compact serialization is
   <header>..<iv>.<ciphertext>.<tag>; the encrypted-key field is empty,
   as direct encryption uses the session key as the CEK.

   The 2FA session identifier identifies the 2FA session key that is
   negotiated during authentication of the users 2 factors.  The 2FA
   session key is ephemeral and MUST be destroyed after use to preserve
   forward secrecy.

Santesson & Altmann     Expires 17 December 2026                [Page 8]
Internet-Draft                    R2PS                         June 2026

4.2.  Inner JWS object

   The inner JWS object [RFC7515] is signed by the sender with its
   context signing key and carries the request or response structure
   common to all service types.  Variant content specific to a service
   type resides entirely within the data member of the payload.

   The JWS protected header MUST contain at least:

   *  alg: SHOULD be ES256.

   *  kid: identifies the signing key.  In a request it MUST identify
      the client's Client Signing Key (CSK) for the security context;
      implementations SHOULD use the JWK Thumbprint [RFC7638] of the CSK
      public key.  In a response it MUST identify the server's Server
      Signing Key (SSK).

   *  typ: MUST be r2ps-request+jwt in a request and r2ps-response+jwt
      in a response.

   The JWS payload is a JSON object.  Members that hold a binary value
   are encoded as base64 strings as defined in [RFC4648], Section 4 (the
   standard base64 alphabet, with padding).  The following members are
   common to all exchanges and MUST be present in both requests and
   responses:

   *  ver (string): the protocol version; "1.0" for this document.

   *  nonce (string): a base64-encoded random byte array carrying at
      least 16 bytes of entropy.  The client generates it for each
      request, and the server echoes it unchanged in the corresponding
      response.

   *  iat (integer): the message creation time as a Unix timestamp.  The
      server MUST enforce a maximum iat age and MUST reject a duplicate
      nonce received within that window.  Freshness windows and the
      state required for replay protection are deployment-defined.

   *  data (object): the service-specific payload, whose structure is
      determined by the service type.

4.2.1.  Request data

   In addition to the common members, a request payload MUST include the
   following, which MUST NOT appear in a response:

Santesson & Altmann     Expires 17 December 2026                [Page 9]
Internet-Draft                    R2PS                         June 2026

   *  type (string): the service type identifier.  It determines the
      structure of data, the operations performed, and the required
      protection mode (1FA or 2FA).

   *  jwe_hash (string): a digest binding this JWS to the JWE that
      encrypts it, constructed as defined below.

   The jwe_hash binds the signed payload to the JWE protected header
   that carries it, preventing surreptitious forwarding (a recipient re-
   encrypting the inner JWS under a different JWE).  It is computed over
   the JWE Protected Header exactly as transmitted in compact
   serialization.  This is defined in JWE [RFC7516] as
   BASE64URL(UTF8(JWE Protected Header)), which is the octets preceding
   the first period in compact serialization.  The sender computes the
   SHA-256 digest of the ASCII octets of that encoded header and carries
   the resulting 32-octet digest in the jwe_hash member, encoded as a
   base64 string.

   jwe_hash = SHA-256( ASCII( BASE64URL(UTF8(JWE Protected Header)) ) )

   The recipient MUST recompute jwe_hash over the received encoded JWE
   Protected Header and MUST reject the message on mismatch.

4.2.2.  Response data

4.2.2.1.  Success Response

   This response SHOULD be used on successful service completion, or
   where error handling is provided as part of service data in the
   response.

   The response payload includes the common members only (ver, nonce,
   iat and data).  The nonce MUST equal the nonce of the request being
   answered.  The response data object carries the service-specific
   response members defined by the service type, for example the p_data
   parameter.

4.2.2.2.  Error response

   If a server fails to process a request and return a normal response,
   e.g. due to a missing or invalid parameter, decryption error or
   signature validation error, etc, it SHOULD return a suitable error
   response.

   When a HTTP API is used for service exchange, the server SHALL
   provide problem details as defined in [RFC9457].

   The following response codes are RECOMMENDED for use in a HTTP API:

Santesson & Altmann     Expires 17 December 2026               [Page 10]
Internet-Draft                    R2PS                         June 2026

             +==========================+====================+
             | Response code            | HTTP response code |
             +==========================+====================+
             | ILLEGAL_REQUEST_DATA     | 400                |
             +--------------------------+--------------------+
             | UNAUTHORIZED             | 401                |
             +--------------------------+--------------------+
             | ACCESS_DENIED            | 403                |
             +--------------------------+--------------------+
             | ILLEGAL_STATE            | 409                |
             +--------------------------+--------------------+
             | UNSUPPORTED_REQUEST_TYPE | 415                |
             +--------------------------+--------------------+
             | SERVER_ERROR             | 500                |
             +--------------------------+--------------------+
             | TRY_LATER                | 503                |
             +--------------------------+--------------------+

                                  Table 1

4.3.  Second factor establishment and session creation

   This section defines common service types for registration, update
   and authentication of a user's second factor to support session
   creation based on the user's two factors.

   The output of session creation is:

   *  session key: a key suitable for direct use as the CEK in the 2FA
      protection mode in use; its length and parameters are determined
      by that mode's encryption algorithm.  This key MUST be uniformly
      distributed, MUST be unique per session, and MUST provide forward
      secrecy.

   *  session identifier: an identifier of the session key and the
      properties bound to it.

   *  context: the context under which the session is exchanged.

   *  task: an optional identifier of the task to be performed within
      the session.

   *  session expiration: the time at which the session expires,
      regardless of whether its task has completed.

Santesson & Altmann     Expires 17 December 2026               [Page 11]
Internet-Draft                    R2PS                         June 2026

   A second-factor authentication mechanism that already outputs a key
   meeting these requirements (for example, the session key produced by
   OPAQUE [RFC9807]) MAY use that key directly as the session key.
   Otherwise, the mechanism MUST derive a suitable key from its output,
   for example using HKDF [RFC5869].

4.3.1.  Request parameters

   These request parameters are defined for use in the defined service
   types for second factor establishment and session creation.

   *  protocol : (*string*) - Identifier of the protocol used for two-
      factor authentication.  This parameter defines the content of the
      p_data parameter in both the request and the response.

   *  state : (*string*) - Identifier of the state of the protocol
      exchange

   *  authorization : (*byte array*) - Authorization data for
      registration of a new second factor

   *  authorization_type : (*string*) - The type of authorization data
      provided in the authorization parameter

   *  task : (*string*) - The requested session task used to determine
      the set of operations that are suitable for a created session

   *  session_duration : (*integer*) - The requested max duration of the
      created session in seconds

   *  p_data : (defined by protocol) - The protocol-specific request
      data.  Its content is defined by the selected protocol and the
      current state, and MAY be a string, an object, or null.

4.3.2.  Response parameters

   These response parameters are defined for use in the defined service
   types for second factor establishment and session creation.

   *  success : (*boolean*) - Indicates whether the server accepted and
      successfully processed the exchange.  This member MUST be present
      in every response.

   *  p_data : (defined by protocol) - The protocol-specific response
      data for the current protocol and state.  Its content is defined
      by the selected protocol and MAY be a string, an object, or null.

Santesson & Altmann     Expires 17 December 2026               [Page 12]
Internet-Draft                    R2PS                         June 2026

   *  session_id : (*string*) - The session identifier of a created
      session

   *  task : (*string*) - Confirming the session task set in the session
      request

   *  session_expiration_time : (*integer*) - The latest time this
      session will end expressed as seconds since epoch

4.3.3.  Member presence

   Each service type specifies, in the tables below, which members
   appear in its requests and responses.  Presence depends on the
   member, on the position of the exchange within the protocol's
   sequence, and, for responses, on whether the server reports success.

   The exchange position is one of:

   *  first: the first exchange of the protocol.

   *  last: the concluding exchange of the protocol.

   *  all: every exchange.

   *  protocol : presence is defined by the protocol.

   A protocol that completes in a single exchange treats that exchange
   as both the first and the last.

   The presence rule is one of:

   *  required: the member MUST be present.

   *  optional: the member MAY be present.

   *  required on success: the member MUST be present when success is
      true, and MUST be absent otherwise.

   *  required if requested: the member MUST be present when the
      corresponding member was present in the request.

   A response with success set to false contains only the success
   member; the presence rules in the tables below describe the success
   path.

Santesson & Altmann     Expires 17 December 2026               [Page 13]
Internet-Draft                    R2PS                         June 2026

4.3.4.  Service types

   The following service types are defined in this section

   *  create_session: Authenticates the user's two factors and creates a
      session

   *  2fa_registration: Register a user's second factor

   *  2fa_update: Update a user's second factor

   These service types are designed to allow any suitable protocol for
   authentication, registration and updates of the user's second factor.
   These service types have defined data structures as defined below.

4.3.4.1.  create_session Service type

   This service type is used to create a session based on authentication
   of the user's two factors.  This service type MUST be exchanged using
   1FA protection mode.

   The create_session request contains:

                +==================+==========+==========+
                | Member           | Exchange | Presence |
                +==================+==========+==========+
                | protocol         | all      | required |
                +------------------+----------+----------+
                | p_data           | all      | required |
                +------------------+----------+----------+
                | state            | all      | required |
                +------------------+----------+----------+
                | session_duration | first    | optional |
                +------------------+----------+----------+
                | task             | first    | optional |
                +------------------+----------+----------+

                                 Table 2

   If session_duration is not specified, the server MUST use a default
   value.

   The create_session response contains:

Santesson & Altmann     Expires 17 December 2026               [Page 14]
Internet-Draft                    R2PS                         June 2026

      +=========================+==========+=======================+
      | Member                  | Exchange | Presence              |
      +=========================+==========+=======================+
      | success                 | all      | required              |
      +-------------------------+----------+-----------------------+
      | session_id              | all      | required on success   |
      +-------------------------+----------+-----------------------+
      | p_data                  | all      | required on success   |
      +-------------------------+----------+-----------------------+
      | task                    | last     | required if requested |
      +-------------------------+----------+-----------------------+
      | session_expiration_time | last     | required on success   |
      +-------------------------+----------+-----------------------+

                                 Table 3

   The session_id identifies the session this exchange is bound to and
   attempts to create.  It MUST be unique within the context and is
   returned in every response of the exchange.  A returned session_id is
   NOT an indication that the session has been created; that is
   determined by success and the protocol data in the concluding
   response.

4.3.4.2.  2fa_registration Service type

   This service type is used to register a user's second factor.  This
   service type MUST be exchanged using 1FA protection mode.

   The 2fa_registration request contains:

               +====================+==========+==========+
               | Member             | Exchange | Presence |
               +====================+==========+==========+
               | protocol           | all      | required |
               +--------------------+----------+----------+
               | p_data             | all      | required |
               +--------------------+----------+----------+
               | state              | all      | required |
               +--------------------+----------+----------+
               | authorization      | protocol | required |
               +--------------------+----------+----------+
               | authorization_type | protocol | optional |
               +--------------------+----------+----------+

                                 Table 4

Santesson & Altmann     Expires 17 December 2026               [Page 15]
Internet-Draft                    R2PS                         June 2026

   The authorization member provides out-of-band authorization that the
   user is authorized to register a second factor.  Its content is
   defined by authorization_type.

   NOTE: authorization is carried in the last exchange rather than the
   first so that protocols with stateless registration are supported
   uniformly.  OPAQUE, for example, processes the evaluate (first)
   exchange without retaining server state; requiring authorization in
   the first exchange would force the server to keep state across the
   exchange.  Placing it in the last exchange, where the server commits
   the registration, keeps registration stateless-friendly for all
   protocols.

   This specification defines the following authorization_type values:

   *  otp : The authorization parameter is a one-time password given to
      the user by out-of-band means.

   The 2fa_registration response contains:

               +=========+==========+=====================+
               | Member  | Exchange | Presence            |
               +=========+==========+=====================+
               | success | all      | required            |
               +---------+----------+---------------------+
               | p_data  | all      | required on success |
               +---------+----------+---------------------+

                                 Table 5

4.3.4.3.  2fa_update Service type

   This service type is used to update the user's second factor under
   the protection of the current 2 factors.  This service type MUST be
   exchanged using 2FA protection mode.  This means that a session must
   already exist that is bound to the user's current 2 factors.  This
   session MUST be bound to a task with the value 2fa_update which
   allows one exchange of the 2fa_update service type under the 2FA
   protection mode.  This ensures that the user MUST present its second
   factor as part of the process to update this factor.

   The 2fa_update request contains:

Santesson & Altmann     Expires 17 December 2026               [Page 16]
Internet-Draft                    R2PS                         June 2026

                    +==========+==========+==========+
                    | Member   | Exchange | Presence |
                    +==========+==========+==========+
                    | protocol | all      | required |
                    +----------+----------+----------+
                    | p_data   | all      | required |
                    +----------+----------+----------+
                    | state    | all      | required |
                    +----------+----------+----------+

                                 Table 6

   The 2fa_update response contains:

               +=========+==========+=====================+
               | Member  | Exchange | Presence            |
               +=========+==========+=====================+
               | success | all      | required            |
               +---------+----------+---------------------+
               | p_data  | all      | required on success |
               +---------+----------+---------------------+

                                 Table 7

4.3.5.  Defined authentication protocols

   This specification defines the following authentication protocols:

   *  opaque: Uses OPAQUE [RFC9807] to send a password knowledge proof
      to the server.  This SHOULD be used for server-side password
      checks.

   *  fido2: Proves the second factor with a roaming WebAuthn
      authenticator.  This mode SHOULD be used for device-attested flows
      using a FIDO2 Authenticator.

4.3.5.1.  OPAQUE protocol

   Use of the OPAQUE protocol option is identified by the protocol
   identifier opaque.

   OPAQUE needs two roundtrips to complete registration or
   authentication and uses the following defined state identifiers in
   the context of this protocol:

   *  evaluate - Identifies the initial server evaluation state where
      the server evaluates the blinded OPRF data.

Santesson & Altmann     Expires 17 December 2026               [Page 17]
Internet-Draft                    R2PS                         June 2026

   *  finalize - Identifies the final state where registration or
      authentication is finalized.

4.3.5.1.1.  create_session

   Protection mode MUST be 1FA.

   The following OPAQUE data is exchanged between the client and server:

     +==========+===========+========================================+
     | State    | Direction | p_data content                         |
     +==========+===========+========================================+
     | evaluate | Request   | AKE message 1 as Base64 encoded string |
     +----------+-----------+----------------------------------------+
     | evaluate | Response  | AKE message 2 as Base64 encoded string |
     +----------+-----------+----------------------------------------+
     | finalize | Request   | AKE message 3 as Base64 encoded string |
     +----------+-----------+----------------------------------------+
     | finalize | Response  | null                                   |
     +----------+-----------+----------------------------------------+

                                  Table 8

4.3.5.1.2.  2fa_registration

   Protection mode MUST be 1FA.

   Authorization data MUST be present in the finalize state of the
   protocol and MUST NOT be provided in the evaluate state.

   The following OPAQUE data is exchanged between the client and server:

            +==========+===========+==========================+
            | State    | Direction | p_data content           |
            +==========+===========+==========================+
            | evaluate | Request   | Registration request as  |
            |          |           | Base64 encoded string    |
            +----------+-----------+--------------------------+
            | evaluate | Response  | Registration response as |
            |          |           | Base64 encoded string    |
            +----------+-----------+--------------------------+
            | finalize | Request   | Registration record as   |
            |          |           | Base64 encoded string    |
            +----------+-----------+--------------------------+
            | finalize | Response  | null                     |
            +----------+-----------+--------------------------+

                                  Table 9

Santesson & Altmann     Expires 17 December 2026               [Page 18]
Internet-Draft                    R2PS                         June 2026

4.3.5.1.3.  2fa_update

   Protection mode MUST be 2FA.

   When OPAQUE is used in 2fa_update, the data exchanged between the
   client and server is the same as in 2fa_registration.  The only
   difference is that the exchange is sent in 2FA protection mode,
   protected by the previous second-factor session key, and therefore
   does not need to provide any authorization data.

4.3.5.2.  FIDO2 Authenticator protocol

   Use of the FIDO2 Authenticator protocol option is identified by the
   protocol identifier fido2.

   The second factor is established and verified locally by the user's
   FIDO2 authenticator.  The resulting device attestation is verified by
   the server.

   The mechanism relies on two complementary signatures: the JWS
   signature, which demonstrates possession, and a WebAuthn assertion
   carried inside data, which demonstrates user verification.

   Every exchange is signed as an ES256 JWS by the context signing key
   (CSK).  In a platform or smartphone deployment the CSK is the
   platform's registered signing key and signs the JWS directly.  In a
   roaming FIDO2 deployment the CSK is held by the FIDO2 authenticator,
   and the JWS signature is produced over the JWS signing input using
   the WebAuthn sign extension [WebAuthn-sign] (a raw signature over the
   supplied input).  Either way the result is an ordinary ES256 JWS.

   The second factor is demonstrated by a regular WebAuthn assertion
   whose authenticator data has the user-verification (UV) flag set.
   The server requests UV; the authenticator prompts for a PIN or
   biometric and sets the UV flag in the assertion.  The assertion is
   carried inside the p_data of a fido2 request.

   To complete the second-factor check the server MUST:

   1.  Verify the assertion signature under the CSK registered for the
       context.

   2.  Verify that the UV flag is set.

   There is no server-side password-verification object for this
   mechanism; registration enrols the WebAuthn credential itself.

Santesson & Altmann     Expires 17 December 2026               [Page 19]
Internet-Draft                    R2PS                         June 2026

   The following defined state identifiers are used in the context of
   this protocol:

   *  challenge - Establish a challenge for the second factor
      authentication.

   *  finalize - Provide a WebAuthn signature that proves the second
      factor.

   The p_data content for each state is defined per service type below.
   The session-key exchange used by create_session (the ephemeral keys
   and the session-key derivation) is out of scope of this revision and
   is defined separately.

4.3.5.2.1.  create_session

   Protection mode MUST be 1FA.

   FIDO2 authentication requires two round-trips; the first to establish
   a challenge, the second to create a WebAuthn signature that proves
   the second factor and to negotiate the 2FA session.

   The following data is exchanged between the client and server:

           +===========+===========+==========================+
           | State     | Direction | p_data content           |
           +===========+===========+==========================+
           | challenge | Request   | Authentication challenge |
           |           |           | request as JSON object   |
           +-----------+-----------+--------------------------+
           | challenge | Response  | Authentication challenge |
           |           |           | response as JSON object  |
           +-----------+-----------+--------------------------+
           | finalize  | Request   | Authentication finalize  |
           |           |           | request as JSON object   |
           +-----------+-----------+--------------------------+
           | finalize  | Response  | Authentication finalize  |
           |           |           | response as JSON object  |
           +-----------+-----------+--------------------------+

                                 Table 10

   The challenge request p_data is null.

   The challenge response p_data:

Santesson & Altmann     Expires 17 December 2026               [Page 20]
Internet-Draft                    R2PS                         June 2026

   {
     "challenge": "<base64 challenge, at least 16 bytes>",
     "token": "<opaque server state token>",
     "user_verification": "required"
   }

   *  challenge: the WebAuthn challenge to be signed in the assertion.

   *  token: opaque server state bound to the challenge, echoed by the
      client in the finalize request so the server need not retain
      challenge state.

   *  user_verification: the WebAuthn user-verification requirement;
      MUST be required.

   The token is an authenticated encryption of the server's challenge
   state under a key known only to the server.  The server MUST encrypt
   at least the challenge, the iat, the client_id, and the context, so
   that the server can, on finalize, recover the issued challenge and
   confirm it was issued to the same client and context.  The encryption
   algorithm is the server's choice and has no interoperability impact,
   since the token is produced and consumed only by the server; A256GCM
   is RECOMMENDED.  The server MUST ensure the token cannot be replayed
   beyond a single authentication, for example by enforcing the iat
   freshness window and unique IVs.

   The finalize request p_data:

   {
     "token": "<token from the challenge response>",
     "assertion": {
       "client_epub : "<base64 client ephemeral public key for session derivation>",
       "credential_id": "<base64 credential id>",
       "authenticator_data": "<base64 authenticatorData>",
       "client_data": "<base64 clientDataJSON>",
       "signature": "<base64 signature>"
     }
   }

   The finalize response p_data:

   {
     "server_epub : "<base64 server ephemeral public key for session derivation>",
   }

   Both sides establish the negotiated 2FA session key as follows:

Santesson & Altmann     Expires 17 December 2026               [Page 21]
Internet-Draft                    R2PS                         June 2026

   1.  Compute ikm = ECDH(own ephemeral private key, peer ephemeral
       public key).

   2.  Derive the 2FA session key K = HKDF(ikm, salt, info, L) where
       salt is message nonce for the finalize round, info is the DST
       concatenated with a transcript-binding hash, and L is 32 bytes.
       The DST MUST be r2ps-2fa_authentication-fido2.  The transcript
       binding hash MUST be SHA256(2fa_mode || client_epub ||
       server_epub || task || fido2 assertion signature).

4.3.5.2.2.  2fa_registration

   Protection mode MUST be 1FA.

   Authorization data MUST be present in the finalize state of the
   protocol and MAY be present also in the challenge state.

   There is no server-side verification object to register for the fido2
   mechanism.  Registration instead enrolls the WebAuthn UV-capable
   credential and binds it to the client_id for that security context.
   The request carries the result of the WebAuthn credential-creation
   ceremony (the attestation object and client data); the server
   validates it according to [WebAuthn] and stores the credential public
   key.  The authorization field authorizes the enrolment, as for the
   other mechanisms.

   The flow is double-round.  The client first requests a challenge.  It
   then runs the WebAuthn credential-creation ceremony using the
   challenge it received in round 1.

   The following data is exchanged between the client and server:

            +===========+===========+=========================+
            | State     | Direction | p_data content          |
            +===========+===========+=========================+
            | challenge | Request   | Registration challenge  |
            |           |           | request as JSON object  |
            +-----------+-----------+-------------------------+
            | challenge | Response  | Registration challenge  |
            |           |           | response as JSON object |
            +-----------+-----------+-------------------------+
            | finalize  | Request   | Registration finalize   |
            |           |           | request as JSON object  |
            +-----------+-----------+-------------------------+
            | finalize  | Response  | null                    |
            +-----------+-----------+-------------------------+

                                  Table 11

Santesson & Altmann     Expires 17 December 2026               [Page 22]
Internet-Draft                    R2PS                         June 2026

   The challenge request p_data MAY carry client capabilities or
   preferences; otherwise it is null.

   Note: Consider if this specification should define a structure for
   client capabilities and preferences.

   The challenge response p_data:

   {
     "challenge": "<base64 challenge, at least 16 bytes>"
   }

   The finalize request p_data:

   {
     "credential_id": "<base64 credential id>",
     "attestation_object": "<base64 attestationObject>",
     "client_data": "<base64 clientDataJSON>"
   }

   On receiving the finalize request, the server MUST validate the
   attestation according to [WebAuthn].  Specifically, the server MUST:

   1.  Parse client_data (the clientDataJSON) and verify that its type
       field is exactly "webauthn.create".

   2.  Verify that the challenge in client_data matches the challenge
       issued in the challenge response.

   3.  Verify that the origin in client_data matches the Relying Party's
       expected origin.

   4.  Decode attestation_object and verify that the rpIdHash in the
       authenticator data is the SHA-256 hash of the Relying Party ID.

   5.  Verify that the User Present (UP) flag in the authenticator data
       is set.

   6.  Verify that the User Verified (UV) flag in the authenticator data
       is set.

   7.  Verify the attestation statement's signature using the
       verification procedure for the attestation format.

Santesson & Altmann     Expires 17 December 2026               [Page 23]
Internet-Draft                    R2PS                         June 2026

   On success, the server extracts the credential identifier and
   credential public key from the attested credential data, and binds
   the credential_id and public key to the client_id in that security
   context.  This credential is the one from which UV assertions are
   required in subsequent create_session exchanges.

   On success, the finalize response p_data is null.

4.3.5.2.3.  2fa_update

   When the FIDO2 Authenticator protocol is used in 2fa_update, the data
   exchanged between the client and server is the same as in
   2fa_registration.  The only difference is that the exchange is sent
   in 2FA protection mode, protected by the previous second-factor
   session key, and therefore does not need to provide any authorization
   data.

5.  Hardening of knowledge factors

   TBD - Separately provide recommendations on PIN/Password hardening
   and when to use it

6.  Definition of service types

   TBD - provide guidance on definition of new service types

7.  Security Considerations

   Security considerations goes here

   Note: write about the importance to provide a new random IV for every
   JWE

8.  IANA Considerations

   IANA considerations goes here

   Determine registration of typ parameter values

   *  r2ps-request+jwt

   *  r2ps-response+jwt

   *  r2ps-1fa

   *  r2ps-2fa

9.  Normative References

Santesson & Altmann     Expires 17 December 2026               [Page 24]
Internet-Draft                    R2PS                         June 2026

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
              Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
              <https://www.rfc-editor.org/rfc/rfc4648>.

   [RFC5869]  Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
              Key Derivation Function (HKDF)", RFC 5869,
              DOI 10.17487/RFC5869, May 2010,
              <https://www.rfc-editor.org/rfc/rfc5869>.

   [RFC7515]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web
              Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
              2015, <https://www.rfc-editor.org/rfc/rfc7515>.

   [RFC7516]  Jones, M. and J. Hildebrand, "JSON Web Encryption (JWE)",
              RFC 7516, DOI 10.17487/RFC7516, May 2015,
              <https://www.rfc-editor.org/rfc/rfc7516>.

   [RFC7518]  Jones, M., "JSON Web Algorithms (JWA)", RFC 7518,
              DOI 10.17487/RFC7518, May 2015,
              <https://www.rfc-editor.org/rfc/rfc7518>.

   [RFC7638]  Jones, M. and N. Sakimura, "JSON Web Key (JWK)
              Thumbprint", RFC 7638, DOI 10.17487/RFC7638, September
              2015, <https://www.rfc-editor.org/rfc/rfc7638>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC9457]  Nottingham, M., Wilde, E., and S. Dalal, "Problem Details
              for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, July 2023,
              <https://www.rfc-editor.org/rfc/rfc9457>.

   [RFC9807]  Bourdrez, D., Krawczyk, H., Lewi, K., and C. A. Wood, "The
              OPAQUE Augmented Password-Authenticated Key Exchange
              (aPAKE) Protocol", RFC 9807, DOI 10.17487/RFC9807, July
              2025, <https://www.rfc-editor.org/rfc/rfc9807>.

Acknowledgments

   TODO acknowledge.

Santesson & Altmann     Expires 17 December 2026               [Page 25]
Internet-Draft                    R2PS                         June 2026

Authors' Addresses

   Stefan Santesson
   IDsec Solutions AB
   Forskningsbyn Ideon
   SE-223 70 Lund
   Sweden
   Email: sts@aaa-sec.com

   Peter Altmann
   SIROS Foundation
   Stockholm
   Sweden
   Email: peter.altman@siros.se

Santesson & Altmann     Expires 17 December 2026               [Page 26]