Anyone can call an open API
API security is the set of checks that make sure only the right callers use an API, only as much as they should. Without it, anyone who finds the address can read your data, change it or run up your bill.
You will learn how a service knows who is calling, what a caller may do, and how it stops one caller using too much.
By the end of this lesson
Note
I can protect an API with keys, tokens and limits.
Key words
| Word | What it means |
|---|---|
| Authentication | proving who the caller is |
| Authorisation | deciding what that caller may do |
| API key | a long secret string that names one caller |
| Bearer token | a short-lived secret sent in a header |
| Expiry | the time after which a token stops working |
| Rate limit | a cap on how many requests a caller may make |
The cells students fill in are left blank in this preview.
Your own lab only
Warning
Look at your lab and at the ideas in this lesson. Never try to get past the keys of a service that is not yours. That is a crime under the Computer Misuse Act 1990, even if you only meant to look.
Authentication asks who, authorisation asks what
Authentication answers: who are you? A key or a token proves it. Authorisation answers: what may you do? A reader may list books and only an admin may delete them.
They give different codes. Not proved gives 401. Proved, but not allowed, gives 403.
Worked example: 401 or 403
| Situation | Who is the caller? | Allowed? | Code |
|---|---|---|---|
| No key sent | Unknown | Not asked | 401 |
| A key that does not exist | Unknown | Not asked | 401 |
| Ana's key, listing books | Ana | Yes | 200 |
| Ana's key, deleting a book | Ana | No, she is a reader | 403 |
The cells students fill in are left blank in this preview.
Look at an API that asks for nothing
Run the next two commands to make a books table. Then ask the API for the books with no key and no token. This lab's API is open to your own private network on purpose, so it answers.
A real service on the internet would answer 401 here.
Give psql the password
export PGPASSWORD=shopShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Make the books table
psql -h db -U shop -c "drop table if exists books; create table books (id serial primary key, title text not null, year int not null, available boolean not null default true); insert into books (title, year, available) values ('Maps of the Sea', 1998, true), ('Rivers of Europe', 2004, false), ('Night Trains', 2011, true); notify pgrst, 'reload schema'"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Ask with no key at all
curl -s -o /dev/null -w "%{http_code}\n" "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Send secrets in a header, never the address
A caller sends its secret in the Authorization header. A bearer token is sent as Authorization: Bearer and then the token. An API key is often sent in a header of its own.
Never put a secret in the address. Addresses are written to logs, browser history and shared links. Use HTTPS (HTTP with encryption) so nobody on the way can read the header.
A request that carries a token (an example)
GET /books HTTP/1.1
Host: library.example
Authorization: Bearer 7f3a9c1e5b8d
# This is the lesson's own example. The token is made up.
# The server looks the token up, finds the caller and checks the expiry.Worked example: key and token compared
| Property | API key | Bearer token |
|---|---|---|
| Lifetime | Long, until someone revokes it | Short, often 15 to 60 minutes |
| Names | One application or person | One user session |
| If it leaks | Revoke it and issue another | It stops working at its expiry |
| Stored by the server | As a hash, not as plain text | As a signed value or a lookup |
The cells students fill in are left blank in this preview.
Hash a made-up key
printf 'key-3f9a' | sha256sumShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think a key hidden inside a phone app or a web page is safe. It is not. Anyone can read what an app sends. Keep secrets on a server you control, give each caller a key of its own, and revoke a key that leaks.
A rate limit stops one caller using everything
A rate limit caps how many requests a caller may make in a time. It protects the service from bugs, from one greedy client and from guessing attacks.
A common design is a token bucket. The bucket holds a few tokens and gains one every second up to a maximum. Each request spends one. With none left, the answer is 429.
Worked example: a bucket of three
| Time (seconds) | Tokens before | Request | Tokens after |
|---|---|---|---|
| 0 | 3 | Allowed | 2 |
| 0 | 2 | Allowed | 1 |
| 0 | 1 | Allowed | 0 |
| 0 | 0 | Refused with 429 | 0 |
| 2 | 2 | Allowed | 1 |
The cells students fill in are left blank in this preview.