summaryrefslogtreecommitdiff
path: root/taler-challenger-manual.rst
diff options
context:
space:
mode:
Diffstat (limited to 'taler-challenger-manual.rst')
-rw-r--r--taler-challenger-manual.rst686
1 files changed, 686 insertions, 0 deletions
diff --git a/taler-challenger-manual.rst b/taler-challenger-manual.rst
new file mode 100644
index 00000000..f9d6a793
--- /dev/null
+++ b/taler-challenger-manual.rst
@@ -0,0 +1,686 @@
+..
+ This file is part of GNU TALER.
+
+ Copyright (C) 2023, 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Christian Grothoff
+ @author Florian Dold
+
+Challenger Operator Manual
+##########################
+
+.. contents:: Table of Contents
+ :depth: 2
+ :local:
+
+
+Introduction
+============
+
+About Challenger
+----------------
+
+Challenger is an OAuth 2.0-compatible address validation service.
+By redirecting a user-agent to a Challenger service a client can
+have Challenger validate that the user is able to receive messages
+at a particular address and obtain that address via the ``/info``
+endpoint.
+
+
+About this manual
+-----------------
+
+This manual targets system administrators who want to install,
+operate or integrate a challenger service. To report issues
+or learn about known limitations, please check our
+`bug tracker <https://bugs.taler.net>`__.
+
+
+Architecture overview
+---------------------
+
+The following picture gives an overview of the Challenger
+architecture and the main interactions:
+
+.. image:: images/challenger.png
+
+Here, the *resource owner* is a user that is in control
+of some *address* at a messaging service. This could be
+an e-mail account, a mobile phone number (for SMS), or
+a physical mail address (using the post office as the
+messaging service).
+
+The *resource owner* makes some request that requires
+some *client* to be in need of address validation. The
+*client* is registered with the Challenger OAuth 2.0
+service and first authorizes an address validation to
+be initiated. The client then redirects the resource
+owner to the Challenger service. In step (2), the resource
+owner submits the address that they claim to own.
+
+The Challenger service then creates a TAN code and
+submits it to the given address via a configurable
+*helper script* that is specific to the type of address
+being validated. When the resource owner submits the
+correct TAN code in step (6), they are given a token
+that they can provide to the client. Using this token
+the client can then finally obtain the now validated
+address in step (8).
+
+Address data, TAN codes and meta-data such as the number
+of failed attempts to submit a TAN code are recorded
+in a Postgres database by the Challenger service.
+
+.. _ChallengerInstallation:
+
+Installation
+============
+
+In this guide's shell-session fragments, the command prompt shows two pieces
+of information:
+
+* Who is performing the command
+ (``$user`` vs ``root``, and ending character ``$`` vs ``#``).
+
+
+Installing from source
+----------------------
+
+The following instructions will show how to install libgnunetutil and
+the core GNU Taler libraries from source.
+
+The package sources can be find in our
+`download directory <http://ftpmirror.gnu.org/taler/>`__.
+
+GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format.
+The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match.
+Exceptions to this general rule are documented in the release notes.
+For example, Challenger 1.3.0 should be compatible with Taler exchange 1.4.x
+as the MAJOR version matches. A MAJOR version of 0 indicates experimental
+development, and you are expected to always run all of the *latest* releases
+together (no compatibility guarantees).
+
+First, the following packages need to be installed before we can compile the
+backend:
+
+.. include:: frags/list-of-dependencies.rst
+
+.. include:: frags/installing-gnunet.rst
+
+.. include:: frags/install-before-check.rst
+
+There is no need to actually run a GNUnet peer or a Taler exchange to use
+Challenger -- all Challenger needs from GNUnet and Taler are a number of
+headers and libraries!
+
+.. include:: frags/installing-taler-exchange.rst
+
+
+.. include:: frags/installing-challenger.rst
+
+.. include:: frags/install-before-check.rst
+
+
+
+Installing the Challenger binary packages on Debian
+---------------------------------------------------
+
+.. include:: frags/installing-debian.rst
+
+To install the Challenger, you can now simply run:
+
+.. code-block:: shell-session
+
+ # apt install challenger
+
+Note that the package does not perform any configuration work except for
+setting up the various users and the systemd service scripts. You still must
+configure at least the database, HTTP reverse proxy (typically with TLS
+certificates) and the terms of service.
+
+Installing the GNU Taler binary packages on Trisquel
+----------------------------------------------------
+
+.. include:: frags/installing-trisquel.rst
+
+Installing the GNU Taler binary packages on Ubuntu
+--------------------------------------------------
+
+.. include:: frags/installing-ubuntu.rst
+
+To install the Taler exchange, you can now simply run:
+
+.. code-block:: shell-session
+
+ # apt install challenger
+
+Note that the package does not perform any configuration work except for
+setting up the various users and the systemd service scripts. You still must
+configure at least the database, HTTP reverse proxy (typically with TLS
+certificates), and the terms of service.
+
+
+Services, users, groups and file system hierarchy
+-------------------------------------------------
+
+The *challenger* package will use several system users
+to compartmentalize different parts of the system:
+
+* ``challenger-httpd``: runs the HTTP daemon with the core business logic.
+* ``postgres``: runs the PostgreSQL database (from *postgresql* package).
+* ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package).
+
+The package will deploy a systemd service files in
+``/usr/lib/systemd/system/`` for Challenger:
+
+* ``challenger-httpd.service``: the Challenger logic with the public REST API.
+
+
+Configuration Fundamentals
+==========================
+
+This chapter provides fundamental details about the exchange configuration.
+
+The configuration for all Taler components uses a single configuration file
+as entry point: ``/etc/challenger/challenger.conf``.
+
+System defaults are automatically loaded from files in
+``/usr/share/challenger/config.d``. These default files should never be modified.
+
+The default configuration ``challenger.conf`` configuration file also includes all
+configuration files in ``/etc/challenger/conf.d``.
+
+To view the entire configuration annotated with the source of each configuration option, you
+can use the ``challenger-config`` helper:
+
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# challenger-config --diagnostics
+ < ... annotated, full configuration ... >
+
+.. warning::
+
+ While ``challenger-config`` also supports rewriting configuration files, we strongly
+ recommend to edit configuration files manually, as ``challenger-config`` does not
+ preserve comments and, by default, rewrites ``/etc/challenger/challenger.conf``.
+
+.. include:: frags/configuration-format.rst
+
+
+Fundamental Setup: Address validation
+-------------------------------------
+
+Each challenger service is designed to validate one type of address. Possible
+address types include:
+
+* phone numbers (via SMS)
+* e-mail addresses (via SMTP)
+* mail addresses (via postal service)
+
+In principle, additional types of addresses can easily be added by extending
+the respective HTML and programs to send challenges to the new address type.
+
+To make different types of address validations possible, the Challenger
+configuration contains two configuration options.
+
+(1) The ``ADDRESS_TYPE`` configuration option informs Challenger about the
+ type of address it is expected to validate. It is returned as part of
+ the OAuth 2.0 ``/info`` endpoint to the client, and is typically also
+ used when deciding how to render the HTML form for address entry that is
+ shown to the user.
+
+(2) The ``AUTH_COMMAND`` configuration option specifies which command
+ Challenger should run to send a challenge to an address. The actual
+ address is given to this subcommand as the first argument (``$1``),
+ while the text with the challenge is passed to standard input.
+ The subcommand should terminate with a status code of 0 on success.
+
+.. code-block:: ini
+ :caption: /etc/challenger/challenger.conf
+
+ [challenger]
+ ADDRESS_TYPE = email
+ AUTH_COMMAND = challenger-send-email.sh
+ # ... rest of file ...
+
+Challenger comes with ``AUTH_COMMAND`` shell scripts for sending e-mail, SMS
+and postal mail. Note that for SMS and postal mail the Challenger scripts uses
+third party services to actually send the SMS or print and mail the postal
+mail. These third parties naturally charge money for their services, and thus
+the Challenger administrator will need to add the respective credentials to
+the SMS and postal mail scripts before they can function. In any case, these
+scripts should be primarily seen as *examples* on how to write authentication
+commands.
+
+.. note::
+
+ We strongly welcome contributions for additional scripts with alternative
+ providers or for new types of addresses.
+
+
+Legal conditions for using the service
+--------------------------------------
+
+.. include:: frags/legal.rst
+
+Database Configuration
+----------------------
+
+The access credentials for the Challenger database are configured in
+``/etc/challenger/challenger.conf``. Currently, only PostgreSQL is
+supported as a database backend.
+
+.. note::
+
+ The **challenger-dbconfig** tool can be used to automate the database
+ setup. When using the Debian/Ubuntu packages, the user should already have
+ been created, so you can just run the tool without any arguments and should
+ have a working database configuration. Subsequently, you should still run
+ **taler-challenger-dbinit** as the ``challenger-httpd`` user to
+ initialize the database schema.
+
+
+To create a database for Challenger on the local system, run:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# su - postgres
+ [postgres@exchange-online]# createuser challenger-httpd
+ [postgres@exchange-online]# createdb -O challenger-httpd challenger
+ [postgres@exchange-online]# exit
+
+This will create a ``challenger`` database owned by the ``taler-httpd`` user.
+We will use that user later to perform database maintenance operations.
+
+Assuming the above database setup, the database credentials to configure
+in the configuration file would simply be:
+
+.. code-block:: ini
+ :caption: /etc/challenger/challenger.conf
+
+ [challenger]
+ DB = postgres
+
+ [challenger-postgres]
+ CONFIG = postgres:///challenger
+
+If the database is run on a different host, please follow the instructions
+from the PostgreSQL manual for configuring remote access.
+
+After configuring the database credentials, the Challenger database needs
+to be initialized with the following command:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# sudo -u challenger-httpd challenger-dbinit
+
+.. note::
+
+ To run this command, the user must have ``CREATE TABLE``, ``CREATE
+ INDEX``, ``ALTER TABLE`` and (in the future possibly even) ``DROP TABLE``
+ permissions. Those permissions are only required for this step (which may
+ have to be repeated when upgrading a deployment). Afterwards, during
+ normal operation, permissions to ``CREATE`` or ``ALTER`` tables are not
+ required by Challenger and thus should not be granted. For more
+ information, see :doc:`manpages/challenger-dbinit.1`.
+
+
+Deployment
+==========
+
+This chapter describes how to deploy Challenger once the basic installation
+and configuration are completed.
+
+.. _ChallengerServing:
+
+Serving
+-------
+
+The Challenger can serve HTTP over both TCP and UNIX domain socket.
+
+The following options are to be configured in the section ``[challenger]``:
+
+- ``SERVE``: Must be set to ``tcp`` to serve HTTP over TCP, or ``unix`` to serve
+ HTTP over a UNIX domain socket.
+
+- ``PORT``: Set to the TCP port to listen on if ``SERVE`` is ``tcp``.
+
+- ``UNIXPATH``: Set to the UNIX domain socket path to listen on if ``SERVE`` is
+ ``unix``.
+
+- ``UNIXPATH_MODE``: Number giving the mode with the access permission mask
+ for the ``UNIXPATH`` (i.e. 660 = ``rw-rw---``). Make sure to set it in such
+ a way that your reverse proxy has permissions to access the UNIX domain
+ socket. The default (660) assumes that the reverse proxy is a member of
+ the group under which the exchange HTTP server is running.
+
+.. _ChallengerReverseProxy:
+
+Reverse Proxy Setup
+-------------------
+
+By default, the ``challenger-httpd`` service listens for HTTP connections
+on a UNIX domain socket. To make the service publicly available, a reverse
+proxy such as nginx should be used. You must configure the reverse proxy
+to use TLS as this is required by OAuth 2.0.
+
+The ``challenger`` package ships with a sample configuration that can be
+enabled in nginx:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# vim /etc/nginx/sites-available/challenger
+ < ... customize configuration ... >
+ [root@exchange-online]# ln -s /etc/nginx/sites-available/challenger \
+ /etc/nginx/sites-enabled/challenger
+ [root@exchange-online]# systemctl reload nginx
+
+
+Launching Challenger
+--------------------
+
+A running exchange requires starting the following processes:
+
+- ``challenger-httpd`` (needs database access)
+
+The processes should be started via a hypervisor like
+``systemd`` or ``gnunet-arm`` that automatically re-starts them should they
+have terminated unexpectedly. Furthermore, the hypervisor
+*should* periodically re-start the service (say once per hour)
+to limit Postgres database memory utilization.
+
+.. note::
+
+ The ``challenger-httpd`` does not ship with HTTPS enabled by default.
+ It must thus be run behind an HTTPS reverse proxy that performs
+ TLS termination on the same system. Thus, it would typically be configured
+ to listen on a UNIX domain socket.
+
+Given proper packaging, all of the above are realized via a simple systemd
+target. This enables Challenger to be properly started using a simple command:
+
+.. code-block:: shell-session
+
+ # systemctl start challenger-httpd.service
+
+
+Authorizing clients
+-------------------
+
+Before clients can use Challenger, they must be explicitly configured. Each
+client is identified via its OAuth 2.0 REDIRECT URI. Thus, a client must have
+exactly one REDIRECT URI
+
+.. note::
+
+ The OAuth 2.0 specification allows for a client to register
+ zero or multiple REDIRECT URIs. However, zero is insecure
+ as it creates an open redirector, and multiple REDIRECT URIs
+ can trivially be implemented with Challenger by adding more
+ clients.
+
+You can add or remove clients at any time; the Challenger service does not
+need to be running, but if it is you can still add or remove clients without
+restarting the service. To add (or remove) a client, you must use the
+``challenger-admin`` command:
+
+.. code-block:: shell-session
+
+ # sudo -u challenger-httpd challenger-admin --add=$SECRET $REDIRECT_URI
+
+Here, ``$SECRET`` is the client secret of OAuth 2.0 which will be used in
+various parts of the protocol to authenticate the client. The
+``$REDIRECT_URI`` is the URI where the user-agent will be redirected to upon
+completion of the process. The ``challenger-admin`` command will
+then output the *client ID*, which will be a unique positive number.
+The first time you run the command, you will thus likely see:
+``Client added. Client ID is: 1``. This client ID, the ``$SECRET``
+and the ``$REDIRECT_URI`` will form the foundation for the OAuth 2.0
+configuration.
+
+
+OAuth 2.0 integration
+---------------------
+
+When integrating Challenger into an OAuth 2.0 process, you need to provide the
+three options from the previous section, but also the authorization, token and
+info endpoints. For Challenger, these are ``/authorize``, ``/token`` and
+``/info``. However, the ``/authorize`` endpoint is special, as it is actually
+``/authorize/$NONCE`` where ``$NONCE`` is a nonce that must be first requested
+by the client using the ``/setup/$CLIENT_ID`` endpoint!
+
+.. note::
+
+ This extra step prevents user-agents from (ab)using the Challenger service
+ to send challenges to addresses even when there is no authorized client
+ that desires address validation. This is an important feature as address
+ validation could be expensive.
+
+Thus, to generate the authorization URL, a client must first POST to
+``/setup/$CLIENT_ID`` using their client secret in an ``Authorization: Bearer $SECRET``
+HTTP header to obtain a fresh ``$NONCE``.
+
+In the GNU Taler exchange configuration, this is indicated by appending
+``#setup`` to the ``KYC_OAUTH2_AUTHORIZE_URL`` endpoint. Be careful to quote
+the URL, as ``#`` is otherwise interpreted as the beginning of a comment by
+the configuration file syntax:
+
+.. code-block:: ini
+ :caption: /etc/taler/conf.d/exchange-oauth2.conf
+
+ [kyc-provider-example-oauth2]
+ LOGIC = oauth2
+ # (generic options omitted)
+ KYC_OAUTH2_AUTHORIZE_URL = "https://challenger.example.com/authorize#setup"
+ KYC_OAUTH2_TOKEN_URL = "https://challenger.example.com/token"
+ KYC_OAUTH2_INFO_URL = "https://challenger.example.com/info"
+ KYC_OAUTH2_CLIENT_ID = 1
+ KYC_OAUTH2_CLIENT_SECRET = "$SECRET"
+
+
+
+Database management
+-------------------
+
+.. note::
+
+ We advise to make good backups before experimenting with
+ the database.
+
+To update the Challenger database after upgrading to a newer
+version of Challenger, you should simply re-run ``challenger-dbinit``.
+Without further options, this command is expected to preserve
+all data and only migrate the existing database to the latest
+schema:
+
+.. code-block:: console
+
+ $ challenger-dbinit
+
+To delete stale data from the Challenger database, you can use
+garbage collection:
+
+.. code-block:: console
+
+ $ challenger-dbinit --garbagecollect
+
+
+The Challenger database can be re-initialized using:
+
+.. code-block:: console
+
+ $ challenger-dbinit --reset
+
+However, running this command will result in all data in the database
+being lost.
+
+
+.. _ChallengerCustomization:
+
+Template Customization
+======================
+
+The Challenger service comes with various HTML templates that are shown to
+guide users through the process. Challenger uses `C implementation of mustache
+<https://gitlab.com/jobol/mustach>`__ as the templating engine. This section
+describes the various templates. In general, the templates must be installed
+to the ``share/challenger/templates/`` directory. The file names must be of
+the form ``$NAME.$LANG.must`` where ``$NAME`` is the name of the template and
+``$LANG`` is the 2-letter language code of the template. English templates
+must exist and will be used as a fallback. If the browser (user-agent) has
+provided language preferences in the HTTP header and the respective language
+exists, the correct language will be automatically served.
+
+The following subsections give details about each of the templates. The
+subsection title is the ``$NAME`` of the respective template.
+
+.. _challenger_enter-address_type-form:
+
+enter-$ADDRESS_TYPE-form
+------------------------
+
+These templates are used to ask the user to enter the address that challenger
+is expected to validate. Here, ``$ADDRESS_TYPE`` will be replaced by the
+``ADDRESS_TYPE`` configuration option in the ``[challenger]`` section of the
+configuration file. Typical values include ``address`` (for physical mailing
+addresses), ``phone`` (for mobile phone numbers) and ``email`` (for email
+addresses). For testing, ``file`` (where the TAN code is written into a local
+file) is also supported.
+
+The template is instantiated using the following information:
+
+* restrictions: Object; map of keys (names of the fields of the
+ address to be entered by the user) to objects with a "regex"
+ (string) containing an extended Posix regular expression for
+ allowed address field values, and a "hint"/"hint_i18n" giving
+ a human-readable explanation to display if the value entered
+ by the user does not match the regex. Keys that are not mapped
+ to such an object have no restriction on the value provided by
+ the user. See "ADDRESS_RESTRICTIONS" in the challenger
+ configuration.
+* fix_address: boolean; indicates if the given address cannot be changed
+ anymore, the form should be read-only if set to true.
+* nonce: String; unique value identifying the challenge, should be shown
+ to the user so that they can recognize it when they receive the TAN code
+* last_address: Object; form values from the previous submission if available,
+ details depend on the ``ADDRESS_TYPE``, should be used to pre-populate the form
+* changes_left: Integer; number of times the address can still be changed,
+ may or may not be shown to the user
+
+.. _challenger_enter-tan-form:
+
+enter-tan-form
+--------------
+
+This page should generate the HTML form for the user to enter the TAN code
+that they received at the respective address.
+
+The template is instantiated using the following information:
+
+* nonce: String; unique value identifying the challenge, should be shown
+ to the user so that they can match it to the TAN code they received
+* attempts_left: Integer; how many more attempts are allowed, might be
+ shown to the user, highlighting might be appropriate for low values
+ such as 1 or 2 (the form will never be used if the value is zero)
+* address: Object; the address that is being validated, might be shown
+ or not
+* transmitted: boolean; true if we just retransmitted the challenge,
+ false if we sent a challenge recently and thus refused to transmit it
+ again this time; might make a useful hint to the user
+* next_tx_time: String; timestamp explaining when we would re-transmit
+ the challenge the next time (at the earliest) if requested by the user
+
+
+.. _challenger_invalid-pin:
+
+invalid-pin
+-----------
+
+The user has provided an invalid TAN code (HTTP 403 Forbidden).
+
+The template is instantiated using the following information:
+
+* ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+* hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+* addresses_left: Integer; how many times is the user still allowed to
+ change the address; if 0, the user should not be shown a link to jump
+ to the address entry form
+* pin_transmissions_left: Integer; how many times might the PIN still
+ be retransmitted
+* auth_attempts_left: Integer; how many times might the user still try
+ entering the PIN code
+* exhausted: Bool; if true, the PIN was not even evaluated as the user
+ previously exhausted the number of attempts
+* no_challenge: Bool; if true, the PIN was not even evaluated as no
+ challenge was ever issued (the user must have skipped the step of
+ providing their address first!)
+
+If both *pin_transmissions_left* and *auth_attempts_left* are zero, the link
+to re-enter the PIN should be hidden and the user should only be allowed to
+specify a different address. The form will never be generated if all three
+values are zero. (Thus there is always at least one valid choice when the form
+is shown.)
+
+
+.. _challenger_validation-unknown:
+
+validation-unknown
+------------------
+
+The user has tried to access a validation process that is not known to the
+backend (HTTP 404 Not Found).
+
+The template is instantiated using the following information:
+
+* ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+* hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+* detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
+
+.. _challenger_invalid-request:
+
+invalid-request
+---------------
+
+The request of the client is invalid (HTTP 400 Bad Request).
+
+The template is instantiated using the following information:
+
+* ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+* hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+* detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context
+
+.. _challenger_internal-error:
+
+internal-error
+--------------
+
+The service experienced an internal error (HTTP 500 Internal Server Error).
+
+The template is instantiated using the following information:
+
+* ec: Integer; numeric Taler error code, should be shown to indicate the
+ error compactly for reporting to developers
+* hint: String; human-readable Taler error code, should be shown for the
+ user to understand the error
+* detail: String; optional, extended human-readable text provided to elaborate
+ on the error, should be shown to provide additional context