Get a Pentest and security assessment of your IT network.

Cyber Security

Client Binding for Auth Tokens

TL;DR

Your authorization tokens aren’t tied to specific applications (clients). This means a token generated for one app could potentially be used in another, which is a security risk. We’ll fix this by ensuring each token includes information about the client it was issued to and verifying that information on every request.

Solution Guide

  1. Understand Client Binding: Client binding means including details about the application requesting the token within the token itself. This usually involves adding a ‘client_id’ claim (a piece of data) to the token.
    • Why it matters: Prevents tokens from being used across different applications, limiting damage if one app is compromised.
  2. Configure Your Authorization Server: Most authorization servers (like Keycloak, Auth0, or Okta) allow you to configure which claims are included in the tokens they issue.
    • Keycloak Example: In your client settings within the Keycloak admin console, ensure that ‘Client ID’ is mapped as a claim in the ‘Mappers’ section.
    • Auth0 Example: In Auth0’s Application Settings, go to API Authorizations and configure the Client ID claim under ‘Advanced Settings’.
  3. Modify Your Token Generation Code (if applicable): If you’re generating tokens yourself (not using a standard server), ensure your code adds the ‘client_id’ as a claim.
    // Example in Python with PyJWT
    payload = {
      'user_id': user.id,
      'client_id': client.id // Add the client ID here
    }
    token = jwt.encode(payload, secret_key, algorithm='HS256')
  4. Update Your Resource Server (API) Code: This is where you verify that the token’s ‘client_id’ matches the expected client for the requested resource.
    • Token Decoding: First, decode the token to extract its claims.
    • Client ID Verification: Check if the decoded token contains a ‘client_id’ claim and that it corresponds to the application making the request.
  5. Example Resource Server Code (Python with Flask):
    from flask import Flask, request
    import jwt
    
    app = Flask(__name__)
    
    @app.route('/protected')
    def protected():
      token = request.headers.get('Authorization')
      if not token:
        return 'Token missing', 401
    
    try:
        payload = jwt.decode(token, secret_key, algorithms=['HS256'])
        client_id = payload.get('client_id')
        expected_client_id = 'your-app-client-id' # Replace with the expected client ID for this route
    
        if client_id != expected_client_id:
          return 'Invalid client', 403
    
        return 'Protected resource accessed!', 200
    
    except jwt.ExpiredSignatureError:
      return 'Token expired', 401
    except jwt.DecodeError:
      return 'Invalid token', 401
  6. Testing:
    • Generate a token for Client A.
    • Attempt to use that token with Client B’s API endpoint. The request should be rejected (HTTP 403 Forbidden).
    • Verify the correct client ID is being extracted from valid tokens.
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