Steps to Update the Langman API

Learn the steps for updating the Langman API.

Run server

First, we need to run it just as we did before, except that we need to specify the JWT_SECRET_KEY environment variable.

$ export FLASK_APP=server.app
$ export FLASK_ENV=dev_lite
$ export FLASK_JWT_SECRET_KEY=9876543210blastoff
$ pipenv run flask run --host=0.0.0.0 --port=3000

This terminal will now wait and report on communications to port 3000.

The POST method

We need to open a new terminal to play the game. We show the full access token only the first time to show how long it is, but then abbreviate it using in the other cases.

$ http POST 0.0.0.0:3000/api/auth username=Bobby password=s3cr3t
HTTP/1.0 200 OK
...
{
      "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1Nzk4Mzc2MzcsIm5iZiI6MTU3OTgzNzYzNywianRpIjoiOTQyNTNmZDAtODFjOS00NDMzLWIxYzYtZDg2MTgxZDUyMzQ1IiwiZXhwIjoxNTc5OTI0MDM3LCJpZGVudGl0eSI6Ijc3MWJhM2YwLWI4YmYtMzJkYy04ODhkLTQ3N2E5ODkzNGM5ZCIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyIsInVzZXJfY2xhaW1zIjp7ImFjY2VzcyI6InBsYXllciIsIm5hbWUiOiJCb2JieSJ9fQ.l0OEB-liBD1zNazBxhj_ZMMEpnqRNjdQoY6MlPItrhM"
}
$ export JWT=eyJ0eXAiOiJKV1...pnqRNjdQoY6MlPItrhM

With the token stored as an environment variable, it becomes easier to start a game.

$ http POST 0.0.0.0:3000/api/games language="en" "Authorization:Bearer $JWT"
HTTP/1.0 200 OK
...
{
      "access_token": "eyJ0eXAiOiJKV1Qi...6wH6LM6XmDKzBpBWrDI",
      "game_id": "1ad1e8ca-91da-47d4-8dad-7a72cad0094b",
      "message": "success"
}
$ export JWT2=eyJ0eXAiOiJKV1Qi...6wH6LM6XmDKzBpBWrDI
$ export GAME=1ad1e8ca-91da-47d4-8dad-7a72cad0094b

The GET method

We can get the information of the game using the game ID

$ http GET 0.0.0.0:3000/api/games/$GAME "Authorization:Bearer $JWT"
HTTP/1.0 200 OK
...
{
      "access_token": "eyJ0eXAiOiJKV1Qi...WEueRXwIeTJS7r87eEw",
      "bad_guesses": 0,
      "end_time": null,
      "game_id": "1ad1e8ca-91da-47d4-8dad-7a72cad0094b",
      "guessed": "",
      "lang": "en",
      "player": "771ba3f0-b8bf-32dc-888d-477a98934c9d",
      "result": "active",
      "reveal_word": "_______",
      "source": "Pride and Prejudice by Jane Austen",
      "start_time": 737447,
      "usage": "Mrs. Bennet, accompanied by her two youngest girls, _______
               Netherfield soon after the family breakfast.  ",
      "usage_id": 1916
}

The PUT method

Playing the game is done by guessing letters. This requires both the game ID and the game-specific access token granting access to play that game. After the first response, we leave out most of the response for brevity.

$ http PUT 0.0.0.0:3000/api/games/$GAME letter=e Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 0,
      "end_time": null,
      "game_id": "1ad1e8ca-91da-47d4-8dad-7a72cad0094b",
      "guessed": "e",
      "lang": "en",
      "player": "771ba3f0-b8bf-32dc-888d-477a98934c9d",
      "result": "active",
      "reveal_word": "_e___e_",
      "source": "Pride and Prejudice by Jane Austen",
      "start_time": 737447,
      "usage": "Mrs. Bennet, accompanied by her two youngest girls, _______
               Netherfield soon after the family breakfast.  ",
      "usage_id": 1916
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=a Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 0,
      "guessed": "ea",
      "result": "active",
      "reveal_word": "_ea__e_",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=d Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 0,
      "guessed": "ead",
      "result": "active",
      "reveal_word": "_ea__ed",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=t Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 1,
      "guessed": "eadt",
      "result": "active",
      "reveal_word": "_ea__ed",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=s Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 2,
      "guessed": "eadts",
      "result": "active",
      "reveal_word": "_ea__ed",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=r Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 2,
      "guessed": "eadtsr",
      "result": "active",
      "reveal_word": "rea__ed",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=c Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 2,
      "guessed": "eadtsrc",
      "result": "active",
      "reveal_word": "reac_ed",
}
$ http PUT 0.0.0.0:3000/api/games/$GAME letter=h Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "bad_guesses": 2,
      "guessed": "eadtsrch",
      "result": "won",
      "reveal_word": "reached",
      "secret_word": "reached",
}

In the end, it provides the secret word and changes the result from “active” to “won”. We can see that quotes are placed around Bearer, sometimes before Authorization and sometimes after it. This is to let httpie know that the token is part of the header value. Otherwise, it interprets the space between Bearer and the token as indicating the end of the header value.

The DELETE method

There is always the option to delete the game and even the user. The first command deletes the game, while the second one deletes the user.

$ http DELETE 0.0.0.0:3000/api/games/$GAME Authorization:"Bearer $JWT2"
HTTP/1.0 200 OK
...
{
      "message": "One record deleted"
}
$ http DELETE 0.0.0.0:3000/api/auth Authorization:"Bearer $JWT"
HTTP/1.0 200 OK
...
{
      "deleted_user_id": "771ba3f0-b8bf-32dc-888d-477a98934c9d"
}

Finally, note that all of this security mainly helps with data integrity. Its success in providing access restrictions depends on also having data confidentiality, which is achieved by using HTTPS instead of HTTP. Without HTTPS, the tokens are sent unprotected, and anyone who sees the packets passing between the client and the server can view,and steal, the token. Ensuring that HTTPS is used is a deployment requirement that will be handled automatically by Heroku.

Get hands-on with 1200+ tech skills courses.