Authentication Service (AS)

In this chapter, we detail the different functionalitites of the authentication service. See the subchapter on credentials for more details on the credential types referenced in this chapter.

For an overview over the security of the AS see here.

Configuration

The AS is configurable by use of the following configuration variables:

  • Anonymous token timeframe: The amount of time which each client has to wait until it can obtain new anonymous authentication tokens.
  • Default token allowance: The default amount of anonymous authentication tokens issued to each user in the anonymous token timeframe.
  • Maximal QS client record age: Maximal age of an inactive client entry.
    • Default: 90d
  • Maximal number of requested messages: Maximal number of messages that will be returned to a client requesting messages from a direct queue.

AS state

The AS generally keeps the following state

  • User entries: A database with one entry for each user account. Each entry is indexed by the user's user id and contains a number of sub-entries.
    • OPAQUE user record: The OPAQUE protocol artifact that allows the user to authenticate itself via its password in queries to the AS.
    • Encrypted user profile: The user's encrypted user profile.
    • Client entries: Sub entries for the users' clients. Indexed by the clients' client id.
      • Client credential: The credential of the client.
      • Token issuance records: A record of how many tokens were issued to the client.
      • Connection packages: Packages uploaded by the client and used in the connection establishment process.
      • Direct queue: A queue similar to the fan-out queues on the QS. Used to enqueue encrypted connection establishment packages.
        • Activity time: Timestamp indicating the last time a client has fetched messages from the queue.
        • Queue encryption key material: Key material to perform queue encryption.
          • Queue encryption key: HPKE public key of the queue owner
          • Encryption ratchet key: Symmetric key used to derive queue encryption keys.
        • Current sequence number: The current message sequence number.
        • Queued messages: A sequence of ciphertexts containing the messages in the queue. Each incoming message is encrypted and is assigned the current sequence number, after which the current sequence number is incremented.
  • Alias entries: Data not linked to user ids and instead indexed by Aliass.
    • Alias: The Alias associated with the direct queue.
    • Direct queue: A queue similar to the fan-out queues on the QS. Used to enqueue encrypted connection establishment packages.
      • Activity time: Timestamp indicating the last time a client has fetched messages from the queue.
      • Queue encryption key material: Key material to perform queue encryption.
        • Queue encryption key: HPKE public key of the queue owner
        • Encryption ratchet key: Symmetric key used to derive queue encryption keys.
      • Current sequence number: The current message sequence number.
      • Queued messages: A sequence of ciphertexts containing the messages in the queue. Each incoming message is encrypted and is assigned the current sequence number, after which the current sequence number is incremented.
    • Connection package payloads: Packages uploaded by the client and used in the connection establishment process.
  • Ephemeral OPAQUE DB: An in-memory database that stores user-name or client-id indexed entries
    • Client credential: Credential of the client that is being added to an existing user entry, or the initial client of a new user entry.
    • Optional OPAQUE state: OPAQUE server state, only present in case of the OPAQUE online AKE flow, i.e. if a client performs 2FA, but not during an OPAQUE setup.
  • AS credential key material: Credentials that can be retrieved by clients, as well as the private key material used by the AS to sign client CSRs.
  • AS OPAQUE key material: OPRF seed, server public key and server private key as required for the server to perform OPAQUE registration a login flows with clients.
  • AS Privacy Pass key material: server public key and server private key as required for the server to process privacy pass token requests.

Authentication

There are four modes of authentication for endpoints on the AS.

  • None: For endpoints that are meant to be publicly accessible, e.g. user account registration
  • Client Credential: A signature over a time stamp using the signature key in the calling client's ClientCredential. The request additionally contains the calling client's ClientCredential.
  • Client Password: An OPAQUE login flow.
  • Client 2FA: The same as Client, but additionally performing an OPAQUE login flow
  • Alias auth key: A signature over a time stamp using the alias auth key. The request additionally contains the calling client's alias.

If not explicitly mentioned, all endpoints additionally require the client to provide a valid privacy pass token as part of the request.

Initiate 2FA operation

The client has to query this endpoint before it can query an endpoint that requires Client 2FA authentication. Note that this endpoint is not meant to be used with endpoints that require Client Password authentication such as the client addition endpoint. Similarly, this endpoint is not meant to be used to set up 2FA (see here instead).

#![allow(unused)]
fn main() {
struct Initiate2FaAuthenticationParams {
  client_id: ClientId,
  opaque_ke1: OpaqueKe1,
}
}

The AS then performs the following steps:

#![allow(unused)]
fn main() {
struct Initiate2FaAuthenticationResponse {
  opaque_ke2: OpaqueKe2,
}
}

Authentication

  • Client Credential

Initialize user registration

The user registration functionality requires the user to perform an OPAQUE registration flow with the homeserver. Note, that the user's chosen user id is part of the client_csr.

#![allow(unused)]
fn main() {
struct InitUserRegistrationParams {
  client_csr: ClientCsr,
  opaque_registration_request: OpaqueRegistrationRequest,
}
}

The AS then performs the following steps:

#![allow(unused)]
fn main() {
struct InitUserRegistrationResponse {
  client_credential: ClientCredential,
  opaque_registration_response: OpaqueRegistrationResponse,
}
}

After receiving the response, the client must call the finish user registration endpoint.

Authentication

  • None

Finish user registration

This endpoint allows the user to finish its registration.

#![allow(unused)]
fn main() {
struct FinishUserRegistrationParams {
  user_id: UserId,
  queue_encryption_key: HpkePublicKey,
  initial_queue_ratchet_key: RatchetKey,
  connection_packages: Vec<ConnectionPackage>,
  opaque_registration_record: OpaqueRegistrationRecord,
}
}

The AS performs the following actions:

  • look up the initial client's ClientCredential in the ephemeral DB based on the user_id
  • authenticate the request using the signature key in the ClientCredential
  • check (again) if the user id already exists
  • create the user entry with the information given in the request
  • create the initial client entry
  • delete the entry in the ephemeral OPAQUE DB

Authentication

  • Client 2FA (the AS has to successfully complete the OPAQUE handshake and the client needs to provide Client Credential authentication using the signature key of the initial client)

Update user profile

Allows users to update their user profile. The profile is stored on the AS encrypted under the user's user profile encryption key.

#![allow(unused)]
fn main() {
struct UpdateUserProfileParams {
  user_id: UserId,
  new_user_profile: Vec<u8>,
}
}

The AS overwrites the existing user profile ciphertext with the new one.

Authentication

  • Client credential

Fetch user profile

Fetch the user profile of the user with the given user id.

#![allow(unused)]
fn main() {
struct UserProfileParams {
  user_id: UserId,
}
}

The AS responds with the encrypted user profile of the user with the given id.

#![allow(unused)]
fn main() {
struct UserProfileResponse {
  user_profile: Vec<u8>,
}
}

Authentication

  • None

Upload user id connection packages

Upload the given encrypted connection packages to the user entry with the given user id.

#![allow(unused)]
fn main() {
struct UploadUserIdPackages {
  user_id: UserId,
  connection_package_ctxt: Vec<Vec<u8>>,
}
}

Authentication

  • Client credential

Get user id connection package

Given a user id, get a connection package for the user's client.

#![allow(unused)]
fn main() {
struct UserClientsParams {
  user_id: UserId,
}
}

The AS returns the following information.

#![allow(unused)]
fn main() {
struct UserClientsResponse {
  connection_package: ConnectionPackage,
}
}

Authentication

  • None

User account deletion

Delete the user account with the given user id.

#![allow(unused)]
fn main() {
struct DeleteUserParams {
  user_id: UserId,
  opaque_ke3: OpaqueKe3,
}
}

The AS performs the following actions:

  • look up the OPAQUE server_state in the ephemeral DB based on the client_id
  • authenticate the request using the signature key in the ClientCredential
  • perform the ServerFinish step of the OPAQUE online AKE flow
  • delete the user entry
  • delete the entry in the ephemeral OPAQUE DB

Authentication

  • Client 2FA

Dequeue messages

Dequeue messages from a client's direct queue, starting with the message with the given sequence number.

#![allow(unused)]
fn main() {
struct DequeueMessagesParams {
  client_id: ClientId,
  sequence_number_start: u64,
  max_message_number: u64,
}
}

The AS deletes messages older than the given sequence number and returns messages starting with the given sequence number. The maximum number of messages returned this way is the smallest of the following values.

  • The number of messages remaining in the queue
  • The value of the max_message_number field in the request
  • The AS configured maximum number of returned messages

Authentication

  • Client

Enqueue message

Enqueue a message into a client's direct queue.

#![allow(unused)]
fn main() {
struct EnqueueMessageParams {
  client_id: ClientId,
  connection_establishment_ctxt: Vec<u8>,
}
}

Authentication

  • None

Get AS credentials

Get the currently valid AS credentials and AS intermediate credentials.

#![allow(unused)]
fn main() {
struct AsCredentialsResponse {
  as_credentials: Vec<AsCredentials>,
  as_intermediate_credentials: Vec<AsIntermediateCredential>,
  revoked_certs: Vec<Fingerprint>,
}
}

Authentication

  • None

Register alias

Register the given alias with the AS. After registration, the calling client can upload connection packages and dequeue messages from the queue associated with the alias.

#![allow(unused)]
fn main() {
struct RegisterAlias {
  alias: Alias
  alias_auth_key: AliasAuthkey,
}
}

The AS performs the following actions:

  • Check that the alias is not already registered
  • Create a alias entry with the given alias and auth key

Authentication

  • None

Delete alias

Delete the alias entry with the given alias, as well as the associated queue and connection packages.

#![allow(unused)]
fn main() {
struct DeleteAlias {
  alias: Alias,
}
}

Authentication

  • Alias auth key

Dequeue alias messages

Dequeue messages from a alias direct queue, starting with the message with the given sequence number.

#![allow(unused)]
fn main() {
struct DequeueAliasMessagesParams {
  alias: Alias,
  sequence_number_start: u64,
  max_message_number: u64,
}
}

The AS deletes messages older than the given sequence number and returns messages starting with the given sequence number. The maximum number of messages returned this way is the smallest of the following values.

  • The number of messages remaining in the queue
  • The value of the max_message_number field in the request
  • The AS configured maximum number of returned messages

Authentication

  • Alias auth key

Enqueue alias messages

Enqueue a message into a client's direct queue.

#![allow(unused)]
fn main() {
struct EnqueueAliasMessageParams {
  alias: Alias,
  connection_establishment_ctxt: Vec<u8>,
}
}

Authentication

  • None

Upload alias connection package payloads

Upload the given connection package payloads to the alias entry with the given alias. Note that in contrast to the similar functionality for user ids, this endpoint only takes the payloads of the connection packages as input.

#![allow(unused)]
fn main() {
struct UploadAliasPackages {
  alias: Alias,
  connection_package_ctxt: Vec<ConnectionPackagePayload>,
}
}

Authentication

  • Alias auth key

Get alias connection package

Given a alias, get a connection package for the user's client.

#![allow(unused)]
fn main() {
struct AliasClientsParams {
  alias: Alias,
}
}

The AS returns the following information.

#![allow(unused)]
fn main() {
struct AliasClientsResponse {
  connection_package: ConnectionPackagePayload,
}
}

Authentication

  • None

Token Issuance

This endpoints allows both local clients and clients of federated homeservers to retrieve Privacy Pass tokens which they can then redeem to interact with the local DS.

#![allow(unused)]
fn main() {
struct RequestToken {
  client_id: ClientId,
  token_request: TokenRequest,
}
}

TokenRequest represents a Privacy Pass token request. The server processes the request, checks if the client sufficient allowance left, reduces the allowance and responds with the tokens.

#![allow(unused)]
fn main() {
struct TokenResponse {
  tokens: Vec<Token>
}
}

Rate-limiting

Token issuance is the main way of rate-limiting queries to the endpoints of the DS of a homeserver, which means that the AS should rate-limit token issuance based on a per-client basis, essentially giving each client a certain allowance of tokens.

If the calling client is a federated client, rate-limiting should also occur on a per-homeserver (or per homeserver domain) basis to protect agains malicious or negligent homeservers that allow an attacker to register a large number of clients.

Authentication

For this endpoint, the AS also accepts authentication by federated clients. If the client_id in the client credential indicates that the client belongs to a federated homeserver, the AS looks up the authentication key material of that client's AS using the corresponding endpoint, or looks the key material up in its local cache. The AS then uses that key material to verify the query.

  • Client Credential