| Internet-Draft | SWT | November 2025 |
| Knauer | Expires 15 May 2026 | [Page] |
The Secure Webhook Token (SWT) is a specialized JSON Web Token (JWT) format designed for securely authorizing and verifying webhook requests.
It defines a set of claims to ensure that the token is explicitly tied to webhook events and that its integrity can be reliably validated by the recipient.
A key feature of SWT is the introduction of a unique claim, webhook, which encapsulates webhook-specific information, such as the event type.¶
By providing a structured and secure approach to webhook authentication, SWT aims to be a lightweight and flexible solution while maintaining compatibility with typical JWT structures. It is designed with the best practices in mind and may serve as a foundation for future standardization efforts.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 15 May 2026.¶
Copyright (c) 2025 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The increasing use of webhooks requires a secure,
standardized approach to authorizing webhook requests and verifying the sender's authenticity.
The SWT specifies a JWT-based [RFC7519] structure, which includes unique claims tailored for webhook events.
This specification mandates that all tokens must be transmitted using HTTP POST requests (see Section 9.3.3 of [RFC9110]),
with the token in the Authorization header and event data in the request body, ensuring secure transmission and optimal compatibility with typical HTTP implementations.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in "Key words for use in RFCs to Indicate Requirement Levels" [RFC2119]. The interpretation should only be applied when the terms appear in all capital letters.¶
This specification defines required claims within the JWT [RFC7519] payload and prescribes the transport protocol as HTTP POST.
The token is transmitted in the Authorization header while the webhook event data is sent in the request body.
These constraints ensure interoperability across diverse systems and provide a consistent approach to webhook authorization.¶
SWTs MUST be transmitted using HTTP POST requests only.¶
The token MUST be included in the Authorization header using the Bearer scheme, while the webhook event data MUST be sent in the request body.¶
Recommended Maximum Token Size: While there is no strict maximum size for an SWT, the token SHOULD be kept concise, containing only essential claims to support efficient processing and minimize resource usage. The primary use case for SWTs is to securely authorize and trigger events rather than transmit extensive data.¶
Header Size Considerations: Since the token is transmitted in the Authorization header, implementers should be aware of HTTP header size limits imposed by web servers and proxies. Most web servers have a default maximum HTTP header size of 8KB, though this can often be configured. To ensure broad compatibility, the JWT token itself SHOULD remain reasonably small (typically under 4KB).¶
An SWT comprises the following:¶
"HS256" (HMAC SHA-256).¶
"SWT". This distinguishes Secure Webhook Tokens from generic JWTs and enables recipients to recognize and process them according to this specification.¶
{
"alg": "HS256",
"typ": "SWT"
}
¶
The payload contains the following required claims, carefully chosen to meet security and identification needs:¶
webhook: Custom claim specific to this specification.¶
"payment.received").
Values should be concise to meet the size limitations.¶
iss (Issuer): Identifies the token issuer (e.g., a unique name or domain representing the entity). Short, meaningful identifiers are RECOMMENDED.¶
sub (Subject) (OPTIONAL): While traditionally used to identify the principal subject of a JWT, the sub claim is not required in SWT.
The purpose and intent of the token are unambiguously defined by the webhook claim.
However, implementers may include sub to identify the system, service, or entity responsible for issuing the token, if such context is useful.¶
exp (Expiration): Specifies the token's expiration time as a Unix timestamp. This prevents tokens from being valid indefinitely.¶
nbf (Not Before): Specifies the earliest time the token is considered valid, using a Unix timestamp.¶
iat (Issued At): The timestamp when the token was issued, aiding in token age validation.¶
jti (JWT ID): A unique identifier for each token to prevent replay attacks. A UUID [RFC9562] or similarly unique identifier is RECOMMENDED.¶
{
"webhook": {
"event": "ping"
},
"exp": 1733987961,
"nbf": 1733987661,
"iat": 1733987661,
"iss": "swt.example.com",
"jti": "2020B14D-C365-4BCF-84CD-5D423E0C6687"
}
¶
{
"webhook": {
"event": "delivery.scheduled",
"hash": "sha-256:22b793b7c031e6a3...05ba920b",
"retry_count": 0
},
"exp": 1733987961,
"nbf": 1733987661,
"iat": 1733987661,
"iss": "swt.example.com",
"jti": "2020B14D-C365-4BCF-84CD-5D423E0C6687"
}
¶
{
"webhook": {
"event": "delivery.scheduled",
"hash": "sha-256:22b793b7c031e6a3...05ba920b",
"retry_count": 3
},
"exp": 1733988561,
"nbf": 1733988261,
"iat": 1733988261,
"iss": "swt.example.com",
"jti": "A1C3F89E-2F4D-4A8C-9B2E-7D8F1C3E5A9B"
}
¶
To ensure payload integrity when sending body content, webhook requests with non-empty request bodies MUST include a cryptographic hash of the request body. Instead of using separate fields for algorithm and value, a self-describing hash field is used:¶
"webhook": {
"event": "delivery.scheduled",
"hash": "sha-512:f8f24b01df358f10...df03db5cf"
}
¶
This format allows the server to interpret the algorithm dynamically and accept or reject hashes according to its policies.¶
[algo, value] = hash.split(":")
¶
Compare computed hash with value.¶
Signature Verification: Receivers MUST verify the JWT signature before processing any claims. Failure to verify signatures exposes the system to token forgery attacks. The signature algorithm specified in the JWT header MUST be validated against an allowlist of permitted algorithms to prevent algorithm substitution attacks.¶
Algorithm Allowlist: Implementations MUST maintain an allowlist of acceptable signing algorithms and MUST reject
tokens signed with algorithms not on this list. The alg header parameter MUST be checked against this allowlist
before signature verification. Implementations MUST NOT accept the "none" algorithm.¶
HTTPS Transport: It is REQUIRED that SWT transmissions occur over HTTPS to ensure the token's confidentiality and protect against man-in-the-middle attacks.¶
Replay Protection: The jti claim MUST be checked for uniqueness on the server side to prevent replay attacks.
Each jti value MUST only be accepted once within the token's validity period. Implementations SHOULD maintain
a cache or registry of seen jti values.¶
Expiration and Time-based Claims: Systems MUST validate the exp, nbf, and iat claims to ensure tokens
are used only within their intended validity period. Implementations SHOULD allow for a small clock skew tolerance
(e.g., 60 seconds) when validating time-based claims to account for clock differences between systems.
Token lifetime (exp - iat) SHOULD be kept as short as practical for the use case, typically not exceeding
15 minutes for most webhook scenarios.¶
Key Management: Symmetric keys used for HMAC algorithms MUST be generated using a cryptographically secure random number generator and MUST have sufficient entropy (at least 256 bits for HS256). Keys SHOULD be rotated regularly. For asymmetric algorithms, private keys MUST be protected with appropriate access controls and SHOULD be stored in hardware security modules (HSMs) or key management systems (KMS) when available.¶
Hash Algorithm Security: When validating request body hashes, implementations MUST reject weak or deprecated hash algorithms (e.g., MD5, SHA-1). Only cryptographically strong hash algorithms (SHA-256 or stronger) SHOULD be accepted.¶
Respect Header Limits: Excessively large JWT tokens SHOULD be avoided to ensure compatibility with HTTP header size limits imposed by web servers and proxies.¶
Retry Count Validation: When the retry_count field is present, receivers SHOULD validate that its value is
reasonable to prevent abuse. Implementations MAY enforce maximum retry limits (e.g., rejecting requests with
retry_count exceeding a configured threshold) to protect against resource exhaustion attacks. The retry_count
value MUST be a non-negative integer. Receivers SHOULD consider implementing exponential backoff expectations and
MAY reject retry attempts that arrive too quickly relative to the retry_count value. Additionally, the combination
of jti and retry_count should be considered together: each retry attempt MUST use a unique jti value, as
retries represent distinct delivery attempts even when delivering the same event.¶
SWT's use of standard HTTP POST requests with JWT-based authorization ensures broad compatibility with existing web infrastructure. The structure is simple to parse and easy to integrate with existing JWT validation libraries. The separation of token metadata and event data provides flexibility for various payload sizes and content types.¶
To maintain a balance between security and usability, SWTs are RECOMMENDED to be used as JSON Web Signatures (JWS) [RFC7515], specifically signed JWTs. This provides data integrity and allows the recipient to verify the token's authenticity. The following signing algorithms are suggested for SWTs, as they offer a secure yet practical approach:¶
While these symmetric algorithms are RECOMMENDED for ease of use and efficiency, other supported algorithms, including asymmetric methods such as RS256 (RSA with SHA-256) or ES256 (ECDSA with SHA-256), MAY also be used if needed based on security requirements or system constraints.¶
In addition to JWS, SWT allows the use of the JSON Web Encryption (JWE) [RFC7516] standard if encrypted JWTs are required to protect sensitive data within the token. JWE adds encryption layers to JWTs, providing confidentiality as well as integrity protection, which may be appropriate in contexts where tokens contain sensitive information.¶
This specification registers the application/swt+jwt media type in the IANA "Media Types" registry in the manner described in [RFC6838].¶
The following entries should be registered:¶
Additional information:¶
This document updates the IANA "JSON Web Token Claims" registry for JWT Claim Names. Following the format in Section 10.1.1 of [RFC7519], the following should be registered.¶
webhook claim
The webhook claim is a JSON object that describes the event to be triggered and optionally includes metadata about the event data sent in the request body.¶
It consists of the following fields:¶
event: A case-sensitive string describing the name of the webhook event. It should be concise and specific (e.g., "order.created").¶
hash (OPTIONAL): The hash algorithm and the hash digest of the request body payload (hex-encoded) (see Section 6).¶
retry_count (OPTIONAL): A non-negative integer indicating the delivery attempt number for this webhook event.¶
0 indicates the initial delivery attempt (no retry).¶
1 or greater indicates a retry attempt (e.g., 1 = first retry, 2 = second retry).¶
Implementers MAY restrict the set of supported algorithms based on their security posture.¶
Senders and receivers SHOULD agree on supported algorithms in advance.¶
Although NOT RECOMMENDED, it may be necessary to send non-JSON event data via SWT. The HTTP Content-Type header SHOULD be set accordingly.¶
To validate an SWT, the receiving system MUST perform the following checks:¶
Authorization header MUST be a valid JWT with all required claims.¶
webhook claim with an event field.¶
Body and Hash Validation:¶
If any validation check fails, the server SHOULD respond with an appropriate HTTP error code:¶
Webhook claim:¶
{
"webhook": {
"event": "ping"
},
"exp": 1733987961,
"nbf": 1733987661,
"iat": 1733987661,
"iss": "swt.example.com",
"jti": "2020B14D-C365-4BCF-84CD-5D423E0C6687"
}
¶
POST request:¶
POST /webhook HTTP/1.1 Content-Length: 0 Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... Host: example.com¶
Webhook claim:¶
{
"webhook": {
"event": "issue.opened",
"hash": "sha-256:04ef96c3bc56b3c4...200a5353",
"retry_count": 0
},
"exp": 1733987961,
"nbf": 1733987661,
"iat": 1733987661,
"iss": "swt.example.com",
"jti": "2020B14D-C365-4BCF-84CD-5D423E0C6687"
}
¶
POST request:¶
POST /webhook HTTP/1.1
Content-Length: 6123
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Host: example.com
{
"action": "opened",
"issue": {
"url": "https://api.github.com/repos/octocat/...",
"number": 1347,
...
},
"repository" : {
"id": 1296269,
"full_name": "octocat/Hello-World",
"owner": {
"login": "octocat",
"id": 1,
...
},
...
},
"sender": {
"login": "octocat",
"id": 1,
...
}
}
¶
The Secure Webhook Token (SWT) format provides a secure, interoperable, and efficient solution for webhook authentication. Its focus on signed payloads, minimal overhead, and clear transport guidance makes it suitable for modern web service ecosystems.¶