Start learning free

LESSON 13 OF 20 · SECURITY: TOKENS AND SESSIONS

Keep Secrets out of Logs

Practice

Before every route, the shop's log_request writes one line to the log: the method, the path, the JSON body and the Authorization header. Logs are read by far more people and tools than the database: support staff, a log service, whoever finds an old backup. Right now, anyone who reads the log gets Ana's password, her login token and her card number.

Redact before you log: make a copy of the details and put *** in place of each secret value. Change the copy, not the original, so the real values stay where the routes need them. The same idea on another value:

order = {"id": 7, "phone": "555-0199"}
shown = dict(order)
shown["phone"] = "***"
print(shown)   # {'id': 7, 'phone': '***'}
print(order)   # {'id': 7, 'phone': '555-0199'}

The check sends these requests, then reads the log through GET /_test/log:

POST /login   {"email": "ana@example.com", "password": "ana-pass-123"}  →  200  {"token": "<token>"}
POST /orders  {"product_id": 1, "card": "4242 4242 4242 4242"}, with the token  →  201  {"email": "ana@example.com", "paid": true, "product_id": 1}
POST /orders  {"product_id": 2, "card": "5555 5555 5555 4444"}, no token  →  401  {"error": "Login required"}
POST /logout  {"token": "<token>"}  →  200  {"logged_out": true}
POST /login   {"email": "ana@example.com", "password": "ana-pass-124"}  →  401  {"error": "Wrong email or password"}
GET /_test/log  →  200
  POST /login {'email': 'ana@example.com', 'password': '***'}
  POST /orders {'product_id': 1, 'card': '***', 'Authorization': '***'}
  POST /orders {'product_id': 2, 'card': '***'}
  POST /logout {'token': '***'}
  POST /login {'email': 'ana@example.com', 'password': '***'}

Your task: below SECRET_FIELDS, write redact(data): it returns a copy of data where each field named in SECRET_FIELDS that the request has is set to "***". Then, in log_request, pass details through it right above the log line.


Assignment
Follow the Coding Tutorial to write redact and use it in log_request.


Hint
Loop over SECRET_FIELDS, not over the request's fields, and write *** only for a key that is already in the copy: writing a missing key would add it to the log line.


STEP 1 OF 7
    Ctrl + Enter to check