An authentication mechanism based on an API Key is a security method used in software development and web services. It involves generating and providing a unique alphanumeric key (API Key) to identify and authenticate the user or application accessing an API. The server verifies the key before granting access.
Configurations
The API Key authentication mechanism has the following configurations:
Configuration | Description |
|---|---|
API Key | The unique key is generated for the user or the applications. |
Add the API Key as part of the Query parameter | Query Key — The API key to be passed in the URL or query parameters of the API request. The query key is used for authentication and authorization. When using a Query Key, the API Key is appended to the URL as a parameter, usually in the following format: In this example, |
Query value template (optional) — The template defines how to format the API key in the query parameter of an API request URL. Traceable dynamically substitutes the required authentication value into the request at runtime. For example, consider an API endpoint that requires an API key in the query string: In this template, you can replace the The Query Value Template keeps the API Key separate from the code logic, allows you to update it easily, and strengthens security because it does not expose the key in plaintext within the codebase. | |
Add the API Key as part of the Header | Header key — The HTTP header used to pass the API key (commonly The header key is used to secure API endpoints by transmitting authentication credentials in the HTTP headers rather than as part of the URL or request body. |
Header value template (optional) — The template defines how to format the API key in the header of an API request URL. Traceable dynamically substitutes the required authentication value into the header at runtime. Using a header value template increases security and flexibility when transmitting authentication credentials. Following is an example of how you can use a template:
Example Request with Header Value Template —
| |
Add the API Key as part of the Cookie | Cookie key — The Cookie value used for authentication.
|
Cookie value template (optional) — A template to add a cookie value, similar to templates for Query Parameter and Header. |
Example
The following are some samples that you can use to configure an API key authentication in the Advanced mode:
Sample 1
def api_key_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
attributes = testcase.get_attributes()
# Replace these with your actual values
csrf_token_value = "CSRF_TOKEN_VALUE"
session_cookie_value = "SESSION_TOKEN_VALUE"
# Keys for header and cookie
csrf_token_key = "TOKEN_VALUE"
session_cookie_key = "TOKEN_VALUE"
# Set the mutated attribute keys
csrf_token_attr = f"mutated.http.request.header.{csrf_token_key}"
session_cookie_attr = f"mutated.http.request.cookie.{session_cookie_key}"
# Set attributes for CSRF header and session cookie
attributes.set(csrf_token_attr, csrf_token_value)
attributes.set(session_cookie_attr, session_cookie_value)
# Set user roles if needed
# normal_user = True
# bola_user = False
# if normal_user:
# attributes.set("mutated.role.user", csrf_token_value)
# if bola_user:
# attributes.set("mutated.role.bolauser", csrf_token_value)
return []Sample 2
import re
import requests
import os
login_endpoint = "TOKEN_VALUE"
login_form_endpoint = "TOKEN_VALUE"
token_regex = re.compile(r"authenticity_token\" value=\"(.+)\" autocomplete=")
username = os.environ.get("TOKEN_VALUE")
password = os.environ.get("TOKEN_VALUE")
def get_token():
result = requests.get(login_form_endpoint)
if result.status_code != 200:
raise Exception("Failed to get token")
token = token_regex.search(result.text).group(1)
return token, result.cookies.get_dict()
def authenticate(username, password):
token, cookies = get_token()
result = requests.post(login_endpoint, data={
"user[email]": username,
"user[password]": password,
"brand_id": TOKEN_VALUE,
"authenticity_token": token
},
headers={
"Cookie": "; ".join([f"{k}={v}" for k, v in cookies.items()]),
"Content-Type": "application/x-www-form-urlencoded",
}
)
if result.status_code != 200:
raise Exception("Authentication failed with token %s and cookies %s" % (token, cookies), result.text)
if "is incorrect," in result.text:
raise Exception("Authentication failed with token %s and cookies %s" % (token, cookies), result.text)
cookies = result.cookies.get_dict()
cookies = {k: v for k, v in cookies.items() if k.startswith("_")}
return cookies
def api_key_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
attributes = testcase.get_attributes()
cookies = {}
if scanctx.get("custom_cookies", None):
cookies = scanctx.get("custom_cookies")
else:
cookies = authenticate("username", "password")
scanctx.set("custom_cookies", cookies)
#attributes.set("mutated.auth.attribute",
# "mutated.http.request.header.authorization")
for key, value in cookies.items():
attributes.set("mutated.http.request.cookie." + key, value)
return []Sample 3
import requests
import json
from traceable.config import logger
from traceable.ast.context import ScanContext, PluginContext
from traceable.ast.testsuite.assertion import Assertion
from traceable.ast.testsuite.plugin import TestCase
url = "TOKEN_VALUE"
headers = {"Accept-Encoding": "gzip,deflate", "Connection": "Keep-Alive", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8; text/plain", "Cache-Control": "no-cache"}
data = {"client_id": "TOKEN_VALUE", "client_secret": "TOKEN_VALUE", "token_type": "signed"}
# function to get token
def get_token(url, headers, data):
try:
result = requests.post(url, headers=headers, data=data)
if result.status_code != 200:
logger.error(f"Check if connected on the DGN: {result.text}")
return None
if "Bad request," in result.text:
logger.error(f"Wrong/expired client ID or secret: {result.text}")
return None
json_response = result.json()
return json_response.get("access_token")
except Exception as e:
logger.error(f"Error in get_token: {str(e)}")
return None
def api_key_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
attributes = testcase.get_attributes()
# Get token from context or fetch new one
token = scanctx.get("token")
if token is None:
token = get_token(url, headers, data)
if token:
scanctx.set("token", token)
logger.info(f"Retrieved new token: {token}")
else:
return []
# Set the authorization header with the token
if token:
attributes.set("mutated.http.request.header.authorization", f"Authorization: Tut {token}")
return []