NOTE

Designing an Open API

A historical note on authentication, signatures, replay protection, rate limiting, and IP allowlists for open APIs.

System DesignCreated Updated 2 min readhistorical

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 + secret to the third party offline.
  • Exchange appid + secret for 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:
    1. Sort all parameters except sign in ascending order by parameter name.
    2. Combine the sorted parameter list into a string such as key1=value1&key2=value2….
    3. Calculate sign with MD5.

2.1.3. Preventing Replay Attacks

  • timestamp + nonce
    • timestamp usually means the parameters are valid within 15 minutes.
    • nonce is 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
    )

4. References

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub