|
| 1 | +# Berlin Group TPP Signature Certificate Support |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +API Explorer II now supports the Berlin Group NextGenPSD2 standard. When configured with a TPP (Third Party Provider) certificate, the server automatically signs every request to a Berlin Group API endpoint. This enables PSD2-compliant access to Account Information Services (AIS) and Payment Initiation Services (PIS) through banks that implement the Berlin Group standard. |
| 6 | + |
| 7 | +The feature is entirely optional. Without certificate configuration, the application behaves exactly as before. |
| 8 | + |
| 9 | +## What You Need Before Starting |
| 10 | + |
| 11 | +### 1. TPP Certificate Files |
| 12 | + |
| 13 | +You need two PEM files issued by your bank or a qualified trust service provider (QTSP): |
| 14 | + |
| 15 | +- **Private key** (`private_key.pem`) -- RSA private key used to sign requests |
| 16 | +- **Certificate** (`certificate.pem`) -- The corresponding TPP certificate that the bank uses to verify your signatures |
| 17 | + |
| 18 | +These are typically provided as part of the TPP onboarding process with the bank. |
| 19 | + |
| 20 | +### 2. Key Identifier |
| 21 | + |
| 22 | +The `keyId` string that identifies your certificate to the bank. This is part of the Signature header and typically looks like: |
| 23 | + |
| 24 | +``` |
| 25 | +SN=1082, CA=CN=Your Name, O=YourOrg |
| 26 | +``` |
| 27 | + |
| 28 | +Your bank will tell you what value to use, or it can be derived from the certificate's serial number and issuer. |
| 29 | + |
| 30 | +### 3. OBP-API Backend with Berlin Group Support |
| 31 | + |
| 32 | +The OBP-API instance must serve Berlin Group endpoints at paths like: |
| 33 | + |
| 34 | +``` |
| 35 | +/berlin-group/v1.3/consents |
| 36 | +/berlin-group/v1.3/accounts |
| 37 | +/berlin-group/v1.3/payments/sepa-credit-transfers |
| 38 | +``` |
| 39 | + |
| 40 | +### 4. Redirect URIs (for consent and payment flows) |
| 41 | + |
| 42 | +Two redirect URLs that the bank will use during PSU (Payment Service User) authorization: |
| 43 | + |
| 44 | +- **Success redirect** -- where the user returns after authorizing a consent or payment |
| 45 | +- **Error redirect** -- where the user returns if authorization fails or is cancelled |
| 46 | + |
| 47 | +## Setup |
| 48 | + |
| 49 | +### Step 1: Place Certificate Files |
| 50 | + |
| 51 | +Put your PEM files in a location accessible to the server, for example: |
| 52 | + |
| 53 | +``` |
| 54 | +certs/ |
| 55 | + private_key.pem |
| 56 | + certificate.pem |
| 57 | +``` |
| 58 | + |
| 59 | +### Step 2: Configure Environment Variables |
| 60 | + |
| 61 | +Add these to your `.env` file: |
| 62 | + |
| 63 | +```bash |
| 64 | +# Required -- paths to your certificate files |
| 65 | +VITE_BG_PRIVATE_KEY_PATH=./certs/private_key.pem |
| 66 | +VITE_BG_CERTIFICATE_PATH=./certs/certificate.pem |
| 67 | + |
| 68 | +# Required -- your certificate's key identifier |
| 69 | +VITE_BG_KEY_ID=SN=1082, CA=CN=Your Name, O=YourOrg |
| 70 | + |
| 71 | +# Berlin Group API version (default: v1.3) |
| 72 | +VITE_BG_API_VERSION=v1.3 |
| 73 | + |
| 74 | +# PSU device identification |
| 75 | +VITE_BG_PSU_DEVICE_ID=device-1234567890 |
| 76 | +VITE_BG_PSU_DEVICE_NAME=API-Explorer-II |
| 77 | +VITE_BG_PSU_IP_ADDRESS=192.168.1.42 |
| 78 | + |
| 79 | +# Redirect URIs for consent/payment authorization flows |
| 80 | +VITE_BG_TPP_REDIRECT_URI=https://your-app.com/berlin-group/redirect |
| 81 | +VITE_BG_TPP_NOK_REDIRECT_URI=https://your-app.com/berlin-group/error |
| 82 | +``` |
| 83 | + |
| 84 | +Only `VITE_BG_PRIVATE_KEY_PATH` and `VITE_BG_CERTIFICATE_PATH` are required to enable the feature. Everything else has sensible defaults. |
| 85 | + |
| 86 | +### Step 3: Start the Server |
| 87 | + |
| 88 | +On startup, the console confirms whether the feature is active: |
| 89 | + |
| 90 | +``` |
| 91 | +--- Berlin Group TPP Signature Certificate ----------------------- |
| 92 | +OK Berlin Group TPP Signature Certificate is configured and loaded |
| 93 | + API Version: v1.3 |
| 94 | +----------------------------------------------------------------- |
| 95 | +``` |
| 96 | + |
| 97 | +If not configured, you will see: |
| 98 | + |
| 99 | +``` |
| 100 | +--- Berlin Group TPP Signature Certificate ----------------------- |
| 101 | +Berlin Group TPP Signature Certificate is NOT configured |
| 102 | + Set VITE_BG_PRIVATE_KEY_PATH and VITE_BG_CERTIFICATE_PATH to enable |
| 103 | +----------------------------------------------------------------- |
| 104 | +``` |
| 105 | + |
| 106 | +## How It Works |
| 107 | + |
| 108 | +``` |
| 109 | +Browser API Explorer II OBP-API / Bank |
| 110 | + | | | |
| 111 | + | GET /api/get?path= | | |
| 112 | + | /berlin-group/v1.3/accounts | | |
| 113 | + | (+ optional X-BG-Consent-ID) | | |
| 114 | + | -------------------------------->| | |
| 115 | + | | | |
| 116 | + | Detects "/berlin-group/" in path | |
| 117 | + | Generates signature headers: | |
| 118 | + | - SHA-256 body digest | |
| 119 | + | - RSA-SHA256 digital signature | |
| 120 | + | - TPP certificate | |
| 121 | + | - PSU identification | |
| 122 | + | - Consent-ID (if provided) | |
| 123 | + | Includes OAuth2 Bearer token (if logged in) | |
| 124 | + | | | |
| 125 | + | | GET /berlin-group/v1.3/accounts | |
| 126 | + | | + Digest, Signature, Certificate | |
| 127 | + | | + Consent-ID, PSU headers | |
| 128 | + | | ------------------------------------>| |
| 129 | + | | | |
| 130 | + | | JSON response | |
| 131 | + | |<------------------------------------ | |
| 132 | + | JSON response | | |
| 133 | + |<---------------------------------| | |
| 134 | +``` |
| 135 | + |
| 136 | +Key points: |
| 137 | + |
| 138 | +- **Automatic detection** -- Any request whose path contains `/berlin-group/` triggers the signing. Standard OBP paths (e.g., `/obp/v5.1.0/banks`) are unaffected. |
| 139 | +- **Transparent to the frontend** -- The browser uses the same proxy endpoints (`/api/get`, `/api/create`, `/api/update`, `/api/delete`) as for any other API call. |
| 140 | +- **OAuth2 and TPP coexist** -- If the user is logged in via OAuth2, the Bearer token is sent alongside the TPP signature headers. Both authentication mechanisms can be active on the same request. |
| 141 | +- **Consent-ID passthrough** -- For endpoints that require a consent (e.g., reading accounts), the frontend includes an `X-BG-Consent-ID` header on its request to the proxy. The server forwards it as the standard `Consent-ID` header to the bank. |
| 142 | + |
| 143 | +## Typical PSD2 Workflows |
| 144 | + |
| 145 | +### Account Information (AIS) |
| 146 | + |
| 147 | +1. **Create a consent** -- POST to `/berlin-group/v1.3/consents` with the desired account access scope. The bank returns a `consentId` and a redirect link for the PSU to authorize. |
| 148 | +2. **PSU authorizes** -- The user is redirected to the bank's authorization page, then back to your redirect URI. |
| 149 | +3. **Check consent status** -- GET `/berlin-group/v1.3/consents/{consentId}/status` to confirm it is `valid`. |
| 150 | +4. **Read accounts** -- GET `/berlin-group/v1.3/accounts` with the `Consent-ID` header. |
| 151 | +5. **Read transactions** -- GET `/berlin-group/v1.3/accounts/{accountId}/transactions` with the `Consent-ID` header. |
| 152 | +6. **Delete consent** -- DELETE `/berlin-group/v1.3/consents/{consentId}` when access is no longer needed. |
| 153 | + |
| 154 | +### Payment Initiation (PIS) |
| 155 | + |
| 156 | +1. **Initiate payment** -- POST to `/berlin-group/v1.3/payments/sepa-credit-transfers` with debtor/creditor accounts and amount. The bank returns a `paymentId` and a redirect link. |
| 157 | +2. **PSU authorizes** -- The user is redirected to the bank to authorize the payment, then back to your redirect URI. |
| 158 | +3. **Check payment status** -- GET `/berlin-group/v1.3/payments/sepa-credit-transfers/{paymentId}/status`. |
| 159 | + |
| 160 | +## What Gets Signed |
| 161 | + |
| 162 | +Every outgoing Berlin Group request includes these headers, generated fresh per request: |
| 163 | + |
| 164 | +| Header | Purpose | |
| 165 | +| ------------------------------------------------------ | ------------------------------------------------------------------- | |
| 166 | +| `Date` | Timestamp in RFC 7231 format | |
| 167 | +| `X-Request-ID` | Unique UUID per request for traceability | |
| 168 | +| `Digest` | SHA-256 hash of the request body | |
| 169 | +| `Signature` | RSA-SHA256 digital signature of the digest, date, and request ID | |
| 170 | +| `TPP-Signature-Certificate` | The TPP certificate for the bank to verify the signature | |
| 171 | +| `PSU-Device-ID` / `PSU-Device-Name` / `PSU-IP-Address` | PSU device identification | |
| 172 | +| `TPP-Redirect-URI` / `TPP-Nok-Redirect-URI` | Where to redirect the user after authorization (POST requests only) | |
| 173 | +| `Consent-ID` | References an existing consent (when provided by the frontend) | |
| 174 | + |
| 175 | +## Configuration Reference |
| 176 | + |
| 177 | +| Variable | Required | Default | Description | |
| 178 | +| ------------------------------ | ----------- | --------------------------- | -------------------------------- | |
| 179 | +| `VITE_BG_PRIVATE_KEY_PATH` | Yes | -- | Path to RSA private key PEM file | |
| 180 | +| `VITE_BG_CERTIFICATE_PATH` | Yes | -- | Path to TPP certificate PEM file | |
| 181 | +| `VITE_BG_KEY_ID` | Recommended | `SN=unknown, CA=CN=unknown` | Certificate key identifier | |
| 182 | +| `VITE_BG_API_VERSION` | No | `v1.3` | Berlin Group API version | |
| 183 | +| `VITE_BG_PSU_DEVICE_ID` | No | `device-api-explorer-ii` | PSU device identifier | |
| 184 | +| `VITE_BG_PSU_DEVICE_NAME` | No | `API-Explorer-II` | PSU device name | |
| 185 | +| `VITE_BG_PSU_IP_ADDRESS` | No | `127.0.0.1` | PSU IP address | |
| 186 | +| `VITE_BG_TPP_REDIRECT_URI` | No | (empty) | Success redirect URI | |
| 187 | +| `VITE_BG_TPP_NOK_REDIRECT_URI` | No | (empty) | Error redirect URI | |
| 188 | + |
| 189 | +## Troubleshooting |
| 190 | + |
| 191 | +| Symptom | Cause | Fix | |
| 192 | +| ------------------------------------------ | -------------------------------------------- | --------------------------------------------------------------------------------- | |
| 193 | +| Startup says "NOT configured" | Certificate env vars not set | Set `VITE_BG_PRIVATE_KEY_PATH` and `VITE_BG_CERTIFICATE_PATH` in `.env` | |
| 194 | +| "Failed to load certificate files" in logs | File paths are wrong or files are unreadable | Check that the PEM files exist at the specified paths and have read permissions | |
| 195 | +| Bank returns 401/403 on signed requests | Key ID mismatch or expired certificate | Verify `VITE_BG_KEY_ID` matches what the bank expects; check certificate validity | |
| 196 | +| Berlin Group requests not being signed | Path doesn't contain `/berlin-group/` | Ensure the API path follows the pattern `/berlin-group/{version}/...` | |
| 197 | +| Consent endpoints fail without Consent-ID | Frontend not sending the header | Frontend must include `X-BG-Consent-ID` header for account data endpoints | |
0 commit comments