Get a Pentest and security assessment of your IT network.

Cyber Security

App Authentication: Secure Handshake

TL;DR

This guide shows how two independent apps can securely verify each other’s identity before exchanging data. We’ll use API keys and a simple challenge-response system.

Step 1: Generate API Keys for Each App

Each app needs its own unique API key. Think of these like passwords, but for apps communicating with each other. Don’t share them!

  • App A Key Generation: Use a secure random string generator. For example:
    openssl rand -base64 32

    This will output something like aBcDeFgHiJkLmNoPqRsTuVwXyZ12345

  • App B Key Generation: Repeat the process for App B:
    openssl rand -base64 32

    This will output something different, like zYxWvUtSrQpOnMlKjIhGfEdCbA9876

Store these keys securely within each app’s configuration.

Step 2: App A Initiates the Handshake

  1. App A sends a request to App B, including its API key. The endpoint on App B should be specifically for authentication (e.g., `/authenticate`).
  2. The request might look like this (using JSON):
    POST /authenticate
    {
     "apiKey": "aBcDeFgHiJkLmNoPqRsTuVwXyZ12345"
    }

Step 3: App B Validates App A’s Key

  1. App B receives the request and checks if the provided API key matches its stored list of valid keys.
  2. If the key is invalid, return an error (e.g., HTTP 401 Unauthorized).

Step 4: App B Generates a Challenge

To further verify authenticity and prevent replay attacks, App B generates a random challenge.

  • Challenge Generation: Create a unique string or number. A timestamp combined with a random value is good.
    import time
    import uuid
    challenge = str(time.time()) + uuid.uuid4()
    

Step 5: App B Sends the Challenge to App A

App B sends the generated challenge back to App A.

  • The response might look like this:
    {
     "challenge": "1678886400.12345abcde"
    }

Step 6: App A Signs the Challenge

  1. App A receives the challenge and signs it using its API key. This means combining the challenge with the key and applying a hashing function (like SHA-256).
  2. Signing Example (Python):
    import hashlib
    import hmac
    
    apiKey = "aBcDeFgHiJkLmNoPqRsTuVwXyZ12345"
    challenge = "1678886400.12345abcde"
    message = challenge.encode('utf-8')
    key = apiKey.encode('utf-8')
    hmac_obj = hmac.new(key, message, hashlib.sha256)
    digested = hmac_obj.hexdigest()
    print(digested)

    This will produce a hash like e5b9d430c87a1f8763456789abcdef0123456789

Step 7: App A Sends the Signed Challenge Back to App B

App A sends the signed challenge back to App B.

  • The request might look like this:
    POST /verify_challenge
    {
     "apiKey": "aBcDeFgHiJkLmNoPqRsTuVwXyZ12345",
     "signedChallenge": "e5b9d430c87a1f8763456789abcdef0123456789"
    }

Step 8: App B Verifies the Signature

  1. App B receives the signed challenge and verifies it using App A’s API key. It performs the same hashing process as in Step 6, then compares the result to the received signature.
  2. If the signatures match, authentication is successful! If not, return an error.

Important Considerations

  • HTTPS: Always use HTTPS for all communication to encrypt data in transit.
  • Key Storage: Protect API keys like passwords – never hardcode them directly into your code. Use environment variables or secure configuration files.
  • Rate Limiting: Implement rate limiting on the authentication endpoint to prevent brute-force attacks.
  • Challenge Expiration: Make challenges expire after a short period (e.g., 30 seconds) to reduce the risk of replay attacks.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation