test_merchant_mfa.sh (11341B)
1 #!/usr/bin/env bash 2 # This file is part of TALER 3 # Copyright (C) 2025 Taler Systems SA 4 # 5 # TALER is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as 7 # published by the Free Software Foundation; either version 3, or 8 # (at your option) any later version. 9 # 10 # TALER is distributed in the hope that it will be useful, but 11 # WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public 16 # License along with TALER; see the file COPYING. If not, see 17 # <http://www.gnu.org/licenses/> 18 # 19 set -eu 20 21 . setup.sh 22 23 24 # Launch system. 25 setup \ 26 -c "test_merchant_mfa.conf" \ 27 -m 28 LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX) 29 30 echo -n "Configuring a merchant admin instance ..." 31 32 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 33 -H 'Authorization: Bearer secret-token:super_secret' \ 34 http://localhost:9966/management/instances \ 35 -d '{"auth":{"method":"external"},"id":"admin","name":"default","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ 36 -w "%{http_code}" -s \ 37 -o "$LAST_RESPONSE") 38 39 if [ "$STATUS" != "204" ] 40 then 41 jq < "$LAST_RESPONSE" 42 exit_fail "Expected 204 ok, instance created. got: $STATUS" 43 fi 44 45 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 46 -H 'Authorization: Bearer secret-token:super_secret' \ 47 http://localhost:9966/private/accounts \ 48 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/43?receiver-name=user43"}' \ 49 -w "%{http_code}" -s \ 50 -o "$LAST_RESPONSE") 51 52 53 if [ "$STATUS" != "200" ] 54 then 55 jq < "$LAST_RESPONSE" 56 exit_fail "Expected 200 OK. Got: $STATUS" 57 fi 58 59 echo " OK" 60 echo -n "Self-provision instance ..." 61 62 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 63 http://localhost:9966/instances \ 64 -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ 65 -w "%{http_code}" -s \ 66 -o "$LAST_RESPONSE") 67 68 if [ "$STATUS" != "202" ] 69 then 70 jq < "$LAST_RESPONSE" 71 exit_fail "Expected 202 Accepted. Got: $STATUS" 72 fi 73 echo " OK" 74 75 C1=$(jq -r .challenges[0].challenge_id < "$LAST_RESPONSE") 76 C2=$(jq -r .challenges[1].challenge_id < "$LAST_RESPONSE") 77 78 echo -n "Requesting challenge $C1 " 79 80 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 81 "http://localhost:9966/challenge/$C1" \ 82 -d '{}' \ 83 -w "%{http_code}" -s \ 84 -o "$LAST_RESPONSE") 85 86 if [ "$STATUS" != "200" ] 87 then 88 jq < "$LAST_RESPONSE" 89 exit_fail "Expected 200 OK. Got: $STATUS" 90 fi 91 echo "OK" 92 93 TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') 94 ADDR=$(cat /tmp/test-merchant-email-address.txt) 95 96 if [ "$ADDR" != "self@example.com" ] 97 then 98 exit_fail "Expected address 'self@example.com'. Got: $ADDR" 99 fi 100 101 echo -n "Sending challenge $C1 solution " 102 103 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 104 "http://localhost:9966/challenge/$C1/confirm" \ 105 -d '{"tan":"'"$TAN"'"}' \ 106 -w "%{http_code}" -s \ 107 -o "$LAST_RESPONSE") 108 109 if [ "$STATUS" != "204" ] 110 then 111 jq < "$LAST_RESPONSE" 112 exit_fail "Expected 204 OK. Got: $STATUS" 113 fi 114 echo "OK" 115 116 117 echo -n "Requesting challenge $C2 " 118 119 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 120 "http://localhost:9966/challenge/$C2" \ 121 -d '{}' \ 122 -w "%{http_code}" -s \ 123 -o "$LAST_RESPONSE") 124 125 if [ "$STATUS" != "200" ] 126 then 127 jq < "$LAST_RESPONSE" 128 exit_fail "Expected 200 OK. Got: $STATUS" 129 fi 130 echo "OK" 131 132 TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1 | awk '{print $1}') 133 134 echo -n "Sending challenge $C2 solution " 135 136 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 137 "http://localhost:9966/challenge/$C2/confirm" \ 138 -d '{"tan":"'"$TAN"'"}' \ 139 -w "%{http_code}" -s \ 140 -o "$LAST_RESPONSE") 141 142 if [ "$STATUS" != "204" ] 143 then 144 jq < "$LAST_RESPONSE" 145 exit_fail "Expected 204 OK. Got: $STATUS" 146 fi 147 echo "OK" 148 149 150 echo -n "Retrying instance creation with other body " 151 152 STATUS=$(curl \ 153 -H "Content-Type: application/json" \ 154 -H "Taler-Challenge-Ids: $C1,$C2" \ 155 -X POST \ 156 http://localhost:9966/instances \ 157 -d '{"auth":{"method":"external"},"id":"self","name":"change","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ 158 -w "%{http_code}" -s \ 159 -o "$LAST_RESPONSE") 160 161 if [ "$STATUS" != "202" ] 162 then 163 jq < "$LAST_RESPONSE" 164 exit_fail "Expected 202 Accepted. Got: $STATUS" 165 fi 166 echo "OK" 167 168 169 170 echo -n "Retrying instance creation with original body " 171 172 STATUS=$(curl \ 173 -H "Content-Type: application/json" \ 174 -H "Taler-Challenge-Ids: $C1,$C2" \ 175 -X POST \ 176 http://localhost:9966/instances \ 177 -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ 178 -w "%{http_code}" -s \ 179 -o "$LAST_RESPONSE") 180 181 if [ "$STATUS" != "204" ] 182 then 183 jq < "$LAST_RESPONSE" 184 exit_fail "Expected 204 OK. Got: $STATUS" 185 fi 186 187 echo "OK" 188 189 190 echo -n "Unauthorized trigger MFA to add bank account " 191 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 192 -H 'Authorization: Bearer secret-token:bad_password' \ 193 http://localhost:9966/instances/self/private/accounts \ 194 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/44?receiver-name=user44"}' \ 195 -w "%{http_code}" -s \ 196 -o "$LAST_RESPONSE") 197 198 if [ "$STATUS" != "401" ] 199 then 200 jq < "$LAST_RESPONSE" 201 exit_fail "Expected 401 Forbidden. Got: $STATUS" 202 fi 203 204 echo " OK" 205 206 207 echo -n "Do NOT Trigger MFA to add first bank account " 208 STATUS=$(curl \ 209 -H "Content-Type: application/json" \ 210 -X POST \ 211 -H 'Authorization: Bearer secret-token:pass1234' \ 212 http://localhost:9966/instances/self/private/accounts \ 213 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/44?receiver-name=user44"}' \ 214 -w "%{http_code}" -s \ 215 -o "$LAST_RESPONSE") 216 217 if [ "$STATUS" != "200" ] 218 then 219 jq < "$LAST_RESPONSE" 220 exit_fail "Expected 200 OK. Got: $STATUS" 221 fi 222 223 echo " OK" 224 225 226 echo -n "Trigger MFA to add 2nd bank account with 2-FA authorization " 227 STATUS=$(curl \ 228 -H "Content-Type: application/json" \ 229 -X POST \ 230 -H 'Authorization: Bearer secret-token:pass1234' \ 231 http://localhost:9966/instances/self/private/accounts \ 232 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/45?receiver-name=user45"}' \ 233 -w "%{http_code}" -s \ 234 -o "$LAST_RESPONSE") 235 236 if [ "$STATUS" != "202" ] 237 then 238 jq < "$LAST_RESPONSE" 239 exit_fail "Expected 202 Accepted. Got: $STATUS" 240 fi 241 242 echo " OK" 243 244 245 C1=$(jq -r .challenges[0].challenge_id < "$LAST_RESPONSE") 246 247 # Delete old TANs. 248 rm /tmp/test-merchant-*-tan.txt 249 echo -n "Requesting challenge $C1 " 250 251 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 252 "http://localhost:9966/challenge/$C1" \ 253 -d '{}' \ 254 -w "%{http_code}" -s \ 255 -o "$LAST_RESPONSE") 256 257 if [ "$STATUS" != "200" ] 258 then 259 jq < "$LAST_RESPONSE" 260 exit_fail "Expected 200 OK. Got: $STATUS" 261 fi 262 echo "OK" 263 264 TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') 265 ADDR=$(cat /tmp/test-merchant-email-address.txt) 266 267 if [ "$ADDR" != "self@example.com" ] 268 then 269 exit_fail "Expected address 'self@example.com'. Got: $ADDR" 270 fi 271 272 echo -n "Sending challenge $C1 solution " 273 274 STATUS=$(curl \ 275 -H "Content-Type: application/json" \ 276 -X POST \ 277 "http://localhost:9966/challenge/$C1/confirm" \ 278 -d '{"tan":"'"$TAN"'"}' \ 279 -w "%{http_code}" -s \ 280 -o "$LAST_RESPONSE") 281 282 if [ "$STATUS" != "204" ] 283 then 284 jq < "$LAST_RESPONSE" 285 exit_fail "Expected 204 OK. Got: $STATUS" 286 fi 287 echo "OK" 288 289 echo -n "Finally, add 2nd bank account " 290 STATUS=$(curl \ 291 -X POST \ 292 -H "Content-Type: application/json" \ 293 -H "Taler-Challenge-Ids: $C1" \ 294 -H 'Authorization: Bearer secret-token:pass1234' \ 295 http://localhost:9966/instances/self/private/accounts \ 296 -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/45?receiver-name=user45"}' \ 297 -w "%{http_code}" -s \ 298 -o "$LAST_RESPONSE") 299 300 if [ "$STATUS" != "200" ] 301 then 302 jq < "$LAST_RESPONSE" 303 exit_fail "Expected 200 OK. Got: $STATUS" 304 fi 305 306 echo " OK" 307 308 309 echo -n "Begin forgotten password reset " 310 STATUS=$(curl \ 311 -X POST \ 312 -H "Content-Type: application/json" \ 313 http://localhost:9966/instances/self/forgot-password \ 314 -d '{"method":"token","password":"amnesia"}' \ 315 -w "%{http_code}" -s \ 316 -o "$LAST_RESPONSE") 317 318 if [ "$STATUS" != "202" ] 319 then 320 jq < "$LAST_RESPONSE" 321 exit_fail "Expected 202 Accepted. Got: $STATUS" 322 fi 323 324 echo " OK" 325 326 C1=$(jq -r .challenges[0].challenge_id < "$LAST_RESPONSE") 327 C2=$(jq -r .challenges[1].challenge_id < "$LAST_RESPONSE") 328 329 echo -n "Requesting challenge $C1 " 330 331 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 332 "http://localhost:9966/challenge/$C1" \ 333 -d '{}' \ 334 -w "%{http_code}" -s \ 335 -o "$LAST_RESPONSE") 336 337 if [ "$STATUS" != "200" ] 338 then 339 jq < "$LAST_RESPONSE" 340 exit_fail "Expected 200 OK. Got: $STATUS" 341 fi 342 echo "OK" 343 344 TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') 345 ADDR=$(cat /tmp/test-merchant-email-address.txt) 346 347 if [ "$ADDR" != "self@example.com" ] 348 then 349 exit_fail "Expected address 'self@example.com'. Got: $ADDR" 350 fi 351 352 echo -n "Sending challenge $C1 solution " 353 354 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 355 "http://localhost:9966/challenge/$C1/confirm" \ 356 -d '{"tan":"'"$TAN"'"}' \ 357 -w "%{http_code}" -s \ 358 -o "$LAST_RESPONSE") 359 360 if [ "$STATUS" != "204" ] 361 then 362 jq < "$LAST_RESPONSE" 363 exit_fail "Expected 204 OK. Got: $STATUS" 364 fi 365 echo "OK" 366 367 368 echo -n "Requesting challenge $C2 " 369 370 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 371 "http://localhost:9966/challenge/$C2" \ 372 -d '{}' \ 373 -w "%{http_code}" -s \ 374 -o "$LAST_RESPONSE") 375 376 if [ "$STATUS" != "200" ] 377 then 378 jq < "$LAST_RESPONSE" 379 exit_fail "Expected 200 OK. Got: $STATUS" 380 fi 381 echo "OK" 382 383 TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1 | awk '{print $1}') 384 385 echo -n "Sending challenge $C2 solution " 386 387 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 388 "http://localhost:9966/challenge/$C2/confirm" \ 389 -d '{"tan":"'"$TAN"'"}' \ 390 -w "%{http_code}" -s \ 391 -o "$LAST_RESPONSE") 392 393 if [ "$STATUS" != "204" ] 394 then 395 jq < "$LAST_RESPONSE" 396 exit_fail "Expected 204 OK. Got: $STATUS" 397 fi 398 echo "OK" 399 400 echo -n "Complete password reset " 401 STATUS=$(curl \ 402 -X POST \ 403 -H "Content-Type: application/json" \ 404 -H "Taler-Challenge-Ids: $C1,$C2" \ 405 http://localhost:9966/instances/self/forgot-password \ 406 -d '{"method":"token","password":"amnesia"}' \ 407 -w "%{http_code}" -s \ 408 -o "$LAST_RESPONSE") 409 410 if [ "$STATUS" != "204" ] 411 then 412 jq < "$LAST_RESPONSE" 413 exit_fail "Expected 204 No content. Got: $STATUS" 414 fi 415 416 echo " OK" 417 418 419 420 421 422 echo "TEST PASSED" 423 424 exit 0