taler-challenger-manual.rst (23292B)
1 .. 2 This file is part of GNU TALER. 3 4 Copyright (C) 2023, 2024 Taler Systems SA 5 6 TALER is free software; you can redistribute it and/or modify it under the 7 terms of the GNU Affero General Public License as published by the Free Software 8 Foundation; either version 3.0, or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 13 14 You should have received a copy of the GNU Affero General Public License along with 15 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 16 17 @author Christian Grothoff 18 @author Florian Dold 19 20 Challenger Operator Manual 21 ########################## 22 23 Introduction 24 ============ 25 26 About Challenger 27 ---------------- 28 29 Challenger is an OAuth 2.0-compatible address validation service. 30 By redirecting a user-agent to a Challenger service a client can 31 have Challenger validate that the user is able to receive messages 32 at a particular address and obtain that address via the ``/info`` 33 endpoint. 34 35 36 About this manual 37 ----------------- 38 39 This manual targets system administrators who want to install, 40 operate or integrate a challenger service. To report issues 41 or learn about known limitations, please check our 42 `bug tracker <https://bugs.taler.net>`__. 43 44 45 Architecture overview 46 --------------------- 47 48 The following picture gives an overview of the Challenger 49 architecture and the main interactions: 50 51 .. image:: images/challenger.png 52 53 Here, the *resource owner* is a user that is in control 54 of some *address* at a messaging service. This could be 55 an e-mail account, a mobile phone number (for SMS), or 56 a physical mail address (using the post office as the 57 messaging service). 58 59 The *resource owner* makes some request that requires 60 some *client* to be in need of address validation. The 61 *client* is registered with the Challenger OAuth 2.0 62 service and first authorizes an address validation to 63 be initiated. The client then redirects the resource 64 owner to the Challenger service. In step (2), the resource 65 owner submits the address that they claim to own. 66 67 The Challenger service then creates a TAN code and 68 submits it to the given address via a configurable 69 *helper script* that is specific to the type of address 70 being validated. When the resource owner submits the 71 correct TAN code in step (6), they are given a token 72 that they can provide to the client. Using this token 73 the client can then finally obtain the now validated 74 address in step (8). 75 76 Address data, TAN codes and meta-data such as the number 77 of failed attempts to submit a TAN code are recorded 78 in a Postgres database by the Challenger service. 79 80 .. _ChallengerInstallation: 81 82 Installation 83 ============ 84 85 In this guide's shell-session fragments, the command prompt shows two pieces 86 of information: 87 88 * Who is performing the command 89 (``$user`` vs ``root``, and ending character ``$`` vs ``#``). 90 91 92 Installing from source 93 ---------------------- 94 95 The following instructions will show how to install libgnunetutil and 96 the core GNU Taler libraries from source. 97 98 The package sources can be find in our 99 `download directory <http://ftpmirror.gnu.org/taler/>`__. 100 101 GNU Taler components version numbers follow the ``MAJOR.MINOR.MICRO`` format. 102 The general rule for compatibility is that ``MAJOR`` and ``MINOR`` must match. 103 Exceptions to this general rule are documented in the release notes. 104 For example, Challenger 1.3.0 should be compatible with Taler exchange 1.4.x 105 as the MAJOR version matches. A MAJOR version of 0 indicates experimental 106 development, and you are expected to always run all of the *latest* releases 107 together (no compatibility guarantees). 108 109 First, the following packages need to be installed before we can compile the 110 backend: 111 112 .. include:: frags/list-of-dependencies.rst 113 114 .. include:: frags/installing-gnunet.rst 115 116 .. include:: frags/install-before-check.rst 117 118 There is no need to actually run a GNUnet peer or a Taler exchange to use 119 Challenger -- all Challenger needs from GNUnet and Taler are a number of 120 headers and libraries! 121 122 .. include:: frags/installing-taler-exchange.rst 123 124 125 .. include:: frags/installing-challenger.rst 126 127 .. include:: frags/install-before-check.rst 128 129 130 131 Installing the Challenger binary packages on Debian 132 --------------------------------------------------- 133 134 .. include:: frags/installing-debian.rst 135 136 To install the Challenger, you can now simply run: 137 138 .. code-block:: shell-session 139 140 # apt install challenger 141 142 Note that the package does not perform any configuration work except for 143 setting up the various users and the systemd service scripts. You still must 144 configure at least the database, HTTP reverse proxy (typically with TLS 145 certificates) and the terms of service. 146 147 Installing the GNU Taler binary packages on Trisquel 148 ---------------------------------------------------- 149 150 .. include:: frags/installing-trisquel.rst 151 152 Installing the GNU Taler binary packages on Ubuntu 153 -------------------------------------------------- 154 155 .. include:: frags/installing-ubuntu.rst 156 157 To install the Taler exchange, you can now simply run: 158 159 .. code-block:: shell-session 160 161 # apt install challenger 162 163 Note that the package does not perform any configuration work except for 164 setting up the various users and the systemd service scripts. You still must 165 configure at least the database, HTTP reverse proxy (typically with TLS 166 certificates), and the terms of service. 167 168 169 Services, users, groups and file system hierarchy 170 ------------------------------------------------- 171 172 The *challenger* package will use several system users 173 to compartmentalize different parts of the system: 174 175 * ``challenger-httpd``: runs the HTTP daemon with the core business logic. 176 * ``postgres``: runs the PostgreSQL database (from *postgresql* package). 177 * ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package). 178 179 The package will deploy systemd service files in 180 ``/usr/lib/systemd/system/`` for Challenger: 181 182 * ``challenger-httpd.service``: the Challenger logic with the public REST API. 183 184 185 Configuration Fundamentals 186 ========================== 187 188 This chapter provides fundamental details about the exchange configuration. 189 190 The configuration for all Taler components uses a single configuration file 191 as entry point: ``/etc/challenger/challenger.conf``. 192 193 System defaults are automatically loaded from files in 194 ``/usr/share/challenger/config.d``. These default files should never be modified. 195 196 The default configuration ``challenger.conf`` configuration file also includes all 197 configuration files in ``/etc/challenger/conf.d``. 198 199 To view the entire configuration annotated with the source of each configuration option, you 200 can use the ``challenger-config`` helper: 201 202 203 .. code-block:: shell-session 204 205 [root@exchange-online]# challenger-config --diagnostics 206 < ... annotated, full configuration ... > 207 208 .. warning:: 209 210 While ``challenger-config`` also supports rewriting configuration files, we strongly 211 recommend to edit configuration files manually, as ``challenger-config`` does not 212 preserve comments and, by default, rewrites ``/etc/challenger/challenger.conf``. 213 214 .. include:: frags/configuration-format.rst 215 216 217 Fundamental Setup: Address validation 218 ------------------------------------- 219 220 Each challenger service is designed to validate one type of address. Possible 221 address types include: 222 223 * phone numbers (via SMS) 224 * e-mail addresses (via SMTP) 225 * mail addresses (via postal service) 226 227 In principle, additional types of addresses can easily be added by extending 228 the respective HTML and programs to send challenges to the new address type. 229 230 To make different types of address validations possible, the Challenger 231 configuration contains two configuration options. 232 233 (1) The ``ADDRESS_TYPE`` configuration option informs Challenger about the 234 type of address it is expected to validate. It is returned as part of 235 the OAuth 2.0 ``/info`` endpoint to the client, and is typically also 236 used when deciding how to render the HTML form for address entry that is 237 shown to the user. 238 239 (2) The ``AUTH_COMMAND`` configuration option specifies which command 240 Challenger should run to send a challenge to an address. The value may 241 include arguments separated by spaces; quoting and escaping are not 242 supported. The actual address is appended as the final argument, while 243 the text with the challenge is passed to standard input. The command 244 should terminate with a status code of 0 on success. 245 246 .. code-block:: ini 247 :caption: /etc/challenger/challenger.conf 248 249 [challenger] 250 ADDRESS_TYPE = email 251 AUTH_COMMAND = challenger-send-email.sh 252 # ... rest of file ... 253 254 Challenger comes with ``AUTH_COMMAND`` shell scripts for sending e-mail, SMS 255 and postal mail. Note that for SMS and postal mail the Challenger scripts use 256 third party services to actually send the SMS or print and mail the postal 257 mail. These third parties naturally charge money for their services, and thus 258 the Challenger administrator will need to obtain an account with one of them. 259 The scripts read the credentials from their **environment** rather than from a 260 configuration file, so they are configured by setting those variables for the 261 ``challenger-httpd`` service and not by editing the scripts; see 262 *SMS transmission providers* below. In any case, these scripts should be 263 primarily seen as *examples* on how to write authentication commands. 264 265 .. note:: 266 267 We strongly welcome contributions for additional scripts with alternative 268 providers or for new types of addresses. 269 270 271 SMS transmission providers 272 -------------------------- 273 274 The ``AUTH_COMMAND`` for phone numbers is ``challenger-send-sms``, which is not 275 itself an SMS sender: it checks the number, then runs each provider helper in 276 turn until one of them accepts the message. The helpers live next to it and are 277 named ``challenger-send-sms-``\ *PROVIDER*; which of them are tried, and in 278 which order, is the ``PROVIDERS`` variable near the top of the dispatcher 279 script. A helper that is not installed or not executable is skipped. 280 281 Credentials are **not** configuration options in ``challenger.conf``. They are 282 read from the environment of the invoking daemon, so that they do not end up in 283 a world-readable configuration file nor in the process table. With systemd they 284 belong in a drop-in for the service, ideally through 285 ``EnvironmentFile=`` pointing at a file readable only by the service user: 286 287 .. code-block:: ini 288 :caption: /etc/systemd/system/challenger-httpd.service.d/sms.conf 289 290 [Service] 291 EnvironmentFile=/etc/challenger/sms-credentials.env 292 293 A helper whose credentials are missing or empty exits with status 40, which the 294 dispatcher treats as a configuration failure and falls through to the next 295 provider. 296 297 .. list-table:: 298 :header-rows: 1 299 :widths: 22 18 60 300 301 * - Helper 302 - Operated from 303 - Environment 304 * - ``challenger-send-sms-telesign`` 305 - United States 306 - ``TELESIGN_AUTH_TOKEN`` 307 * - ``challenger-send-sms-clicksend`` 308 - Australia 309 - ``CLICKSEND_USERNAME``, ``CLICKSEND_API_KEY`` 310 * - ``challenger-send-sms-aspsms`` 311 - Switzerland 312 - ``ASPSMS_USERKEY``, ``ASPSMS_PASSWORD`` 313 * - ``challenger-send-sms-seven`` 314 - Germany 315 - ``SEVEN_API_KEY`` 316 * - ``challenger-send-sms-gatewayapi`` 317 - Denmark 318 - ``GATEWAYAPI_TOKEN``, optionally ``GATEWAYAPI_BASE_URL`` 319 * - ``challenger-send-sms-budgetsms`` 320 - Netherlands 321 - ``BUDGETSMS_USERNAME``, ``BUDGETSMS_USERID``, ``BUDGETSMS_HANDLE``, 322 optionally ``BUDGETSMS_SENDER`` 323 324 Two of the variables above are not credentials: 325 326 ``GATEWAYAPI_BASE_URL`` 327 Which GatewayAPI platform to use. Optional, defaults to 328 ``https://gatewayapi.eu``, the platform on which hosting, ownership and 329 routing stay inside the European Union. Set it to ``https://gatewayapi.com`` 330 for an account on the global platform. An API token is only valid on the 331 platform it was created for. 332 333 ``BUDGETSMS_SENDER`` 334 Sender identity to show on the message, at most 11 alphanumeric or 16 335 numeric characters. Optional, defaults to ``Challenger``. The BudgetSMS API 336 requires a sender on every message; the other helpers use the sender 337 configured on the provider account. Note that an alphanumeric sender has to 338 be registered with the operator in a number of countries before messages 339 using it are delivered. 340 341 Only the first three helpers are listed in ``PROVIDERS`` as shipped. The three 342 below them are operated inside the European Economic Area, which avoids 343 transferring the phone number and the TAN — personal data that is at the same 344 time an authentication secret — to a third country, and with it the need for a 345 transfer instrument under Chapter V of the GDPR. They have been written against 346 the published specifications of their APIs and are covered by the offline test 347 suite, but have not yet been exercised against a live account, which is why a 348 deployment has to enable them explicitly by adding their name to ``PROVIDERS``. 349 350 Whether a failing provider causes the next one to be tried depends on the class 351 of failure: a number that one provider rejects would be rejected by all of 352 them, so that is reported immediately, whereas a provider that is down, out of 353 credit, rate limited or misconfigured does not prevent another from succeeding. 354 The full table of exit statuses is in challenger-send-sms(1), and each helper's 355 manual page documents the subset it can report, its API, and its credentials. 356 357 .. warning:: 358 359 A provider that accepts a message charges for it. Because a submission that 360 times out may still have been accepted, a fall-through can send the same TAN 361 twice; the dispatcher prefers that over not delivering a TAN at all. 362 363 364 Legal conditions for using the service 365 -------------------------------------- 366 367 .. include:: frags/legal.rst 368 369 Database Configuration 370 ---------------------- 371 372 The access credentials for the Challenger database are configured in 373 ``/etc/challenger/challenger.conf``. Currently, only PostgreSQL is 374 supported as a database backend. 375 376 .. note:: 377 378 The **challenger-dbconfig** tool can be used to automate the database 379 setup. When using the Debian/Ubuntu packages, the user should already have 380 been created, so you can just run the tool without any arguments and should 381 have a working database configuration. Subsequently, you should still run 382 **taler-challenger-dbinit** as the ``challenger-httpd`` user to 383 initialize the database schema. 384 385 386 To create a database for Challenger on the local system, run: 387 388 .. code-block:: shell-session 389 390 [root@exchange-online]# su - postgres 391 [postgres@exchange-online]# createuser challenger-httpd 392 [postgres@exchange-online]# createdb -O challenger-httpd challenger 393 [postgres@exchange-online]# exit 394 395 This will create a ``challenger`` database owned by the ``taler-httpd`` user. 396 We will use that user later to perform database maintenance operations. 397 398 Assuming the above database setup, the database credentials to configure 399 in the configuration file would simply be: 400 401 .. code-block:: ini 402 :caption: /etc/challenger/challenger.conf 403 404 [challenger] 405 DB = postgres 406 407 [challenger-postgres] 408 CONFIG = postgres:///challenger 409 410 If the database is run on a different host, please follow the instructions 411 from the PostgreSQL manual for configuring remote access. 412 413 After configuring the database credentials, the Challenger database needs 414 to be initialized with the following command: 415 416 .. code-block:: shell-session 417 418 [root@exchange-online]# sudo -u challenger-httpd challenger-dbinit 419 420 .. note:: 421 422 To run this command, the user must have ``CREATE TABLE``, ``CREATE 423 INDEX``, ``ALTER TABLE`` and (in the future possibly even) ``DROP TABLE`` 424 permissions. Those permissions are only required for this step (which may 425 have to be repeated when upgrading a deployment). Afterwards, during 426 normal operation, permissions to ``CREATE`` or ``ALTER`` tables are not 427 required by Challenger and thus should not be granted. For more 428 information, see :doc:`manpages/challenger-dbinit.1`. 429 430 431 Deployment 432 ========== 433 434 This chapter describes how to deploy Challenger once the basic installation 435 and configuration are completed. 436 437 .. _ChallengerServing: 438 439 Serving 440 ------- 441 442 The Challenger can serve HTTP over both TCP and UNIX domain socket. 443 444 The following options are to be configured in the section ``[challenger]``: 445 446 - ``SERVE``: Must be set to ``tcp`` to serve HTTP over TCP, or ``unix`` to serve 447 HTTP over a UNIX domain socket. 448 449 - ``PORT``: Set to the TCP port to listen on if ``SERVE`` is ``tcp``. 450 451 - ``UNIXPATH``: Set to the UNIX domain socket path to listen on if ``SERVE`` is 452 ``unix``. 453 454 - ``UNIXPATH_MODE``: Number giving the mode with the access permission mask 455 for the ``UNIXPATH`` (i.e. 660 = ``rw-rw---``). Make sure to set it in such 456 a way that your reverse proxy has permissions to access the UNIX domain 457 socket. The default (660) assumes that the reverse proxy is a member of 458 the group under which the exchange HTTP server is running. 459 460 .. _ChallengerReverseProxy: 461 462 Reverse Proxy Setup 463 ------------------- 464 465 By default, the ``challenger-httpd`` service listens for HTTP connections 466 on a UNIX domain socket. To make the service publicly available, a reverse 467 proxy such as nginx should be used. You must configure the reverse proxy 468 to use TLS as this is required by OAuth 2.0. 469 470 The ``challenger`` package ships with a sample configuration that can be 471 enabled in nginx: 472 473 .. code-block:: shell-session 474 475 [root@exchange-online]# vim /etc/nginx/sites-available/challenger 476 < ... customize configuration ... > 477 [root@exchange-online]# ln -s /etc/nginx/sites-available/challenger \ 478 /etc/nginx/sites-enabled/challenger 479 [root@exchange-online]# systemctl reload nginx 480 481 482 Launching Challenger 483 -------------------- 484 485 A running exchange requires starting the following processes: 486 487 - ``challenger-httpd`` (needs database access) 488 489 The processes should be started via a hypervisor like 490 ``systemd`` or ``gnunet-arm`` that automatically re-starts them should they 491 have terminated unexpectedly. Furthermore, the hypervisor 492 *should* periodically re-start the service (say once per hour) 493 to limit Postgres database memory utilization. 494 495 .. note:: 496 497 The ``challenger-httpd`` does not ship with HTTPS enabled by default. 498 It must thus be run behind an HTTPS reverse proxy that performs 499 TLS termination on the same system. Thus, it would typically be configured 500 to listen on a UNIX domain socket. 501 502 Given proper packaging, all of the above are realized via a simple systemd 503 target. This enables Challenger to be properly started using a simple command: 504 505 .. code-block:: shell-session 506 507 # systemctl start challenger-httpd.service 508 509 510 Authorizing clients 511 ------------------- 512 513 Before clients can use Challenger, they must be explicitly configured. Each 514 client is identified via its OAuth 2.0 REDIRECT URI. Thus, a client must have 515 exactly one REDIRECT URI. Challenger also does not allow multiple clients sharing the same REDIRECT URI. 516 517 .. note:: 518 519 The OAuth 2.0 specification allows for a client to register 520 zero or multiple REDIRECT URIs. However, zero is insecure 521 as it creates an open redirector, and multiple REDIRECT URIs 522 can trivially be implemented with Challenger by adding more 523 clients. 524 525 You can add or remove clients at any time; the Challenger service does not 526 need to be running, but if it is you can still add or remove clients without 527 restarting the service. To add (or remove) a client, you must use the 528 ``challenger-admin`` command: 529 530 .. code-block:: shell-session 531 532 # sudo -u challenger-httpd challenger-admin --add=$CLIENT_SECRET $CLIENT_REDIRECT_URI 533 534 Here, ``$CLIENT_SECRET`` is the client secret of OAuth 2.0 which will be used in 535 various parts of the protocol to authenticate the client. It must begin with the "secret-token:" prefix of RFC 8959. The 536 ``$CLIENT_REDIRECT_URI`` is the REDIRECT URI where the user-agent will be redirected to upon 537 completion of the process. The ``challenger-admin`` command will 538 then output the *CLIENT_ID*, which will be a unique positive number. 539 The first time you run the command, you will thus likely see: 540 ``Client added. Client ID is: 1``. This CLIENT_ID, the ``$CLIENT_SECRET`` 541 and the ``$CLIENT_REDIRECT_URI`` will form the foundation for the OAuth 2.0 542 configuration. 543 544 545 OAuth 2.0 integration 546 --------------------- 547 548 When integrating Challenger into an OAuth 2.0 process, you need to provide the 549 three options from the previous section, but also the authorization, token and 550 info endpoints. For Challenger, these are ``/authorize``, ``/token`` and 551 ``/info``. However, the ``/authorize`` endpoint is special, as it is actually 552 ``/authorize/$NONCE`` where ``$NONCE`` is a nonce that must be first requested 553 by the client using the ``/setup/$CLIENT_ID`` endpoint! 554 555 .. note:: 556 557 This extra step prevents user-agents from (ab)using the Challenger service 558 to send challenges to addresses even when there is no authorized client 559 that desires address validation. This is an important feature as address 560 validation could be expensive. 561 562 Thus, to generate the authorization URL, a client must first POST to 563 ``/setup/$CLIENT_ID`` using their client secret in an ``Authorization: Bearer 564 $CLIENT_SECRET`` HTTP header to obtain a fresh ``$NONCE``. It is (optionally) 565 possible to pass an address in the body of the ``/setup`` POST request. In 566 this case, Challenger will pre-populate the address of the KYC form with the 567 given body. Here, the format of the body is *address type*-specific. 568 569 .. note:: 570 571 By passing a flag ``read_only: true`` editing of the address in the SPA can 572 be disabled. However, the backend currently does not enforce this 573 (see #9349). 574 575 In the GNU Taler exchange configuration, this is indicated by appending 576 ``#setup`` to the ``KYC_OAUTH2_AUTHORIZE_URL`` endpoint. Be careful to quote 577 the URL, as ``#`` is otherwise interpreted as the beginning of a comment by 578 the configuration file syntax: 579 580 .. code-block:: ini 581 :caption: /etc/taler-exchange/conf.d/exchange-oauth2.conf 582 583 [kyc-provider-example-oauth2] 584 LOGIC = oauth2 585 # (generic options omitted) 586 KYC_OAUTH2_AUTHORIZE_URL = "https://challenger.example.com/authorize#setup" 587 KYC_OAUTH2_TOKEN_URL = "https://challenger.example.com/token" 588 KYC_OAUTH2_INFO_URL = "https://challenger.example.com/info" 589 KYC_OAUTH2_CLIENT_ID = 1 590 # Make sure to include the RFC 8959 prefix in "$SECRET" 591 KYC_OAUTH2_CLIENT_SECRET = "$SECRET" 592 593 594 595 Database management 596 ------------------- 597 598 .. note:: 599 600 We advise to make good backups before experimenting with 601 the database. 602 603 To update the Challenger database after upgrading to a newer 604 version of Challenger, you should simply re-run ``challenger-dbinit``. 605 Without further options, this command is expected to preserve 606 all data and only migrate the existing database to the latest 607 schema: 608 609 .. code-block:: console 610 611 $ challenger-dbinit 612 613 To delete stale data from the Challenger database, you can use 614 garbage collection: 615 616 .. code-block:: console 617 618 $ challenger-dbinit --garbagecollect 619 620 621 The Challenger database can be re-initialized using: 622 623 .. code-block:: console 624 625 $ challenger-dbinit --reset 626 627 However, running this command will result in all data in the database 628 being lost.