..
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
@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 `__.
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 `__.
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. Challenger also does not allow multiple clients sharing the same 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=$CLIENT_SECRET $CLIENT_REDIRECT_URI
Here, ``$CLIENT_SECRET`` is the client secret of OAuth 2.0 which will be used in
various parts of the protocol to authenticate the client. It must begin with the "secret-token:" prefix of RFC 8959. The
``$CLIENT_REDIRECT_URI`` is the REDIRECT 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 ``$CLIENT_SECRET``
and the ``$CLIENT_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
$CLIENT_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
# Make sure to include the RFC 8959 prefix in "$SECRET"
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.