Blog | G5 Cyber Security

Rest API Authentication

TL;DR

This guide shows you how to secure your Restful web services using common authentication methods like API Keys and JSON Web Tokens (JWT). We’ll cover implementation steps, security considerations, and examples.

1. Choose an Authentication Method

Several options exist. Here are two popular choices:

We’ll cover both.

2. API Key Authentication

  1. Generate Keys: Create unique keys for each client application. Use a strong random string generator.
  2. Store Keys Securely: Store the keys on your server (e.g., in a database). Never hardcode them into your application!
  3. Request Header: Clients include their API key in an HTTP header, typically X-API-Key.
  4. Server-Side Validation: Your server checks the incoming API key against its stored list. If valid, allow access; otherwise, return a 401 Unauthorized error.

Example (Python/Flask):

from flask import Flask, request, jsonify

app = Flask(__name__)

API_KEYS = {"client1": "your_api_key", "client2": "another_api_key"}

@app.route('/data')
def get_data():
    api_key = request.headers.get('X-API-Key')
    if api_key in API_KEYS:
        return jsonify({"message": "Data accessed successfully!"})
    else:
        return jsonify({"error": "Unauthorized"}), 401

if __name__ == '__main__':
    app.run(debug=True)

3. JSON Web Token (JWT) Authentication

  1. User Authentication: Users provide credentials (username/password).
  2. Token Generation: Upon successful authentication, your server generates a JWT containing user information and signs it with a secret key.
  3. Token Storage (Client-Side): The client stores the token (e.g., in local storage or a cookie). Be careful storing tokens on the client side – consider security implications!
  4. Request Header: Clients include the JWT in an Authorization header, typically as Bearer <token>.
  5. Server-Side Validation: Your server verifies the token’s signature and extracts user information from it. If valid, allow access; otherwise, return a 401 Unauthorized error.

Example (Python/Flask with PyJWT):

import jwt
from flask import Flask, request, jsonify

payload = {"user_id": "123", "username": "testuser"}
SECRET_KEY = "your-secret-key"

@app.route('/login', methods=['POST'])
def login():
    # Replace with your actual authentication logic
    if request.json["username"] == "testuser" and request.json["password"] == "password":
        token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
        return jsonify({"token": token})
    else:
        return jsonify({"error": "Invalid credentials"}), 401

@app.route('/data')
def get_data():
    token = request.headers.get('Authorization')
    if token:
        try:
            decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ "HS256"])
            return jsonify({"message": f"Data accessed successfully for user {decoded_payload['username']}!"})
        except jwt.ExpiredSignatureError:
            return jsonify({"error": "Token expired"}), 401
        except jwt.InvalidTokenError:
            return jsonify({"error": "Invalid token"}), 401
    else:
        return jsonify({"error": "Unauthorized"}), 401

4. Security Considerations

Exit mobile version