challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

test-challenger-revisit.sh (6274B)


      1 #!/bin/bash
      2 # This file is in the public domain.
      3 #
      4 # Tests that re-submitting to /challenge for an already-solved
      5 # validation returns a redirect_url with both ``code`` and ``state``
      6 # query parameters, so the user agent can still be sent back to the
      7 # OAuth client with a usable authorization grant.
      8 #
      9 # Regression test: previously the "already solved" branch returned the
     10 # bare client redirect URI without code/state.
     11 
     12 set -eu
     13 
     14 function exit_skip() {
     15     echo " SKIP: $1"
     16     exit 77
     17 }
     18 
     19 function exit_fail() {
     20     echo " FAIL: $@"
     21     exit 1
     22 }
     23 
     24 function cleanup()
     25 {
     26     for n in $(jobs -p)
     27     do
     28         kill $n 2> /dev/null || true
     29     done
     30     rm -f "$LAST_RESPONSE" "$FILENAME"
     31     wait
     32 }
     33 
     34 LAST_RESPONSE=$(mktemp responseXXXXXX.log)
     35 FILENAME="test-challenger-revisit.txt"
     36 
     37 trap cleanup EXIT
     38 
     39 export PATH="$PATH:."
     40 
     41 echo -n "Testing for jq"
     42 jq -h > /dev/null || exit_skip "jq required"
     43 echo " FOUND"
     44 echo -n "Testing for curl"
     45 curl -h > /dev/null || exit_skip "curl required"
     46 echo " FOUND"
     47 echo -n "Testing for wget"
     48 wget -h > /dev/null || exit_skip "wget required"
     49 echo " FOUND"
     50 echo -n "Testing for challenger-httpd ..."
     51 challenger-httpd -h > /dev/null || exit_skip "challenger-httpd required"
     52 echo " FOUND"
     53 
     54 CONF="test-challenger.conf"
     55 BURL="http://localhost:9967"
     56 REDIRECT_URI="http://client.example.com/"
     57 
     58 echo -n "Initialize challenger database ..."
     59 challenger-dbinit -r -c "${CONF}" &> dbinit.log
     60 echo " OK"
     61 
     62 echo -n "Add challenger client ..."
     63 CLIENT_SECRET="secret-token:secret"
     64 challenger-admin -c "${CONF}" -a "${CLIENT_SECRET}" "${REDIRECT_URI}" &> admin.log
     65 echo " OK"
     66 CLIENT_ID=1
     67 
     68 echo -n "Start challenger-httpd ..."
     69 challenger-httpd -L INFO -c "${CONF}" &> httpd.log &
     70 
     71 for n in $(seq 1 50)
     72 do
     73     echo -n "."
     74     sleep 0.2
     75     OK=0
     76     wget --tries=1 --timeout=1 "${BURL}/config" -o /dev/null -O /dev/null >/dev/null || continue
     77     OK=1
     78     break
     79 done
     80 if [ 1 != $OK ]
     81 then
     82     exit_skip "Failed to launch challenger service"
     83 fi
     84 
     85 
     86 echo -n "Setup new validation process..."
     87 STATUS=$(curl "${BURL}/setup/${CLIENT_ID}" \
     88     -H "Authorization: Bearer ${CLIENT_SECRET}" \
     89     -d '' \
     90     -w "%{http_code}" -s -o $LAST_RESPONSE)
     91 
     92 if [ "$STATUS" != "200" ]
     93 then
     94     exit_fail "Expected 200 OK. Got: $STATUS" $(cat $LAST_RESPONSE)
     95 fi
     96 NONCE=$(jq -r .nonce < "$LAST_RESPONSE")
     97 echo " OK"
     98 
     99 CLIENT_STATE="the-client-state"
    100 CLIENT_SCOPE="the-client-scope"
    101 
    102 echo -n "Initiating user login..."
    103 STATUS=$(curl "${BURL}/authorize/${NONCE}" \
    104     -G \
    105     -H "Accept: application/json" \
    106     --data-urlencode "response_type=code" \
    107     --data-urlencode "client_id=${CLIENT_ID}" \
    108     --data-urlencode "redirect_uri=${REDIRECT_URI}" \
    109     --data-urlencode "state=${CLIENT_STATE}" \
    110     --data-urlencode "scope=${CLIENT_SCOPE}" \
    111     -w "%{http_code}" -s -o $LAST_RESPONSE)
    112 
    113 if [ "$STATUS" != "200" ]
    114 then
    115     exit_fail "Expected 200 OK. Got: $STATUS" $(cat $LAST_RESPONSE)
    116 fi
    117 echo "OK"
    118 
    119 
    120 echo -n "Initiating address submission..."
    121 STATUS=$(curl "${BURL}/challenge/${NONCE}" \
    122     -X POST \
    123     -H "Accept: application/json" \
    124     --data-urlencode "filename=${FILENAME}" \
    125     -w "%{http_code}" -s -o $LAST_RESPONSE)
    126 
    127 if [ "$STATUS" != "200" ]
    128 then
    129     exit_fail "Expected 200 OK. Got: $STATUS" $(cat $LAST_RESPONSE)
    130 fi
    131 echo "OK"
    132 
    133 PIN=$(cat ${FILENAME} | awk '{print $5}')
    134 
    135 echo -n "Initiating PIN ${PIN} submission..."
    136 RESULT=$(curl "${BURL}/solve/${NONCE}" \
    137     -X POST \
    138     -H "Accept: text/html" \
    139     --data-urlencode "pin=${PIN}" \
    140     -w "%{http_code} %{redirect_url}" -s -o $LAST_RESPONSE)
    141 STATUS=$(echo "$RESULT" | awk '{print $1}')
    142 TARGET=$(echo "$RESULT" | awk '{print $2}')
    143 
    144 if [ "$STATUS" != "302" ]
    145 then
    146     exit_fail "Expected 302. Got: $STATUS" $(cat $LAST_RESPONSE)
    147 fi
    148 
    149 # This is where we start to diverge from test-challenger.sh:
    150 # We track the original (good) response and then check we get
    151 # it again later.
    152 
    153 ORIG_CODE=$(echo "$TARGET" | sed -e "s/.*?code=//g" -e "s/&.*//g")
    154 ORIG_STATE=$(echo "$TARGET" | sed -e "s/.*&state=//g")
    155 
    156 if [ -z "${ORIG_CODE}" ]
    157 then
    158     exit_fail "No code returned from /solve"
    159 fi
    160 echo "OK"
    161 
    162 # Now the actual regression test: re-submit the SAME address to
    163 # /challenge.  Since the validation is already solved, the server
    164 # should reply with a JSON ChallengeRedirect whose redirect_url
    165 # carries an OAuth ``code`` (and the original ``state``) so the user
    166 # agent can still be returned to the client with a valid grant.
    167 echo -n "Re-submitting address after solve..."
    168 STATUS=$(curl "${BURL}/challenge/${NONCE}" \
    169     -X POST \
    170     -H "Accept: application/json" \
    171     --data-urlencode "filename=${FILENAME}" \
    172     -w "%{http_code}" -s -o $LAST_RESPONSE)
    173 
    174 if [ "$STATUS" != "200" ]
    175 then
    176     exit_fail "Expected 200 OK on re-submit. Got: $STATUS" $(cat $LAST_RESPONSE)
    177 fi
    178 
    179 TYPE=$(jq -r .type < "$LAST_RESPONSE")
    180 if [ "$TYPE" != "completed" ]
    181 then
    182     exit_fail "Expected type=completed on re-submit. Got: $TYPE" $(cat $LAST_RESPONSE)
    183 fi
    184 
    185 REDIRECT_URL=$(jq -r .redirect_url < "$LAST_RESPONSE")
    186 if [ -z "${REDIRECT_URL}" ] || [ "${REDIRECT_URL}" = "null" ]
    187 then
    188     exit_fail "Missing redirect_url in re-submit response" $(cat $LAST_RESPONSE)
    189 fi
    190 
    191 # redirect_url must have a query string with code= and state=.
    192 case "${REDIRECT_URL}" in
    193     *\?*code=*)
    194         # Good!
    195         ;;
    196     *)
    197         exit_fail "redirect_url has no 'code' parameter: ${REDIRECT_URL}"
    198         ;;
    199 esac
    200 case "${REDIRECT_URL}" in
    201     *state=*)
    202         # Good!
    203         ;;
    204     *)
    205         exit_fail "redirect_url has no 'state' parameter: ${REDIRECT_URL}"
    206         ;;
    207 esac
    208 
    209 REVISIT_URL=$(echo "${REDIRECT_URL}" | sed -e "s/?.*//g")
    210 REVISIT_CODE=$(echo "${REDIRECT_URL}" | sed -e "s/.*?code=//g" -e "s/&.*//g")
    211 REVISIT_STATE=$(echo "${REDIRECT_URL}" | sed -e "s/.*&state=//g")
    212 
    213 if [ "${REVISIT_URL}" != "${REDIRECT_URI}" ]
    214 then
    215     exit_fail "Re-submit redirect URL ${REVISIT_URL} differs from registered ${REDIRECT_URI}"
    216 fi
    217 if [ "${REVISIT_STATE}" != "${CLIENT_STATE}" ]
    218 then
    219     exit_fail "Re-submit state ${REVISIT_STATE} differs from original ${CLIENT_STATE}"
    220 fi
    221 # The code is deterministic over (nonce, secret, scope, address,
    222 # redirect_uri), so re-issuing must produce the same value as /solve did.
    223 if [ "${REVISIT_CODE}" != "${ORIG_CODE}" ]
    224 then
    225     exit_fail "Re-submit code ${REVISIT_CODE} differs from /solve code ${ORIG_CODE}"
    226 fi
    227 echo "OK"
    228 
    229 exit 0