kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs | Submodules | README | LICENSE

taler-kych-manual.rst (26305B)


      1 ..
      2   This file is part of GNU TALER.
      3 
      4   Copyright (C) 2024, 2025 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 2.1, 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 
     18 KyCH Operator Manual
     19 ####################
     20 
     21 Introduction
     22 ============
     23 
     24 About KyCH
     25 ----------
     26 
     27 KyCH is an OAuth 2.0-compatible gateway for KYC (Know Your Customer) verification
     28 using OID4VP (OpenID for Verifiable Presentations) with Swiyu Verifier.
     29 By redirecting a user-agent to a KyCH service, a client (such as a Taler exchange)
     30 can have KyCH verify the user's identity through verifiable credentials stored
     31 in the user's Swiyu Wallet and obtain the verified identity attributes via
     32 the ``/info`` endpoint.
     33 
     34 
     35 About this manual
     36 -----------------
     37 
     38 This manual targets system administrators who want to install,
     39 operate or integrate a KyCH service.  To report issues
     40 or learn about known limitations, please check our
     41 `bug tracker <https://bugs.taler.net>`__.
     42 
     43 
     44 Architecture overview
     45 ---------------------
     46 
     47 The following diagram shows the high-level architecture of KyCH and its
     48 interactions with other components:
     49 
     50 .. image:: images/kych_overview.jpg
     51    :alt: KyCH Architecture Overview
     52    :align: center
     53 
     54 KyCH acts as an OAuth 2.0 gateway that orchestrates KYC verification between:
     55 
     56 - **Taler Exchange**: The client that requires KYC verification for users.
     57 - **KyCH OAuth2 Gateway**: Manages OAuth 2.0 flows and verification sessions.
     58 - **Swiyu Verifier**: Handles OID4VP verification requests.
     59 - **Swiyu Wallet**: The user's mobile wallet containing verifiable credentials.
     60 
     61 The flow proceeds as follows:
     62 
     63 1. The *resource owner* (user) initiates a KYC-requiring operation with the
     64    *client* (e.g., Taler exchange).
     65 
     66 2. The *client* calls ``POST /setup/{client_id}`` with its client secret to
     67    obtain a ``nonce`` for the verification session.
     68 
     69 3. The *client* redirects the user-agent to ``GET /authorize/{nonce}`` with
     70    OAuth 2.0 parameters (``response_type``, ``client_id``, ``redirect_uri``,
     71    ``state``, ``scope``).
     72 
     73 4. KyCH creates a verification request with the Swiyu Verifier and returns
     74    an HTML page with a QR code (or JSON with ``verification_url``).
     75 
     76 5. The user scans the QR code with their Swiyu Wallet, which retrieves the
     77    DCQL query and requests user consent.
     78 
     79 6. Upon user consent, the Swiyu Wallet presents the requested credentials to
     80    the Swiyu Verifier.
     81 
     82 7. The Swiyu Verifier sends a webhook notification to KyCH's ``/notification``
     83    endpoint with the verification result.
     84 
     85 8. The client polls ``GET /status/{verification_id}`` until the status becomes
     86    ``verified``, then redirects to ``GET /finalize/{verification_id}``.
     87 
     88 9. KyCH redirects the user to the client's ``redirect_uri`` with an
     89    authorization code.
     90 
     91 10. The client exchanges the authorization code for an access token via
     92     ``POST /token``.
     93 
     94 11. The client retrieves the verified identity claims via ``GET /info`` using
     95     the access token.
     96 
     97 
     98 .. _KyCHInstallation:
     99 
    100 Installation
    101 ============
    102 
    103 Prerequisites
    104 -------------
    105 
    106 Before installing KyCH, ensure you have the following:
    107 
    108 * Rust toolchain. The crate is edition 2024, so rustc 1.85 or later.
    109 * PostgreSQL 12 or later
    110 * A Swiyu Verifier instance with API access, of release 3.0.0 or newer --
    111   KyCH sends a DCQL query, and that release dropped the DIF Presentation
    112   Exchange format older verifiers took. The verifier can be run from the
    113   ``swiyu-verifier`` package built from the same source tree; see
    114   :doc:`taler-swiyu-verifier-manual`.
    115 
    116 
    117 From the Debian package
    118 -----------------------
    119 
    120 On Debian, ``kych`` packages the gateway with its systemd unit, a
    121 configuration under ``/etc/kych`` and the database tools:
    122 
    123 .. code-block:: shell-session
    124 
    125    [root@server]# apt install ./kych_*.deb
    126    [root@server]# kych-dbconfig
    127 
    128 ``kych-dbconfig`` creates the PostgreSQL role and database and loads the
    129 schema; afterwards the package keeps the schema up to date by itself, running
    130 ``kych-dbinit`` from its ``postinst`` on every upgrade and restarting the
    131 service if it was running.
    132 
    133 The service ships disabled, since it has nothing to serve before at least one
    134 OAuth 2.0 client is registered. See
    135 ``/usr/share/doc/kych/README.Debian`` for the remaining steps. Note that the
    136 package's defaults live in ``/usr/share/kych/config.d/``, which is read
    137 *before* ``/etc/kych/kych.conf``; put only your own settings in the latter.
    138 
    139 The rest of this manual describes the gateway itself and applies either way.
    140 
    141 
    142 Building from source
    143 --------------------
    144 
    145 Clone the KyCH repository and build the release binaries:
    146 
    147 .. code-block:: shell-session
    148 
    149    $ git clone https://github.com/example/kych.git
    150    $ cd kych/kych_oauth2_gateway
    151    $ cargo build --release
    152 
    153 The compiled binaries will be available in ``target/release/``:
    154 
    155 * ``kych-oauth2-gateway`` - the main HTTP server
    156 * ``kych-client-management`` - CLI tool for managing clients
    157 
    158 
    159 Database setup
    160 --------------
    161 
    162 KyCH uses PostgreSQL to store client configurations, verification sessions,
    163 authorization codes, and access tokens.
    164 
    165 First, switch to the ``postgres`` user and create a database user and database
    166 for KyCH:
    167 
    168 .. code-block:: shell-session
    169 
    170    [root@server]# su - postgres
    171    [postgres@server]# createuser kych
    172    [postgres@server]# createdb -O kych kych
    173    [postgres@server]# exit
    174 
    175 The ``createuser`` command creates a PostgreSQL role named ``kych``.
    176 The ``createdb`` command creates a database named ``kych`` owned by the
    177 ``kych`` role (``-O kych``).
    178 
    179 Next, initialize the database schema with ``kych-dbinit``:
    180 
    181 .. code-block:: shell-session
    182 
    183    $ sudo -u kych kych-dbinit -c /etc/kych/kych.conf
    184 
    185 That is also the command that *upgrades* an existing schema: KyCH uses a
    186 versioning system in which every schema change is a numbered patch file that
    187 registers itself in the ``_v`` schema, and the tool applies those the database
    188 does not have yet, in order. It is idempotent, which is why the Debian package
    189 runs it unattended on every upgrade. ``--dry-run`` reports what it would do.
    190 
    191 The tool reads the patch files from ``SQL_DIR``, which defaults to
    192 ``$DATADIR/sql`` -- ``/usr/share/kych/sql`` for the Debian package, and
    193 ``oauth2_gatewaydb/`` in a source tree, which can be given with
    194 ``--sql-dir``. On a host where the database or the role does not exist yet,
    195 it says so and exits with status 2 instead of failing; ``kych-dbconfig``
    196 creates both and then calls it.
    197 
    198 The first patch creates the ``oauth2gw`` schema with the following tables:
    199 
    200 - ``clients``: Registered OAuth 2.0 clients and their configurations.
    201 - ``verification_sessions``: Active and completed verification sessions.
    202 - ``authorization_codes``: OAuth 2.0 authorization codes issued after verification.
    203 - ``access_tokens``: Bearer tokens issued to clients for accessing user data.
    204 
    205 .. note::
    206 
    207    In a source tree the patch files are in ``oauth2_gatewaydb/``; pass
    208    ``--sql-dir oauth2_gatewaydb`` or set ``SQL_DIR`` in the configuration if
    209    they are somewhere else.
    210 
    211 
    212 Configuration
    213 =============
    214 
    215 Configuration file location
    216 ---------------------------
    217 
    218 KyCH reads its configuration from a file in the GNU Taler configuration
    219 format, the same one the rest of the Taler stack uses: INI-like, with
    220 ``@inline@`` includes and ``$VAR`` expansion in paths. The default location is
    221 ``/etc/kych/kych.conf``. You can specify an alternative path using the
    222 ``--config`` or ``-c`` command-line option. See kych.conf(5) for the format
    223 and for the full list of options.
    224 
    225 
    226 Main configuration section
    227 --------------------------
    228 
    229 The main configuration is specified in the ``[kych-oauth2-gateway]`` section:
    230 
    231 .. code-block:: ini
    232    :caption: /etc/kych/kych.conf
    233 
    234    [kych-oauth2-gateway]
    235    # Server binding: unix, tcp or systemd
    236    SERVE = unix
    237 
    238    # For SERVE = unix:
    239    UNIXPATH = /run/kych/kych.sock
    240    UNIXPATH_MODE = 660
    241 
    242    # For SERVE = tcp:
    243    #BIND_TO = 127.0.0.1
    244    #PORT = 8080
    245 
    246    # Database connection string
    247    DATABASE = postgres://kych:password@localhost/kych
    248 
    249    # Cryptographic parameters
    250    NONCE_BYTES = 32
    251    TOKEN_BYTES = 32
    252    AUTH_CODE_BYTES = 32
    253    AUTH_CODE_TTL_MINUTES = 10
    254 
    255    # Optional: restrict allowed OAuth scopes
    256    #ALLOWED_SCOPES = {family_name, given_name, birth_date}
    257 
    258 
    259 Server binding options
    260 ----------------------
    261 
    262 ``SERVE`` selects one of three ways to obtain the listening socket. For
    263 production deployments behind a reverse proxy (recommended), a Unix socket
    264 avoids network exposure altogether.
    265 
    266 **Unix socket binding (SERVE = unix):**
    267 
    268 Use this for production deployments behind nginx or another reverse proxy.
    269 
    270 -  ``UNIXPATH``: Path to the Unix domain socket file (e.g., ``/run/kych/kych.sock``).
    271    Ensure the directory exists and is writable by the KyCH process.
    272 -  ``UNIXPATH_MODE``: Octal permission mode for the socket file. Use ``660``
    273    so that only the reverse proxy user, which shares KyCH's group, can reach it.
    274 
    275 **TCP binding (SERVE = tcp):**
    276 
    277 Use TCP binding for development or when KyCH must be accessible over the network.
    278 
    279 -  ``BIND_TO``: The IP address to bind to. Use ``127.0.0.1`` for localhost-only
    280    access or ``0.0.0.0`` to accept connections on all interfaces.
    281 -  ``PORT``: The TCP port to listen on (e.g., ``8080``).
    282 
    283 **Socket activation (SERVE = systemd):**
    284 
    285 KyCH takes the listening socket from the service manager rather than binding
    286 one, so systemd owns the socket, its permissions and its lifetime, and the
    287 service can start on the first connection. Nothing else needs to be
    288 configured; the Debian package ships a ``kych.socket`` unit for it.
    289 
    290 
    291 Database configuration
    292 ----------------------
    293 
    294 KyCH requires a PostgreSQL database to persist client registrations, verification
    295 sessions, authorization codes, and access tokens. The connection is specified
    296 using a standard PostgreSQL connection URI.
    297 
    298 -  ``DATABASE``: PostgreSQL connection string in the format
    299    ``postgres://user:password@host:port/database``. For local connections,
    300    you can omit the port (defaults to 5432). Example:
    301    ``postgres://kych:secretpassword@localhost/kych``
    302 
    303 For production deployments, consider using environment variables or a secrets
    304 manager to avoid storing database credentials in plain text configuration files.
    305 
    306 
    307 Cryptographic parameters
    308 ------------------------
    309 
    310 KyCH generates cryptographically secure random values for nonces, access tokens,
    311 and authorization codes. These parameters control the size (entropy) and
    312 lifetime of these values. Larger sizes provide more security but result in
    313 longer token strings.
    314 
    315 -  ``NONCE_BYTES``: Number of random bytes for session nonces. The nonce is
    316    used in the ``/authorize/{nonce}`` URL to identify the verification session.
    317    Recommended: ``32`` (256 bits of entropy, base64-encoded to ~43 characters).
    318 
    319 -  ``TOKEN_BYTES``: Number of random bytes for OAuth 2.0 access tokens. These
    320    tokens are used by clients to access the ``/info`` endpoint.
    321    Recommended: ``32`` (256 bits of entropy).
    322 
    323 -  ``AUTH_CODE_BYTES``: Number of random bytes for OAuth 2.0 authorization codes.
    324    These short-lived codes are exchanged for access tokens at the ``/token``
    325    endpoint. Recommended: ``32`` (256 bits of entropy).
    326 
    327 -  ``AUTH_CODE_TTL_MINUTES``: How long authorization codes remain valid before
    328    expiring. Clients must exchange the code for an access token within this
    329    time window. Default: ``10`` minutes. Shorter values are more secure but
    330    may cause issues with slow clients.
    331 
    332 
    333 Verifiable Credential settings
    334 ------------------------------
    335 
    336 These settings define the type of verifiable credential that KyCH will request
    337 from the Swiyu Verifier during the OID4VP flow. The configuration must match
    338 the credential type supported by your Swiyu Verifier deployment and the
    339 credentials available in users' Swiyu Wallets.
    340 
    341 .. code-block:: ini
    342    :caption: /etc/kych/kych.conf
    343 
    344    [kych-oauth2-gateway]
    345    VC_TYPE = betaid-sdjwt
    346    VC_FORMAT = vc+sd-jwt
    347    VC_ALGORITHMS = {ES256}
    348    VC_CLAIMS = {family_name, given_name, birth_date, age_over_18}
    349 
    350 -  ``VC_TYPE``: The verifiable credential type identifier. This must match
    351    the credential type configured in the Swiyu Verifier. For Swiss Beta ID
    352    credentials, use ``betaid-sdjwt``.
    353 
    354 -  ``VC_FORMAT``: The credential format. SD-JWT (Selective Disclosure JWT)
    355    credentials use ``vc+sd-jwt``, which allows users to disclose only the
    356    specific claims requested.
    357 
    358 -  ``VC_ALGORITHMS``: Cryptographic signature algorithms accepted for credential
    359    verification, as a bracketed list. The Swiyu ecosystem uses ``{ES256}``
    360    (ECDSA with P-256 and SHA-256).
    361 
    362 -  ``VC_CLAIMS``: The complete set of claims that may be requested from the
    363    credential. Clients specify which of these claims they need via the
    364    ``scope`` parameter in the authorization request. Only claims listed here
    365    can be requested.
    366 
    367 **Available claims for Swiss Beta ID (betaid-sdjwt):**
    368 
    369 The Swiss Beta ID credential supports the following claims:
    370 
    371 *Personal identification:*
    372 
    373 - ``family_name``: Family name (surname)
    374 - ``given_name``: Given name (first name)
    375 - ``birth_date``: Date of birth (ISO 8601 format)
    376 - ``sex``: Gender
    377 - ``portrait``: Photograph of the credential holder
    378 
    379 *Swiss-specific attributes:*
    380 
    381 - ``place_of_origin``: Place of citizenship (Heimatort), a Swiss legal concept
    382 - ``birth_place``: Place of birth
    383 - ``nationality``: Nationality/citizenship
    384 - ``personal_administrative_number``: Swiss social security number (AHV/AVS number)
    385 
    386 *Age verification (selective disclosure):*
    387 
    388 - ``age_over_16``: Boolean indicating if holder is 16 or older
    389 - ``age_over_18``: Boolean indicating if holder is 18 or older
    390 - ``age_over_65``: Boolean indicating if holder is 65 or older
    391 - ``age_birth_year``: Year of birth (for age verification without full date)
    392 
    393 *Document information:*
    394 
    395 - ``document_number``: Identity document number
    396 - ``issuance_date``: When the credential was issued
    397 - ``expiry_date``: When the credential expires
    398 - ``issuing_authority``: Authority that issued the credential
    399 - ``issuing_country``: Country that issued the credential
    400 
    401 *Verification metadata:*
    402 
    403 - ``verification_type``: How the identity was verified (e.g., in-person)
    404 - ``verification_organization``: Organization that performed verification
    405 - ``reference_id_type``: Type of reference identity document
    406 - ``reference_id_expiry_date``: Expiry date of reference document
    407 - ``additional_person_info``: Additional personal information
    408 
    409 For most KYC use cases, requesting ``family_name``, ``given_name``,
    410 ``birth_date``, and ``age_over_18`` provides sufficient identity verification
    411 while minimizing data collection.
    412 
    413 
    414 Scope restrictions
    415 ------------------
    416 
    417 Optionally, you can restrict which claims clients are allowed to request,
    418 regardless of what claims are defined in ``VC_CLAIMS``. This provides an
    419 additional policy layer to limit data exposure.
    420 
    421 -  ``ALLOWED_SCOPES``: If set, only these claims can be requested by clients.
    422    If not set, clients may request any claim from ``VC_CLAIMS``. Format is
    423    a bracketed comma-separated list.
    424 
    425 For example, to allow clients to only verify age without accessing personal
    426 details:
    427 
    428 .. code-block:: ini
    429 
    430    ALLOWED_SCOPES = {age_over_18, age_over_16}
    431 
    432 
    433 Client Management
    434 =================
    435 
    436 OAuth 2.0 clients (such as Taler exchanges) must be registered with KyCH before
    437 they can initiate KYC verification flows. Each client has its own credentials,
    438 redirect URI, and may use a different Swiyu Verifier instance.
    439 
    440 There are two methods to manage clients:
    441 
    442 - **Configuration-based**: Define clients in the configuration file and use the
    443   ``sync`` command to load them into the database. Good for infrastructure-as-code
    444   deployments.
    445 
    446 - **CLI-based**: Use the ``kych-client-management`` tool to create, update, and
    447   delete clients directly in the database. Good for dynamic management.
    448 
    449 
    450 Configuration-based client management
    451 -------------------------------------
    452 
    453 Clients can be defined in the configuration file using ``[client_*]`` sections.
    454 Each section name must start with ``client_`` followed by a unique identifier
    455 (e.g., ``[client_exchange]``, ``[client_staging]``).
    456 
    457 .. code-block:: ini
    458    :caption: /etc/kych/kych.conf
    459 
    460    [client_exchange]
    461    CLIENT_ID = exchange_production
    462    CLIENT_SECRET = secret-token:your-secure-secret-here
    463    VERIFIER_URL = https://swiyu-verifier.example.com
    464    VERIFIER_MANAGEMENT_API_PATH = /management/api/verifications
    465    REDIRECT_URI = https://exchange.example.com/kyc/kych-redirect
    466    ACCEPTED_ISSUER_DIDS = {did:tdw:trusted_issuer_1, did:tdw:trusted_issuer_2}
    467 
    468 **Client configuration options:**
    469 
    470 -  ``CLIENT_ID``: Unique identifier that the client uses to authenticate with
    471    KyCH. This is passed in the ``client_id`` parameter during OAuth 2.0 flows
    472    and in the ``/setup/{client_id}`` endpoint URL.
    473 
    474 -  ``CLIENT_SECRET``: Shared secret for client authentication. The client
    475    provides this as a Bearer token in the ``Authorization`` header when calling
    476    ``/setup``, and in the request body when calling ``/token``. Use the
    477    ``secret-token:`` prefix per RFC 8959 for secrets that should not be logged.
    478    KyCH stores the secret as a bcrypt hash in the database.
    479 
    480 -  ``VERIFIER_URL``: Base URL of the Swiyu Verifier instance that this client
    481    will use for credential verification. Different clients can use different
    482    verifier instances (e.g., production vs. staging).
    483 
    484 -  ``VERIFIER_MANAGEMENT_API_PATH``: Path to the verifier's management API
    485    endpoint for creating verification requests. Default:
    486    ``/management/api/verifications``. Only change this if your Swiyu Verifier
    487    uses a non-standard API path.
    488 
    489 -  ``REDIRECT_URI``: The OAuth 2.0 redirect URI where users are sent after
    490    completing verification. This must exactly match the ``redirect_uri``
    491    parameter provided by the client in authorization requests. For security,
    492    KyCH rejects requests with mismatched redirect URIs.
    493 
    494 -  ``ACCEPTED_ISSUER_DIDS``: List of trusted credential issuer DIDs (Decentralized
    495    Identifiers) in bracketed format. Only credentials issued by these DIDs will
    496    be accepted. This provides trust anchoring - you specify which issuers you
    497    trust to have properly verified identities. Example:
    498    ``{did:tdw:issuer1, did:tdw:issuer2}``.
    499 
    500 
    501 CLI-based client management
    502 ---------------------------
    503 
    504 The ``kych-client-management`` tool manages clients directly in the database.
    505 All commands require the ``--config`` option to specify the configuration file
    506 (for database connection settings).
    507 
    508 **Listing clients:**
    509 
    510 Display all registered clients:
    511 
    512 .. code-block:: shell-session
    513 
    514    $ kych-client-management --config /etc/kych/kych.conf list
    515 
    516 This shows a summary of all clients including their IDs and verifier URLs.
    517 
    518 **Viewing client details:**
    519 
    520 Show full details for a specific client:
    521 
    522 .. code-block:: shell-session
    523 
    524    $ kych-client-management --config /etc/kych/kych.conf show exchange_prod
    525 
    526 This displays all configuration options for the client, except the secret
    527 (which is stored as a hash).
    528 
    529 **Creating a client:**
    530 
    531 Register a new OAuth 2.0 client:
    532 
    533 .. code-block:: shell-session
    534 
    535    $ kych-client-management --config /etc/kych/kych.conf create \
    536        --client-id exchange_prod \
    537        --secret "secret-token:your-secure-secret" \
    538        --verifier-url https://swiyu-verifier.example.com \
    539        --redirect-uri https://exchange.example.com/kyc/kych-redirect \
    540        --accepted-issuer-dids "{did:tdw:trusted_issuer}"
    541 
    542 The ``--client-id``, ``--secret``, ``--verifier-url``, and ``--redirect-uri``
    543 options are required. The ``--verifier-api-path`` defaults to
    544 ``/management/api/verifications`` if not specified.
    545 
    546 **Updating a client:**
    547 
    548 Modify an existing client's configuration:
    549 
    550 .. code-block:: shell-session
    551 
    552    $ kych-client-management --config /etc/kych/kych.conf update exchange_prod \
    553        --redirect-uri https://new-exchange.example.com/kyc/kych-redirect
    554 
    555 Only the specified options are updated; other settings remain unchanged.
    556 
    557 **Deleting a client:**
    558 
    559 Remove a client from the database:
    560 
    561 .. code-block:: shell-session
    562 
    563    $ kych-client-management --config /etc/kych/kych.conf delete exchange_prod
    564 
    565 You will be prompted for confirmation. Use ``-y`` to skip the prompt:
    566 
    567 .. code-block:: shell-session
    568 
    569    $ kych-client-management --config /etc/kych/kych.conf delete exchange_prod -y
    570 
    571 .. warning::
    572 
    573    Deleting a client will cascade to all associated sessions and tokens.
    574 
    575 **Synchronizing configuration to database:**
    576 
    577 The ``sync`` command is the bridge between configuration-based and database-based
    578 client management. It reads all ``[client_*]`` sections from the configuration
    579 file and creates or updates the corresponding clients in the database:
    580 
    581 .. code-block:: shell-session
    582 
    583    $ kych-client-management --config /etc/kych/kych.conf sync
    584 
    585 This is useful for infrastructure-as-code workflows where client configuration
    586 is managed in version control and deployed to the database during releases.
    587 
    588 To also remove clients from the database that are no longer defined in the
    589 configuration file, use the ``--prune`` flag:
    590 
    591 .. code-block:: shell-session
    592 
    593    $ kych-client-management --config /etc/kych/kych.conf sync --prune
    594 
    595 .. warning::
    596 
    597    The ``--prune`` flag will delete clients and all their associated sessions
    598    and tokens. Use with caution in production.
    599 
    600 
    601 Deployment
    602 ==========
    603 
    604 systemd service
    605 ---------------
    606 
    607 The Debian package ships a unit; what follows is for an installation built
    608 from source. Note two things that the packaged unit gets right and that are
    609 easy to miss here: the daemon serves its QR-code JavaScript from ``js/``
    610 *relative to the working directory*, so ``WorkingDirectory`` has to point at
    611 the directory holding it; and if the configuration file is kept readable only
    612 by ``root:kych`` -- which it should be, as it holds the client secrets --
    613 then a unit that overrides the primary group with ``Group=`` also needs
    614 ``SupplementaryGroups=kych``, or the daemon cannot read it.
    615 
    616 Create a systemd service file for KyCH:
    617 
    618 .. code-block:: ini
    619    :caption: /etc/systemd/system/kych.service
    620 
    621    [Unit]
    622    Description=KyCH OAuth2 Gateway
    623    After=network.target postgresql.service
    624 
    625    [Service]
    626    Type=simple
    627    User=kych
    628    Group=kych
    629    ExecStart=/usr/local/bin/kych-oauth2-gateway --config /etc/kych/kych.conf
    630    Restart=always
    631    RestartSec=5
    632 
    633    [Install]
    634    WantedBy=multi-user.target
    635 
    636 Enable and start the service:
    637 
    638 .. code-block:: shell-session
    639 
    640    [root@server]# systemctl daemon-reload
    641    [root@server]# systemctl enable kych
    642    [root@server]# systemctl start kych
    643 
    644 
    645 Reverse proxy setup
    646 -------------------
    647 
    648 KyCH should be deployed behind a reverse proxy that provides TLS termination,
    649 as required by OAuth 2.0. The following example shows an nginx configuration
    650 using a Unix socket:
    651 
    652 .. code-block:: nginx
    653    :caption: /etc/nginx/sites-available/kych
    654 
    655    upstream kych {
    656        server unix:/run/kych/kych.sock;
    657    }
    658 
    659    server {
    660        listen 443 ssl http2;
    661        server_name kych.example.com;
    662 
    663        ssl_certificate /etc/letsencrypt/live/kych.example.com/fullchain.pem;
    664        ssl_certificate_key /etc/letsencrypt/live/kych.example.com/privkey.pem;
    665 
    666        location / {
    667            proxy_pass http://kych;
    668            proxy_set_header Host $host;
    669            proxy_set_header X-Real-IP $remote_addr;
    670            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    671            proxy_set_header X-Forwarded-Proto $scheme;
    672        }
    673    }
    674 
    675 Enable the site:
    676 
    677 .. code-block:: shell-session
    678 
    679    [root@server]# ln -s /etc/nginx/sites-available/kych /etc/nginx/sites-enabled/kych
    680    [root@server]# nginx -t
    681    [root@server]# systemctl reload nginx
    682 
    683 
    684 Webhook configuration
    685 ---------------------
    686 
    687 KyCH receives callbacks from the Swiyu Verifier when a verification request
    688 changes state (e.g., when the user presents their credential). The webhook
    689 endpoint is ``/notification``.
    690 
    691 When configuring the Swiyu Verifier, set the callback URL to:
    692 
    693 ::
    694 
    695    https://kych.example.com/notification
    696 
    697 This endpoint must be accessible from the Swiyu Verifier service.
    698 
    699 .. note::
    700 
    701    The Swiyu Verifier must be configured to send notifications to the KyCH
    702    gateway. Consult the Swiyu Verifier documentation for details on configuring
    703    webhook callbacks. The verifier will POST a JSON payload containing the
    704    ``verification_id`` and ``timestamp`` when a verification completes.
    705 
    706 
    707 Integration with Taler Exchange
    708 ===============================
    709 
    710 To use KyCH as a KYC provider for a GNU Taler exchange, configure the
    711 exchange with the following settings:
    712 
    713 .. code-block:: ini
    714    :caption: /etc/taler-exchange/conf.d/exchange-kyc.conf
    715 
    716    [kyc-provider-kych]
    717    LOGIC = oauth2
    718    PROVIDED_CHECKS = KYCH_IDENTITY
    719    KYC_OAUTH2_AUTHORIZE_URL = https://kych.example.com/authorize
    720    KYC_OAUTH2_TOKEN_URL = https://kych.example.com/token
    721    KYC_OAUTH2_INFO_URL = https://kych.example.com/info
    722    KYC_OAUTH2_CLIENT_ID = exchange_production
    723    KYC_OAUTH2_CLIENT_SECRET = secret-token:your-secure-secret
    724    KYC_OAUTH2_POST_URL = https://kych.example.com
    725 
    726 The exchange will then use KyCH for KYC verification when the
    727 ``KYCH_IDENTITY`` check is required.
    728 
    729 
    730 OAuth 2.0 endpoints
    731 -------------------
    732 
    733 KyCH provides the following OAuth 2.0 endpoints:
    734 
    735 -  ``/authorize`` - Authorization endpoint (redirects user to Swiyu Wallet flow)
    736 -  ``/token`` - Token endpoint (exchanges authorization code for access token)
    737 -  ``/info`` - Info endpoint (returns verified identity claims)
    738 
    739 The flow follows standard OAuth 2.0 authorization code grant:
    740 
    741 1. Client redirects user to ``/authorize`` with ``client_id``, ``redirect_uri``,
    742    ``response_type=code``, and optional ``state`` parameter.
    743 
    744 2. User completes verification via Swiyu Wallet.
    745 
    746 3. User is redirected to the client's ``redirect_uri`` with an authorization
    747    ``code``.
    748 
    749 4. Client exchanges the ``code`` for an ``access_token`` at ``/token``.
    750 
    751 5. Client retrieves user information using the ``access_token`` at ``/info``.