|
| 1 | +# Approov Integrations Examples |
| 2 | + |
| 3 | +[Approov](https://approov.io) is an API security solution used to verify that requests received by your backend services originate from trusted versions of your mobile apps, and here you can find a full working example for the Tyk API Gateway that is the base for the Approov [quickstart](/docs/APPROOV_TOKEN_QUICKSTART.md). |
| 4 | + |
| 5 | +For more information about how Approov works and why you should use it you can read the [Approov Overview](/OVERVIEW.md) at the root of this repo. |
| 6 | + |
| 7 | +## Docker Stack |
| 8 | + |
| 9 | +The docker stack provided via the `docker-compose.yml` file in this repo is used for development proposes and if you are familiar with docker then feel free to use it to follow the quickstart before you try it for real in your project. |
| 10 | + |
| 11 | +### Setup Env File |
| 12 | + |
| 13 | +Do not forget to properly setup the `.env` file at the root of this repo before you start the docker stack. |
| 14 | + |
| 15 | +```bash |
| 16 | +cp .env.example .env |
| 17 | +``` |
| 18 | + |
| 19 | +Edit rhe `.env` file and add a dummy secret: |
| 20 | + |
| 21 | +```bash |
| 22 | +APPROOV_BASE64_SECRET=h+CX0tOzdAAR9l15bWAqvq7w9olk66daIH+Xk+IAHhVVHszjDzeGobzNnqyRze3lw/WVyWrc2gZfh3XXfBOmww== |
| 23 | +``` |
| 24 | + |
| 25 | +### Build the Docker Stack |
| 26 | + |
| 27 | +The docker stack is composed by the Tyk API Gateway version `4.1` and Redis version `5.0`. |
| 28 | + |
| 29 | +```bash |
| 30 | +sudo docker-compose build |
| 31 | +``` |
| 32 | + |
| 33 | +### Start the Docker Stack |
| 34 | + |
| 35 | +```bash |
| 36 | +sudo docker-compose up --detach |
| 37 | +``` |
| 38 | + |
| 39 | +Redis may take sometime to be ready to be used by the Tyk API Gateway, therefore wait around 30 to 60 seconds before you setup anything in the Tyk API Gateway. |
| 40 | + |
| 41 | +### Tail the Logs |
| 42 | + |
| 43 | +```bash |
| 44 | +sudo docker-compose logs --follow tyk-gateway |
| 45 | +``` |
| 46 | + |
| 47 | +You can ommit the `tyk-gateway` service to follow the logs of all services declared in the `docker-compose.yml` file. |
| 48 | + |
| 49 | +## The HttpBin API Example |
| 50 | + |
| 51 | +We will create a proxy for httpnin.org where all the API endpoints require a valid and not expired Approov token. |
| 52 | + |
| 53 | +We will use a bash script helper to simplify the usage, while at same time we provide the cURL command being executed by it. You can always see the exact cURL commands being executed by the bash script by invoking it in debug mode `bash -x ./tyk command`. |
| 54 | + |
| 55 | +### Creating the HttpBin API |
| 56 | + |
| 57 | +```bash |
| 58 | +./tyk api-setup |
| 59 | +``` |
| 60 | + |
| 61 | +or |
| 62 | + |
| 63 | +```bash |
| 64 | +curl http://localhost:8002/tyk/apis -i -s -H 'x-tyk-authorization: ___YOUR_TYK_SUPER_SECRET_HERE___' -H 'Content-Type: application/json' -X POST -d '{ |
| 65 | + "api_id": "httpbin.org", |
| 66 | + "slug": "httpbin", |
| 67 | + "name": "HttpBin", |
| 68 | + "org_id": "1", |
| 69 | + "auth": { |
| 70 | + "auth_header_name": "Approov-Token" |
| 71 | + }, |
| 72 | + "definition": { |
| 73 | + "location": "header", |
| 74 | + "key": "x-api-version" |
| 75 | + }, |
| 76 | + "version_data": { |
| 77 | + "not_versioned": true, |
| 78 | + "versions": { |
| 79 | + "Default": { |
| 80 | + "name": "Default", |
| 81 | + "use_extended_paths": true |
| 82 | + } |
| 83 | + } |
| 84 | + }, |
| 85 | + "proxy": { |
| 86 | + "listen_path": "/", |
| 87 | + "target_url": "https://httpbin.org", |
| 88 | + "strip_listen_path": true |
| 89 | + }, |
| 90 | + "active": true, |
| 91 | + "enable_jwt": true, |
| 92 | + "jwt_signing_method": "hmac", |
| 93 | + "jwt_identity_base_field": "iss", |
| 94 | + "jwt_default_policies": [ |
| 95 | + "approov" |
| 96 | + ], |
| 97 | + "jwt_source": "h+CX0tOzd...fh3XXfBOmww==" |
| 98 | +
|
| 99 | + }' |
| 100 | +``` |
| 101 | + |
| 102 | +The output: |
| 103 | + |
| 104 | +``` |
| 105 | +HTTP/1.1 200 OK |
| 106 | +Content-Type: application/json |
| 107 | +Date: Wed, 31 Aug 2022 17:52:02 GMT |
| 108 | +Content-Length: 53 |
| 109 | +
|
| 110 | +{"key":"httpbin.org","status":"ok","action":"added"} |
| 111 | +
|
| 112 | +``` |
| 113 | + |
| 114 | +The important bits in the API definition are the keys `jwt_*` and in the key `auth_header_name`. |
| 115 | + |
| 116 | +### Creating the Approov Security Policy |
| 117 | + |
| 118 | +```bash |
| 119 | +./tyk create-policy |
| 120 | +``` |
| 121 | + |
| 122 | +or |
| 123 | + |
| 124 | +```bash |
| 125 | +curl http://localhost:8002/tyk/policies -i -s -H 'x-tyk-authorization: ___YOUR_TYK_SUPER_SECRET_HERE___' -H 'Content-Type: application/json' -X POST -d ' |
| 126 | + { |
| 127 | + "id": "approov", |
| 128 | + "access_rights": { |
| 129 | + "httpbin.org": { |
| 130 | + "allowed_urls": [], |
| 131 | + "api_id": "httpbin.org", |
| 132 | + "api_name": "HttpBin", |
| 133 | + "versions": [ |
| 134 | + "Default" |
| 135 | + ] |
| 136 | + } |
| 137 | + }, |
| 138 | + "org_id": "1", |
| 139 | + "active": true, |
| 140 | + "name": "Approov", |
| 141 | + "rate": 0, |
| 142 | + "per": 1, |
| 143 | + "quota_max": -1, |
| 144 | + "state": "active", |
| 145 | + "tags": ["Approov"] |
| 146 | + }' |
| 147 | +``` |
| 148 | + |
| 149 | +The output: |
| 150 | + |
| 151 | +```text |
| 152 | +HTTP/1.1 200 OK |
| 153 | +Content-Type: application/json |
| 154 | +Date: Wed, 31 Aug 2022 17:59:29 GMT |
| 155 | +Content-Length: 49 |
| 156 | +
|
| 157 | +{"key":"approov","status":"ok","action":"added"} |
| 158 | +
|
| 159 | +``` |
| 160 | + |
| 161 | +The Approov security policy doesn't require rate limiting or quota usage, because the Approov token check guarantees with a very high degree of confidence that incoming requests are from **what** the Tyk API Gateway expects, a genuine and unmodified instance of your mobile app, not one that is under attack or that has been tampered with. Bots will not succeed on accessing the API because they are not able to provide an Approov token, and fake tokens will fail the signature check. |
| 162 | + |
| 163 | +### Reload the Tyk API Gateway |
| 164 | + |
| 165 | +For the changes to take effect you need to reload or restart your Tyk API Gateway: |
| 166 | + |
| 167 | +```bash |
| 168 | +./tyk reload |
| 169 | +``` |
| 170 | + |
| 171 | +or |
| 172 | + |
| 173 | +```bash |
| 174 | +curl -i -H 'x-tyk-authorization: ___YOUR_TYK_SUPER_SECRET_HERE___' -s http://localhost:8002/tyk/reload/group |
| 175 | +``` |
| 176 | + |
| 177 | +```text |
| 178 | +HTTP/1.1 200 OK |
| 179 | +Content-Type: application/json |
| 180 | +Date: Wed, 31 Aug 2022 18:08:57 GMT |
| 181 | +Content-Length: 29 |
| 182 | +
|
| 183 | +{"status":"ok","message":""} |
| 184 | +``` |
| 185 | + |
| 186 | +Now that we have an API protected with Approov it's time to test it, which we will do in the next section. |
| 187 | + |
| 188 | +### Testing the Approov Integration |
| 189 | + |
| 190 | +Any incoming API request requires a correctly signed and not expired Approov token, thus we will test several scenarios to ensure that the Approov protection works as expected. |
| 191 | + |
| 192 | +The Tyk API Gateway will only forward the API request to the API endpoint `https://httpbin.org/uuid` when the Approov token passes the validation, otherwise the API request will be denied. |
| 193 | + |
| 194 | +#### A valid Approov Token |
| 195 | + |
| 196 | +The Approov token is correctly signed and it's not expired. |
| 197 | + |
| 198 | +```bash |
| 199 | +./tyk test-approov-token valid |
| 200 | +``` |
| 201 | + |
| 202 | +or |
| 203 | + |
| 204 | +```bash |
| 205 | +curl http://localhost:8002/uuid -i -H 'Content-Type: application/json' -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjQ3MDg2ODMyMDUuODkxOTEyfQ.u-rlLdZgaYUjUpU_wWi7nzeMgae_IfcT7asu22ptXn0' |
| 206 | +``` |
| 207 | + |
| 208 | +The output: |
| 209 | + |
| 210 | +```text |
| 211 | +HTTP/1.1 200 OK |
| 212 | +Access-Control-Allow-Credentials: true |
| 213 | +Access-Control-Allow-Origin: * |
| 214 | +Content-Length: 53 |
| 215 | +Content-Type: application/json |
| 216 | +Date: Wed, 31 Aug 2022 18:34:09 GMT |
| 217 | +Server: gunicorn/19.9.0 |
| 218 | +X-Ratelimit-Limit: -1 |
| 219 | +X-Ratelimit-Remaining: 0 |
| 220 | +X-Ratelimit-Reset: 0 |
| 221 | +
|
| 222 | +{ |
| 223 | + "uuid": "afaaeb50-8f15-44cd-b1e2-1a1326bbfede" |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +#### Approov Token with Invalid Signature |
| 228 | + |
| 229 | +The Approov token provided in the header of the request was signed with a secret not known by the Tyk API Gateway to signal that it cannot trust in the incoming API request. |
| 230 | + |
| 231 | +```bash |
| 232 | +./tyk test-approov-token invalid-signature |
| 233 | +``` |
| 234 | + |
| 235 | +or |
| 236 | + |
| 237 | +```bash |
| 238 | +curl http://localhost:8002/uuid -i -H 'Content-Type: application/json' -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjQ3MDg2ODMyMDUuODkxOTEyfQ.u-rlLdZgaYUjUpU_wWi7nasMgae_IfcT7asu22ptXn0' |
| 239 | +``` |
| 240 | + |
| 241 | +The output: |
| 242 | + |
| 243 | +```text |
| 244 | +HTTP/1.1 403 Forbidden |
| 245 | +Content-Type: application/json |
| 246 | +X-Generator: tyk.io |
| 247 | +Date: Wed, 31 Aug 2022 18:40:47 GMT |
| 248 | +Content-Length: 64 |
| 249 | +
|
| 250 | +{ |
| 251 | + "error": "Key not authorized:Unexpected signing method." |
| 252 | +} |
| 253 | +``` |
| 254 | + |
| 255 | +#### Approov Token Expired |
| 256 | + |
| 257 | +The Approov token provided in the header of the request was correctly signed with the same secret known by the Tyk API Gateway, but the `exp` claim is in the past, therefore the token **it's expired** and the incoming API request cannot be served. |
| 258 | + |
| 259 | +```bash |
| 260 | +./tyk test-approov-token expired |
| 261 | +``` |
| 262 | + |
| 263 | +or |
| 264 | + |
| 265 | +```bash |
| 266 | +curl http://localhost:8002/uuid -i -H 'Content-Type: application/json' -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjE2NjE1MzAxMjB9.bdl_U893ahMEV5bEp7mPAIkRr53qVA0iuZs0LqvSIho' |
| 267 | +``` |
| 268 | + |
| 269 | +The output: |
| 270 | + |
| 271 | +```text |
| 272 | +HTTP/1.1 401 Unauthorized |
| 273 | +Content-Type: application/json |
| 274 | +X-Generator: tyk.io |
| 275 | +Date: Wed, 31 Aug 2022 18:43:40 GMT |
| 276 | +Content-Length: 56 |
| 277 | +
|
| 278 | +{ |
| 279 | + "error": "Key not authorized: token has expired" |
| 280 | +} |
| 281 | +``` |
| 282 | + |
| 283 | +#### Approov Token Missing |
| 284 | + |
| 285 | +The Approov token isn't present in the headers of the request therefore the incoming API request cannot be served. |
| 286 | + |
| 287 | +```bash |
| 288 | +./tyk test-approov-token missing |
| 289 | +``` |
| 290 | + |
| 291 | +or |
| 292 | + |
| 293 | +```bash |
| 294 | +curl http://localhost:8002/uuid -i -H 'Content-Type: application/json' |
| 295 | +``` |
| 296 | + |
| 297 | +The output: |
| 298 | + |
| 299 | +```text |
| 300 | +HTTP/1.1 400 Bad Request |
| 301 | +Content-Type: application/json |
| 302 | +X-Generator: tyk.io |
| 303 | +Date: Wed, 31 Aug 2022 18:49:57 GMT |
| 304 | +Content-Length: 46 |
| 305 | +
|
| 306 | +{ |
| 307 | + "error": "Authorization field missing" |
| 308 | +} |
| 309 | +``` |
| 310 | + |
| 311 | +#### Approov Token Empty |
| 312 | + |
| 313 | +The Approov token in the headers of the request is empty therefore the incoming API request cannot be served. |
| 314 | + |
| 315 | +```bash |
| 316 | +./tyk test-approov-token empty |
| 317 | +``` |
| 318 | + |
| 319 | +or |
| 320 | + |
| 321 | +```bash |
| 322 | +curl http://localhost:8002/uuid -i -H 'Content-Type: application/json' -H 'Approov-Token: ' |
| 323 | +``` |
| 324 | + |
| 325 | +The output: |
| 326 | + |
| 327 | +```text |
| 328 | +HTTP/1.1 400 Bad Request |
| 329 | +Content-Type: application/json |
| 330 | +X-Generator: tyk.io |
| 331 | +Date: Wed, 31 Aug 2022 18:49:57 GMT |
| 332 | +Content-Length: 46 |
| 333 | +
|
| 334 | +{ |
| 335 | + "error": "Authorization field missing" |
| 336 | +} |
| 337 | +``` |
| 338 | + |
| 339 | + |
| 340 | +## Issues |
| 341 | + |
| 342 | +If you find any issue while following our instructions then just report it [here](https://github.com/approov/quickstart-tyk-api-gateway-token-check/issues), with the steps to reproduce it, and we will sort it out and/or guide you to the correct path. |
| 343 | + |
| 344 | + |
| 345 | +## Useful Links |
| 346 | + |
| 347 | +If you wish to explore the Approov solution in more depth, then why not try one of the following links as a jumping off point: |
| 348 | + |
| 349 | +* [Approov Free Trial](https://approov.io/signup)(no credit card needed) |
| 350 | +* [Approov Get Started](https://approov.io/product/demo) |
| 351 | +* [Approov QuickStarts](https://approov.io/docs/latest/approov-integration-examples/) |
| 352 | +* [Approov Docs](https://approov.io/docs) |
| 353 | +* [Approov Blog](https://approov.io/blog/) |
| 354 | +* [Approov Resources](https://approov.io/resource/) |
| 355 | +* [Approov Customer Stories](https://approov.io/customer) |
| 356 | +* [Approov Support](https://approov.io/contact) |
| 357 | +* [About Us](https://approov.io/company) |
| 358 | +* [Contact Us](https://approov.io/contact) |
0 commit comments