Problem/Motivation
CyberSource is deprecating HTTP_SIGNATURE messaging on the REST API by September 2026. After that date, requests using HTTP Signature will be rejected. The official documentation now flags HTTP Signature pages with [DEPRECATING]:
The replacement that requires the least operational change for existing merchants is JWT v2 signed with the existing shared secret key pair (HMAC HS256). This path is not deprecated and reuses the same credentials the module already collects
today:
- Set Up a JSON Web Token Message Using Shared Secret Keys
- Construct Messages Using JSON Web Tokens (defines JWT v2:
v-c-jwt-version: 2,
HS256/384/512)
The module currently hardcodes HTTP Signature in src/Plugin/Commerce/PaymentGateway/Flex.php:139:
$merchantConfig->setAuthenticationType('HTTP_SIGNATURE');Note: Message-Level Encryption (MLE) is documented as optional and is not required by the September 2026 deadline. P12-based JWT (RS256) and MLE are intentionally out of scope for this issue and should be addressed in a follow-up alongside a major version bump.
Proposed resolution
Add a backward-compatible JWT v2 (HS256) authentication path to the cybersource_flex gateway, keeping the existing credential fields:
- Add an
auth_typeradio to the gateway form:http_signature(default, current behavior) orjwt_shared_secret. No new credential fields are needed;key_serial_numberandkey_shared_secretare reused. - The official PHP SDK
cybersource/rest-client-phponly implements JWT signing with P12 + RS256, so whenauth_type = jwt_shared_secretthe module signs the JWT itself usingfirebase/php-jwt(already pulled as a transitive SDK
dependency). The token is injected via a Guzzle middleware on the SDK's HTTP client, replacing theAuthorizationheader the SDK would otherwise add. - Build the JWT v2 payload per the spec:
v-c-jwt-version: "2",
v-c-merchant-id,jti(UUID v4),iat,exp = iat + 120,iss(merchant ID),request-method,request-host,request-resource-path, plusdigestand
digestAlgorithm: SHA-256for POST/PUT/PATCH. Header:alg: HS256,kid: <key_serial_number>,typ: JWT. Sign with the base64-decoded shared secret. - Extend
config/schema/commerce_cybersource.schema.ymlwith theauth_typekey, and add ahook_update_Nincommerce_cybersource.installthat setsauth_type = http_signatureon existing gateway entities so update
paths preserve current behavior. - Reference: StandAloneJWTv2.php for the JWT v2 payload structure (the sample uses RS256 + P12; the construction logic is identical apart from the
signing algorithm and key).
Remaining tasks
Add a backward-compatible JWT v2 (HS256) authentication path to the cybersource_flex gateway, keeping the existing credential fields:
- Add an
auth_typeradio to the gateway form:http_signature(default, current behavior) orjwt_shared_secret. No new credential fields are needed;key_serial_numberandkey_shared_secretare reused. - The official PHP SDK
cybersource/rest-client-phponly implements JWT signing with P12 + RS256, so whenauth_type = jwt_shared_secretthe module signs the JWT itself usingfirebase/php-jwt(already pulled as a transitive SDK
dependency). The token is injected via a Guzzle middleware on the SDK's HTTP client, replacing theAuthorizationheader the SDK would otherwise add. - Build the JWT v2 payload per the spec:
v-c-jwt-version: "2",
v-c-merchant-id,jti(UUID v4),iat,exp = iat + 120,iss(merchant ID),request-method,request-host,request-resource-path, plusdigestand
digestAlgorithm: SHA-256for POST/PUT/PATCH. Header:alg: HS256,kid: <key_serial_number>,typ: JWT. Sign with the base64-decoded shared secret. - Extend
config/schema/commerce_cybersource.schema.ymlwith theauth_typekey, and add ahook_update_Nincommerce_cybersource.installthat setsauth_type = http_signatureon existing gateway entities so update
paths preserve current behavior. - Reference: StandAloneJWTv2.php for the JWT v2 payload structure (the sample uses RS256 + P12; the construction logic is identical apart from the
signing algorithm and key).
User interface changes
API changes
None breaking. The gateway plugin gains additional configuration keys. The default value of auth_type is http_signature for new and existing gateways, so the public API surface and runtime behavior of unmigrated sites is unchanged.
Data model changes
A hook_update_N seeds auth_type = http_signature on existing gateway entities. No content entity or database schema changes.
Issue fork commerce_cybersource-3587372
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
plopescComment #3
plopescComment #5
plopescMoving to NR
Comment #6
jsacksick commented@plopesc: We should be able to skip the update hook for setting the auth type right? If we ensure the default is the current signature method (i.e. http_signature)?
Comment #7
plopescYes, we could skip it, assuming that the code will infer that http_signature if empty.
However, I think that might be worth to consolidate the data unless you have other concerns.
Comment #8
plopescHello!
Is there anything we could do to try to push this one forward?
Comment #10
jsacksick commented