JWT (JSON Web Token) is a compact, URL-safe, self-contained format for securely transmitting information between parties. A JWT includes claims, which are statements about a user or system, and is signed by the server. Clients send the JWT in the Authorization header with each API request, allowing the server to verify the token's authenticity and authorize access based on the claims embedded within it.
Configurations
JWT authentication mechanism has the following configurations:
Explicit Token
An explicit token refers to a token that includes clear, detailed information about the user or entity it represents. In the context of JWTs, it makes the token more self-contained by not relying on the server to retrieve user data based solely on the sub (subject) claim.
Configuration | Description |
|---|---|
Token | The JSON Web Token string containing the signed claims. |
Add token as part of the Query Parameter | You can include a token as a query parameter if needed. However, you must use this approach carefully and follow best practices to mitigate security risks. |
Add token as part of the Header | JWT is commonly included in the |
Add token as part of the Cookie | In JWT authentication mechanisms that use cookies, the cookie key refers to the name or identifier of the cookie that stores the JWT. When the server sends a JWT to the client as a cookie, it specifies this key so that both the client and server know which cookie contains the token and can access or update it as needed. |
Dynamic Token
A dynamic token in JWT authentication refers to a token that is generated or updated based on specific conditions, user actions, or contextual requirements. Dynamic tokens provide flexibility in authentication and authorization systems by allowing the token’s contents or validity to adapt to different scenarios.
Configuration | Description |
|---|---|
Secret Key | The secret key is essential for securing tokens, including dynamic tokens. It is used to sign the token and to verify its integrity, allowing the server to ensure that the token has not been altered by unauthorized parties. |
Algorithm | Select from one of the following:
|
Add Claim | In JWT, a claim is a piece of information about an entity, usually the user, encoded in the token. Claims convey details, such as the user's identity, token expiration, roles, or permissions. They appear in the token's payload and define the token's purpose and access capabilities. Claims appear as key-value pairs inside the JWT payload, which is a JSON object. The following is an example of a JWT payload containing claims: In this example:
|
Example
The following are some samples that you can use to configure the JWT mechanism in the Advanced mode:
Sample 1
import os
def jwt_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
attributes = testcase.get_attributes()
token = os.getenv("session_value")
set_key = "sesison"
# set api key in cookie
attributes.set("mutated.http.request.cookie.%s" % set_key, token)
return []Sample 2
import json
import jwt
import requests
import time
import os
TEX_URL_MAP = {
'stg': 'TOKEN_VALUE',
'prd': 'TOKEN_VALUE'
}
SKYLINE_HOSTS_STAGING = ["TOKEN_VALUE"]
PURE1_HOSTS_STAGING = ["sTOKEN_VALUE", "TOKEN_VALUE"]
def sign_id_token():
#iss, priv_pem = load_issuer_and_pem(iss_file, priv_pem_file)
iss = "TOKEN_VALUE"
priv_pem = os.environ.get("TOKEN_PRIVATE_KEY")
# Create a JWT token using my issuer and private key
token = jwt.encode(
{
'iss': iss.strip(),
'iat': int(time.time()),
'exp': int(time.time()) + 36000
},
priv_pem,
algorithm='RS256'
)
return token
def exchange_token(env, id_token, audience = None):
# Make API Call
data = {
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": id_token,
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
}
if audience:
data["audience"] = audience
# Public REST API
response = requests.post("{}/oauth2/v1/token".format(TEX_URL_MAP[env]),
data=data,
verify=False)
#print("[{}] {}".format(response.status_code, response.content))
if response.status_code != 200:
raise Exception("Failed to exchange token with oauth2 server /token call: {}:{}".format(response.status_code,
response.content))
exchange_response = json.loads(response.content)
#print("{}".format(exchange_response))
return exchange_response['access_token']
def get_access_token(env, audience):
print("Generating access token with audience : ", audience)
# Create an internal token
id_token = sign_id_token()
# Exchange my id token for an access token
access_token = exchange_token(env, id_token, audience)
return access_token
def jwt_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
#print("starting hook")
attributes = testcase.get_attributes()
host = attributes.get("mutated.net.host.name")
print("mutated.net.host.name: %s" % host)
if any(sky_host in host for sky_host in SKYLINE_HOSTS_STAGING):
print("skyline host found")
if scanctx.get('token.skyline.staging') != None:
token = scanctx.get('token.skyline.staging')
else:
token = get_access_token('stg', 'skyline')
scanctx.set("token.skyline.staging", token)
elif any(pure1_host in host for pure1_host in PURE1_HOSTS_STAGING):
if scanctx.get('token.pure1.staging') != None:
token = scanctx.get('token.pure1.staging')
else:
token = get_access_token('stg', 'pure1')
scanctx.set("token.pure1.staging", token)
else:
if scanctx.get('token.internal.staging') != None:
token = scanctx.get('token.internal.staging')
else:
token = get_access_token('stg', None)
scanctx.set("token.internal.staging", token)
cookie_name = "access_token"
jwt_value = token
auth_attr = "mutated.http.request.cookie.%s" % cookie_name
attributes.set("mutated.auth.attribute", "mutated.http.request.cookie.%s" % cookie_name)
attributes.set(auth_attr, jwt_value)
return []