NOTE
Designing an Open API
A historical note on authentication, signatures, replay protection, rate limiting, and IP allowlists for open APIs.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What Is an Open API?
A normal API is only open to internal systems. An open API is exposed to external systems, so other systems or software can call the API to obtain data from this system.
2. How to Design an Open API
2.1. Security
Open APIs mainly face three security problems:
- Is the request identity trustworthy? – authentication
- Have the request parameters been tampered with? – signature
- Is the request unique? – replay-attack prevention
2.1.1. Authentication
- Used to solve the identity-trust problem.
- Distribute an
appid + secretto the third party offline. - Exchange
appid + secretfor a token, and then authenticate API requests with the token.- The reason for using a token is to minimize how often the user’s plaintext password is exposed.
2.1.2. Signature
- Used to prevent parameter tampering.
- Process:
- Sort all parameters except
signin ascending order by parameter name. - Combine the sorted parameter list into a string such as
key1=value1&key2=value2…. - Calculate
signwith MD5.
- Sort all parameters except
2.1.3. Preventing Replay Attacks
timestamp + noncetimestampusually means the parameters are valid within 15 minutes.nonceis a unique random string used to identify each signed request. By giving every request a unique identifier, the server can prevent a request from being reused.- To prevent these two parameters from being tampered with, include them in the signature.
- You can also use only
nonce + Redis expire.
2.2. Rate Limiting
- Counter.
- Leaky bucket.
- Token bucket.
How to Design a Rate-Limiting System
2.3. IP Allowlist
- Control access-party IPs with an allowlist.
3. Example
3.1. Third-Party Identity Verification Flow
Only flow-level pseudocode is retained below. It illustrates authentication, signing, request correlation, and result lookup without mapping to any specific provider or internal system.
-
Start verification
credentials = load_provider_credentials() access_token = authenticate(credentials) challenge = request_verification_challenge(access_token, subject_ref) nonce = generate_random_nonce() signature = sign(challenge, nonce, request_metadata) request_id = generate_request_id() save_request_mapping(subject_ref, request_id) verification_id = create_verification( access_token, request_id, verification_payload, signature ) -
Query the verification result
access_token = authenticate(credentials) challenge = request_query_challenge(access_token, subject_ref) nonce = generate_random_nonce() signature = sign(challenge, nonce, request_metadata) result = query_verification_result( access_token, verification_id, signature )
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub