taler-kych-manual.rst (24001B)
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 presentation definition 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 (stable, version 1.70 or later) 109 * PostgreSQL 12 or later 110 * A Swiyu Verifier instance with API access 111 112 113 Building from source 114 -------------------- 115 116 Clone the KyCH repository and build the release binaries: 117 118 .. code-block:: shell-session 119 120 $ git clone https://github.com/example/kych.git 121 $ cd kych/kych_oauth2_gateway 122 $ cargo build --release 123 124 The compiled binaries will be available in ``target/release/``: 125 126 * ``kych-oauth2-gateway`` - the main HTTP server 127 * ``kych-client-management`` - CLI tool for managing clients 128 129 130 Database setup 131 -------------- 132 133 KyCH uses PostgreSQL to store client configurations, verification sessions, 134 authorization codes, and access tokens. 135 136 First, switch to the ``postgres`` user and create a database user and database 137 for KyCH: 138 139 .. code-block:: shell-session 140 141 [root@server]# su - postgres 142 [postgres@server]# createuser kych 143 [postgres@server]# createdb -O kych kych 144 [postgres@server]# exit 145 146 The ``createuser`` command creates a PostgreSQL role named ``kych``. 147 The ``createdb`` command creates a database named ``kych`` owned by the 148 ``kych`` role (``-O kych``). 149 150 Next, initialize the database schema. KyCH uses a versioning system to manage 151 database migrations. First, install the versioning support, then apply the 152 schema migration: 153 154 .. code-block:: shell-session 155 156 $ psql -U kych -d kych -f oauth2_gatewaydb/versioning.sql 157 $ psql -U kych -d kych -f oauth2_gatewaydb/oauth2gw-0001.sql 158 159 The ``versioning.sql`` script installs the ``_v`` schema which tracks applied 160 database patches. The ``oauth2gw-0001.sql`` script creates the ``oauth2gw`` 161 schema with the following tables: 162 163 - ``clients``: Registered OAuth 2.0 clients and their configurations. 164 - ``verification_sessions``: Active and completed verification sessions. 165 - ``authorization_codes``: OAuth 2.0 authorization codes issued after verification. 166 - ``access_tokens``: Bearer tokens issued to clients for accessing user data. 167 168 .. note:: 169 170 The SQL migration files are located in the ``oauth2_gatewaydb/`` directory 171 of the KyCH source tree. Adjust the path if you installed KyCH to a 172 different location. 173 174 175 Configuration 176 ============= 177 178 Configuration file location 179 --------------------------- 180 181 KyCH reads its configuration from a file in the GNU Taler configuration 182 format, the same one the rest of the Taler stack uses: INI-like, with 183 ``@inline@`` includes and ``$VAR`` expansion in paths. The default location is 184 ``/etc/kych/kych.conf``. You can specify an alternative path using the 185 ``--config`` or ``-c`` command-line option. See kych.conf(5) for the format 186 and for the full list of options. 187 188 189 Main configuration section 190 -------------------------- 191 192 The main configuration is specified in the ``[kych-oauth2-gateway]`` section: 193 194 .. code-block:: ini 195 :caption: /etc/kych/kych.conf 196 197 [kych-oauth2-gateway] 198 # Server binding: unix, tcp or systemd 199 SERVE = unix 200 201 # For SERVE = unix: 202 UNIXPATH = /run/kych/kych.sock 203 UNIXPATH_MODE = 660 204 205 # For SERVE = tcp: 206 #BIND_TO = 127.0.0.1 207 #PORT = 8080 208 209 # Database connection string 210 DATABASE = postgres://kych:password@localhost/kych 211 212 # Cryptographic parameters 213 NONCE_BYTES = 32 214 TOKEN_BYTES = 32 215 AUTH_CODE_BYTES = 32 216 AUTH_CODE_TTL_MINUTES = 10 217 218 # Optional: restrict allowed OAuth scopes 219 #ALLOWED_SCOPES = {family_name, given_name, birth_date} 220 221 222 Server binding options 223 ---------------------- 224 225 ``SERVE`` selects one of three ways to obtain the listening socket. For 226 production deployments behind a reverse proxy (recommended), a Unix socket 227 avoids network exposure altogether. 228 229 **Unix socket binding (SERVE = unix):** 230 231 Use this for production deployments behind nginx or another reverse proxy. 232 233 - ``UNIXPATH``: Path to the Unix domain socket file (e.g., ``/run/kych/kych.sock``). 234 Ensure the directory exists and is writable by the KyCH process. 235 - ``UNIXPATH_MODE``: Octal permission mode for the socket file. Use ``660`` 236 so that only the reverse proxy user, which shares KyCH's group, can reach it. 237 238 **TCP binding (SERVE = tcp):** 239 240 Use TCP binding for development or when KyCH must be accessible over the network. 241 242 - ``BIND_TO``: The IP address to bind to. Use ``127.0.0.1`` for localhost-only 243 access or ``0.0.0.0`` to accept connections on all interfaces. 244 - ``PORT``: The TCP port to listen on (e.g., ``8080``). 245 246 **Socket activation (SERVE = systemd):** 247 248 KyCH takes the listening socket from the service manager rather than binding 249 one, so systemd owns the socket, its permissions and its lifetime, and the 250 service can start on the first connection. Nothing else needs to be 251 configured; the Debian package ships a ``kych.socket`` unit for it. 252 253 254 Database configuration 255 ---------------------- 256 257 KyCH requires a PostgreSQL database to persist client registrations, verification 258 sessions, authorization codes, and access tokens. The connection is specified 259 using a standard PostgreSQL connection URI. 260 261 - ``DATABASE``: PostgreSQL connection string in the format 262 ``postgres://user:password@host:port/database``. For local connections, 263 you can omit the port (defaults to 5432). Example: 264 ``postgres://kych:secretpassword@localhost/kych`` 265 266 For production deployments, consider using environment variables or a secrets 267 manager to avoid storing database credentials in plain text configuration files. 268 269 270 Cryptographic parameters 271 ------------------------ 272 273 KyCH generates cryptographically secure random values for nonces, access tokens, 274 and authorization codes. These parameters control the size (entropy) and 275 lifetime of these values. Larger sizes provide more security but result in 276 longer token strings. 277 278 - ``NONCE_BYTES``: Number of random bytes for session nonces. The nonce is 279 used in the ``/authorize/{nonce}`` URL to identify the verification session. 280 Recommended: ``32`` (256 bits of entropy, base64-encoded to ~43 characters). 281 282 - ``TOKEN_BYTES``: Number of random bytes for OAuth 2.0 access tokens. These 283 tokens are used by clients to access the ``/info`` endpoint. 284 Recommended: ``32`` (256 bits of entropy). 285 286 - ``AUTH_CODE_BYTES``: Number of random bytes for OAuth 2.0 authorization codes. 287 These short-lived codes are exchanged for access tokens at the ``/token`` 288 endpoint. Recommended: ``32`` (256 bits of entropy). 289 290 - ``AUTH_CODE_TTL_MINUTES``: How long authorization codes remain valid before 291 expiring. Clients must exchange the code for an access token within this 292 time window. Default: ``10`` minutes. Shorter values are more secure but 293 may cause issues with slow clients. 294 295 296 Verifiable Credential settings 297 ------------------------------ 298 299 These settings define the type of verifiable credential that KyCH will request 300 from the Swiyu Verifier during the OID4VP flow. The configuration must match 301 the credential type supported by your Swiyu Verifier deployment and the 302 credentials available in users' Swiyu Wallets. 303 304 .. code-block:: ini 305 :caption: /etc/kych/kych.conf 306 307 [kych-oauth2-gateway] 308 VC_TYPE = betaid-sdjwt 309 VC_FORMAT = vc+sd-jwt 310 VC_ALGORITHMS = {ES256} 311 VC_CLAIMS = {family_name, given_name, birth_date, age_over_18} 312 313 - ``VC_TYPE``: The verifiable credential type identifier. This must match 314 the credential type configured in the Swiyu Verifier. For Swiss Beta ID 315 credentials, use ``betaid-sdjwt``. 316 317 - ``VC_FORMAT``: The credential format. SD-JWT (Selective Disclosure JWT) 318 credentials use ``vc+sd-jwt``, which allows users to disclose only the 319 specific claims requested. 320 321 - ``VC_ALGORITHMS``: Cryptographic signature algorithms accepted for credential 322 verification, as a bracketed list. The Swiyu ecosystem uses ``{ES256}`` 323 (ECDSA with P-256 and SHA-256). 324 325 - ``VC_CLAIMS``: The complete set of claims that may be requested from the 326 credential. Clients specify which of these claims they need via the 327 ``scope`` parameter in the authorization request. Only claims listed here 328 can be requested. 329 330 **Available claims for Swiss Beta ID (betaid-sdjwt):** 331 332 The Swiss Beta ID credential supports the following claims: 333 334 *Personal identification:* 335 336 - ``family_name``: Family name (surname) 337 - ``given_name``: Given name (first name) 338 - ``birth_date``: Date of birth (ISO 8601 format) 339 - ``sex``: Gender 340 - ``portrait``: Photograph of the credential holder 341 342 *Swiss-specific attributes:* 343 344 - ``place_of_origin``: Place of citizenship (Heimatort), a Swiss legal concept 345 - ``birth_place``: Place of birth 346 - ``nationality``: Nationality/citizenship 347 - ``personal_administrative_number``: Swiss social security number (AHV/AVS number) 348 349 *Age verification (selective disclosure):* 350 351 - ``age_over_16``: Boolean indicating if holder is 16 or older 352 - ``age_over_18``: Boolean indicating if holder is 18 or older 353 - ``age_over_65``: Boolean indicating if holder is 65 or older 354 - ``age_birth_year``: Year of birth (for age verification without full date) 355 356 *Document information:* 357 358 - ``document_number``: Identity document number 359 - ``issuance_date``: When the credential was issued 360 - ``expiry_date``: When the credential expires 361 - ``issuing_authority``: Authority that issued the credential 362 - ``issuing_country``: Country that issued the credential 363 364 *Verification metadata:* 365 366 - ``verification_type``: How the identity was verified (e.g., in-person) 367 - ``verification_organization``: Organization that performed verification 368 - ``reference_id_type``: Type of reference identity document 369 - ``reference_id_expiry_date``: Expiry date of reference document 370 - ``additional_person_info``: Additional personal information 371 372 For most KYC use cases, requesting ``family_name``, ``given_name``, 373 ``birth_date``, and ``age_over_18`` provides sufficient identity verification 374 while minimizing data collection. 375 376 377 Scope restrictions 378 ------------------ 379 380 Optionally, you can restrict which claims clients are allowed to request, 381 regardless of what claims are defined in ``VC_CLAIMS``. This provides an 382 additional policy layer to limit data exposure. 383 384 - ``ALLOWED_SCOPES``: If set, only these claims can be requested by clients. 385 If not set, clients may request any claim from ``VC_CLAIMS``. Format is 386 a bracketed comma-separated list. 387 388 For example, to allow clients to only verify age without accessing personal 389 details: 390 391 .. code-block:: ini 392 393 ALLOWED_SCOPES = {age_over_18, age_over_16} 394 395 396 Client Management 397 ================= 398 399 OAuth 2.0 clients (such as Taler exchanges) must be registered with KyCH before 400 they can initiate KYC verification flows. Each client has its own credentials, 401 redirect URI, and may use a different Swiyu Verifier instance. 402 403 There are two methods to manage clients: 404 405 - **Configuration-based**: Define clients in the configuration file and use the 406 ``sync`` command to load them into the database. Good for infrastructure-as-code 407 deployments. 408 409 - **CLI-based**: Use the ``kych-client-management`` tool to create, update, and 410 delete clients directly in the database. Good for dynamic management. 411 412 413 Configuration-based client management 414 ------------------------------------- 415 416 Clients can be defined in the configuration file using ``[client_*]`` sections. 417 Each section name must start with ``client_`` followed by a unique identifier 418 (e.g., ``[client_exchange]``, ``[client_staging]``). 419 420 .. code-block:: ini 421 :caption: /etc/kych/kych.conf 422 423 [client_exchange] 424 CLIENT_ID = exchange_production 425 CLIENT_SECRET = secret-token:your-secure-secret-here 426 VERIFIER_URL = https://swiyu-verifier.example.com 427 VERIFIER_MANAGEMENT_API_PATH = /management/api/verifications 428 REDIRECT_URI = https://exchange.example.com/kyc/kych-redirect 429 ACCEPTED_ISSUER_DIDS = {did:tdw:trusted_issuer_1, did:tdw:trusted_issuer_2} 430 431 **Client configuration options:** 432 433 - ``CLIENT_ID``: Unique identifier that the client uses to authenticate with 434 KyCH. This is passed in the ``client_id`` parameter during OAuth 2.0 flows 435 and in the ``/setup/{client_id}`` endpoint URL. 436 437 - ``CLIENT_SECRET``: Shared secret for client authentication. The client 438 provides this as a Bearer token in the ``Authorization`` header when calling 439 ``/setup``, and in the request body when calling ``/token``. Use the 440 ``secret-token:`` prefix per RFC 8959 for secrets that should not be logged. 441 KyCH stores the secret as a bcrypt hash in the database. 442 443 - ``VERIFIER_URL``: Base URL of the Swiyu Verifier instance that this client 444 will use for credential verification. Different clients can use different 445 verifier instances (e.g., production vs. staging). 446 447 - ``VERIFIER_MANAGEMENT_API_PATH``: Path to the verifier's management API 448 endpoint for creating verification requests. Default: 449 ``/management/api/verifications``. Only change this if your Swiyu Verifier 450 uses a non-standard API path. 451 452 - ``REDIRECT_URI``: The OAuth 2.0 redirect URI where users are sent after 453 completing verification. This must exactly match the ``redirect_uri`` 454 parameter provided by the client in authorization requests. For security, 455 KyCH rejects requests with mismatched redirect URIs. 456 457 - ``ACCEPTED_ISSUER_DIDS``: List of trusted credential issuer DIDs (Decentralized 458 Identifiers) in bracketed format. Only credentials issued by these DIDs will 459 be accepted. This provides trust anchoring - you specify which issuers you 460 trust to have properly verified identities. Example: 461 ``{did:tdw:issuer1, did:tdw:issuer2}``. 462 463 464 CLI-based client management 465 --------------------------- 466 467 The ``kych-client-management`` tool manages clients directly in the database. 468 All commands require the ``--config`` option to specify the configuration file 469 (for database connection settings). 470 471 **Listing clients:** 472 473 Display all registered clients: 474 475 .. code-block:: shell-session 476 477 $ kych-client-management --config /etc/kych/kych.conf list 478 479 This shows a summary of all clients including their IDs and verifier URLs. 480 481 **Viewing client details:** 482 483 Show full details for a specific client: 484 485 .. code-block:: shell-session 486 487 $ kych-client-management --config /etc/kych/kych.conf show exchange_prod 488 489 This displays all configuration options for the client, except the secret 490 (which is stored as a hash). 491 492 **Creating a client:** 493 494 Register a new OAuth 2.0 client: 495 496 .. code-block:: shell-session 497 498 $ kych-client-management --config /etc/kych/kych.conf create \ 499 --client-id exchange_prod \ 500 --secret "secret-token:your-secure-secret" \ 501 --verifier-url https://swiyu-verifier.example.com \ 502 --redirect-uri https://exchange.example.com/kyc/kych-redirect \ 503 --accepted-issuer-dids "{did:tdw:trusted_issuer}" 504 505 The ``--client-id``, ``--secret``, ``--verifier-url``, and ``--redirect-uri`` 506 options are required. The ``--verifier-api-path`` defaults to 507 ``/management/api/verifications`` if not specified. 508 509 **Updating a client:** 510 511 Modify an existing client's configuration: 512 513 .. code-block:: shell-session 514 515 $ kych-client-management --config /etc/kych/kych.conf update exchange_prod \ 516 --redirect-uri https://new-exchange.example.com/kyc/kych-redirect 517 518 Only the specified options are updated; other settings remain unchanged. 519 520 **Deleting a client:** 521 522 Remove a client from the database: 523 524 .. code-block:: shell-session 525 526 $ kych-client-management --config /etc/kych/kych.conf delete exchange_prod 527 528 You will be prompted for confirmation. Use ``-y`` to skip the prompt: 529 530 .. code-block:: shell-session 531 532 $ kych-client-management --config /etc/kych/kych.conf delete exchange_prod -y 533 534 .. warning:: 535 536 Deleting a client will cascade to all associated sessions and tokens. 537 538 **Synchronizing configuration to database:** 539 540 The ``sync`` command is the bridge between configuration-based and database-based 541 client management. It reads all ``[client_*]`` sections from the configuration 542 file and creates or updates the corresponding clients in the database: 543 544 .. code-block:: shell-session 545 546 $ kych-client-management --config /etc/kych/kych.conf sync 547 548 This is useful for infrastructure-as-code workflows where client configuration 549 is managed in version control and deployed to the database during releases. 550 551 To also remove clients from the database that are no longer defined in the 552 configuration file, use the ``--prune`` flag: 553 554 .. code-block:: shell-session 555 556 $ kych-client-management --config /etc/kych/kych.conf sync --prune 557 558 .. warning:: 559 560 The ``--prune`` flag will delete clients and all their associated sessions 561 and tokens. Use with caution in production. 562 563 564 Deployment 565 ========== 566 567 systemd service 568 --------------- 569 570 Create a systemd service file for KyCH: 571 572 .. code-block:: ini 573 :caption: /etc/systemd/system/kych.service 574 575 [Unit] 576 Description=KyCH OAuth2 Gateway 577 After=network.target postgresql.service 578 579 [Service] 580 Type=simple 581 User=kych 582 Group=kych 583 ExecStart=/usr/local/bin/kych-oauth2-gateway --config /etc/kych/kych.conf 584 Restart=always 585 RestartSec=5 586 587 [Install] 588 WantedBy=multi-user.target 589 590 Enable and start the service: 591 592 .. code-block:: shell-session 593 594 [root@server]# systemctl daemon-reload 595 [root@server]# systemctl enable kych 596 [root@server]# systemctl start kych 597 598 599 Reverse proxy setup 600 ------------------- 601 602 KyCH should be deployed behind a reverse proxy that provides TLS termination, 603 as required by OAuth 2.0. The following example shows an nginx configuration 604 using a Unix socket: 605 606 .. code-block:: nginx 607 :caption: /etc/nginx/sites-available/kych 608 609 upstream kych { 610 server unix:/run/kych/kych.sock; 611 } 612 613 server { 614 listen 443 ssl http2; 615 server_name kych.example.com; 616 617 ssl_certificate /etc/letsencrypt/live/kych.example.com/fullchain.pem; 618 ssl_certificate_key /etc/letsencrypt/live/kych.example.com/privkey.pem; 619 620 location / { 621 proxy_pass http://kych; 622 proxy_set_header Host $host; 623 proxy_set_header X-Real-IP $remote_addr; 624 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 625 proxy_set_header X-Forwarded-Proto $scheme; 626 } 627 } 628 629 Enable the site: 630 631 .. code-block:: shell-session 632 633 [root@server]# ln -s /etc/nginx/sites-available/kych /etc/nginx/sites-enabled/kych 634 [root@server]# nginx -t 635 [root@server]# systemctl reload nginx 636 637 638 Webhook configuration 639 --------------------- 640 641 KyCH receives callbacks from the Swiyu Verifier when a verification request 642 changes state (e.g., when the user presents their credential). The webhook 643 endpoint is ``/notification``. 644 645 When configuring the Swiyu Verifier, set the callback URL to: 646 647 :: 648 649 https://kych.example.com/notification 650 651 This endpoint must be accessible from the Swiyu Verifier service. 652 653 .. note:: 654 655 The Swiyu Verifier must be configured to send notifications to the KyCH 656 gateway. Consult the Swiyu Verifier documentation for details on configuring 657 webhook callbacks. The verifier will POST a JSON payload containing the 658 ``verification_id`` and ``timestamp`` when a verification completes. 659 660 661 Integration with Taler Exchange 662 =============================== 663 664 To use KyCH as a KYC provider for a GNU Taler exchange, configure the 665 exchange with the following settings: 666 667 .. code-block:: ini 668 :caption: /etc/taler-exchange/conf.d/exchange-kyc.conf 669 670 [kyc-provider-kych] 671 LOGIC = oauth2 672 PROVIDED_CHECKS = KYCH_IDENTITY 673 KYC_OAUTH2_AUTHORIZE_URL = https://kych.example.com/authorize 674 KYC_OAUTH2_TOKEN_URL = https://kych.example.com/token 675 KYC_OAUTH2_INFO_URL = https://kych.example.com/info 676 KYC_OAUTH2_CLIENT_ID = exchange_production 677 KYC_OAUTH2_CLIENT_SECRET = secret-token:your-secure-secret 678 KYC_OAUTH2_POST_URL = https://kych.example.com 679 680 The exchange will then use KyCH for KYC verification when the 681 ``KYCH_IDENTITY`` check is required. 682 683 684 OAuth 2.0 endpoints 685 ------------------- 686 687 KyCH provides the following OAuth 2.0 endpoints: 688 689 - ``/authorize`` - Authorization endpoint (redirects user to Swiyu Wallet flow) 690 - ``/token`` - Token endpoint (exchanges authorization code for access token) 691 - ``/info`` - Info endpoint (returns verified identity claims) 692 693 The flow follows standard OAuth 2.0 authorization code grant: 694 695 1. Client redirects user to ``/authorize`` with ``client_id``, ``redirect_uri``, 696 ``response_type=code``, and optional ``state`` parameter. 697 698 2. User completes verification via Swiyu Wallet. 699 700 3. User is redirected to the client's ``redirect_uri`` with an authorization 701 ``code``. 702 703 4. Client exchanges the ``code`` for an ``access_token`` at ``/token``. 704 705 5. Client retrieves user information using the ``access_token`` at ``/info``.