Skip to content

Concepts Service Providers

Sebastian Willenborg edited this page Nov 4, 2022 · 2 revisions

Service Providers

A service provider is an entity with a registered, verified and approved provider account through which it provides services to Wire users.

Contents

Accounts

Provider accounts are registered and administered through a dedicated website, developer.wire.com (TODO!). After initial registration and e-mail verification, provider accounts are subject to approval by Wire staff before they can be used to register services.

At this time, a provider account is protected only by a password. A password can be chosen on registration or be generated. The generated passwords are ensured to be sufficiently strong. For security reasons there is no self-service password reset for provider accounts at this time and loss of the password may lead to permanent loss of the provider account. It is thus advisable to not only use a strong password but also to write it down and keep it in a reasonably safe place.

Additionally, some administrative operations on registered services such as changing connection information of a service (public keys, API tokens or URLs) require password reauthentication.

Mechanisms for two-factor authentication or self-service password reset based on multiple security factors are being considered as future enhancements.

Services

A service provider manages a set of services that it wants to make available to Wire users. Upon creation, a service is initially disabled. As long as a service is disabled, it does not appear in the service directory and does not receive requests through the external service API from Wire. A service can be enabled when it is deemed ready for use. A service may be disabled and re-enabled at any time. It is recommended to disable a service if there is a planned downtime, in order to avoid failed delivery attempts from Wire which may lead to the service being penalised.

Wire does not store messages for a service that is unavailable, i.e. services are responsible for their availability. When a service is unavailable, users will no longer be able to request bots from that service in conversations and existing bots will naturally not receive messages.

An important consequence in combination with end-to-end encryption is that a bot may run into decryption errors due to too many skipped messages after a prolonged period of unavailability. When using the proteus / cryptobox libraries developed by Wire, these manifest as errors of the form TOO_DISTANT_FUTURE. To recover from these errors, a bot needs to re-initialise the affected session, followed by sending a message to the peer, to have it update its session as well. If the long-term identity key of the bot does not change, that recovery will be transparent (i.e. without alerting the user) even in verified conversations.

Authentication

Wire shares a secret bearer token with each registered service, which it uses to authenticate outbound requests towards a service. Conversely, the service itself communicates with the Wire API through making inbound requests in the context of individual bots, where each bot is assigned a secret bearer token bound to that specific bot and the conversation the bot is created in. These tokens are referred to as "bot tokens". Bot tokens do not expire but they are implicitly invalidated when the associated bot is removed from the conversation.

Bots

When a user adds a service to a conversation, the service (in cooperation with the Wire backend) instantiates a bot in the conversation (see the lifecycle). A bot is a specific type of constrained Wire user that can be identified as belonging to a service. It is the interface between a service and the users in a conversation, i.e. the service talks to the users in a conversation through a bot and vice versa.

A single service may have multiple bots in the same conversation, if requested by the user and if the service allows it, i.e. if it does not respond with an appropriate error when receiving a bot creation requests with a conversation ID for which the service already has an active bot.

State

At a minimum, a bot must maintain the following state in order to operate:

  • A cryptobox for encryption and decryption of messages.
  • The client ID assigned to the bot.
  • The API access token assigned to the bot.

Additionally it may wish to maintain the following state:

  • The bot's own ID.
  • The conversation ID.
  • User and client information of other members of the conversation, as far as it is accessible to the bot.
  • Auxiliary state to drive the bots behaviour.

It is recommended but not strictly necessary that all of that state needs to be made durable, in fact a service (or an individual bot) may choose to operate almost entirely in volatile RAM. When the state of a bot is no longer available and unless the bot removes itself, it will eventually be removed from the conversation, either by users who find it unresponsive or preferably automatically if the service responds with an appropriate error upon a message delivery attempt by Wire. The latter will yield a better user experience for users using the service and is thus the preferred practice if a service finds a bot to be "lost" or otherwise unavailable.

If a service wishes to maintain conversation state beyond the lifetime of a single bot in a conversation, it may do so based on the conversation ID given to the service in outbound bot creation and message requests.

Lifecycle

A bot is created and destroyed as it is added and removed from a conversation, respectively, i.e. it is scoped to a single conversation and its lifecycle bound to its membership in that conversation.

A bot is also automatically deleted and removed from a conversation when it is found to have been orphaned by the respective service during a message delivery attempt, which can happen in one of two ways:

  • The service itself has been deleted by the provider (or the entire provider account has been deleted).
  • The service indicated in an error response on an incoming message that it no longer knows (or wants to know) about a bot.

When a user adds a service to a conversation, Wire sends a bot creation request to the designated service. Upon success, Wire adds the bot to the conversation and the users and the bot can begin exchanging messages. While the bot is in the conversation, Wire forwards all messages in that conversation to the bot via a bot message request.

API

The external service API is the name for the collective set of APIs used for communication between Wire and services, in either direction. Details can be found here. To implement that API, a service must be able to accept all the outbound requests made by Wire and itself make inbound requests as necessary to implement the desired functionality.

TLS

TLS is mandatory for communication between Wire and services in both directions. Furthermore, in its role as a client connecting to a service in the context of the external service API, Wire supports only a small subset of modern TLS cipher suites based on RSA signatures, at least one of which must be supported by the TLS implementation used by the server(s) hosting a service:

  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_RSA_WITH_AES_128_GCM_SHA256

It is therefore necessary that the TLS certificate used by a service be based on RSA signatures. The minimum RSA key size supported by Wire is 2048 bits. Other signature schemes might be supported in the future. As a client of a service, Wire accepts regular CA certificates as well as self-signed certificates but mandates public key pinning. For that purpose, the PEM-encoded (RSA) public key that a service uses must be registered with that service on the Wire provider website. In order to facilitate key rotation, up to two public keys can be associated with a registered service at any time. Services are encouraged to use certificate or public key pinning in their capacity as a client of the Wire API as well.

Only TLS protocol versions 1.1 and 1.2 are supported by Wire when acting as a client of a service.

For more background information on certificate and public key pinning, please see Certificate and Public Key Pinning.

Note: The PEM-encoded RSA public keys used with registered services must contain a SubjectPublicKeyInfo structure as defined in RFC5280, not a PKCS#1 RSAPublicKey structure. The former should be the default when using the openssl commands mentioned in the FAQ. The header and footer of the PEM-encoded public key should read -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----, respectively, which is an indicator of the correct format. Other formats may be supported in the future.

Fingerprint Verification

In the context of end-to-end encryption, fingerprint verification is necessary to truly defend against MITM attacks. Since service providers only interact with Wire users through artificial users called "bots", an in-person fingerprint comparison, as it can be done between Wire users, is usually not possible. In order to establish a certain level of trust and rule out Wire and other parties as a potential MITM, a service provider can do the following:

  • Share a single, long-lived identity key pair (as provided by the proteus / cryptobox libraries or compatible implementations) across all bots of a single service (or even across all services of the provider).

  • Publish the public key fingerprint(s) on the provider website.

Wire users thus have the ability to verify the fingerprints of services and thereby of bots, by comparing them to those on the provider's website. The authenticity of the public key fingerprint(s) necessarily hinges on the authenticity of the provider website itself and its TLS certificate. It is thus advisable to obtain and use a certificate from a well-established and widely trusted CA for a provider website. Ultimately, Wire users can only trust bots and their services to the degree to which they trust the owning provider.

FAQ

Q: How do I extract a PEM-encoded RSA public key from my PEM-encoded RSA key pair for use with my service, using OpenSSL?

A: If the RSA key pair was created using openssl genrsa, you can use the following command:

openssl rsa -in key.pem -pubout -out pubkey.pem

The pubkey.pem can then be added to your service from within your Wire provider account.


Q: How do I generate a self-signed, PEM-encoded X509 certificate for use by my service, using OpenSSL?

A: First, generate an RSA keypair with a key size of at least 2048 bits, e.g.:

openssl genrsa -out key.pem 4096

Generate a certificate signing request (CSR), e.g.:

openssl req -new -key key.pem -out csr.pem

Sign the CSR using the RSA private key, e.g.:

openssl x509 -req -days 7300 -in csr.pem -signkey key.pem -out cert.pem

Install the private key and certificate on your server(s).

Finally, extract the RSA public key for use by Wire, e.g.:

openssl rsa -in key.pem -pubout -out pubkey.pem