Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Json Rpc Sign Bundle Laravel Package

tourze/json-rpc-sign-bundle

A Symfony bundle that adds request signing and verification to JSON-RPC services, helping secure client-server communication with configurable signature handling. Integrates with Tourze's JSON-RPC stack for tamper-evident API calls.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the diff before you read the docs. The 0.1.0 release was published with an empty notes body — the only artifact is the compare link (0.0.3...0.1.0). Before adding this to a project, run composer require tourze/json-rpc-sign-bundle:^0.1.0 in a scratch app and diff the two tags locally:

git clone https://github.com/tourze/json-rpc-sign-bundle
git diff 0.0.3..0.1.0 -- src/ composer.json

A 0.0.x → 0.1.x bump in a pre-1.0 package almost always means a config-key rename, a changed default algorithm, or a signature-payload change. Those are exactly the changes that silently break a working integration, so budget an hour for this.

Where to look first, in order:

  1. composer.json — check whether it pulls symfony/framework-bundle or symfony/dependency-injection with a hard constraint. Despite the -bundle suffix, what you actually want in Laravel is the underlying signer/verifier services, not the DI extension.
  2. src/DependencyInjection/Configuration.php — the Symfony config tree is the de-facto option reference. Every knob the bundle exposes lives here, and the README usually lags it.
  3. src/Resources/config/services.yaml — shows which concrete class is bound to each interface, i.e. your extension points.
  4. The signer/verifier classes themselves — read the canonicalization routine, because that is where 90% of integration bugs come from.

First use case: signing outbound JSON-RPC calls to a partner gateway. Concretely, resolve the signer from the container (or instantiate it directly with a shared secret) and wrap your HTTP call so the signature is computed over the exact body bytes you send:

$payload = json_encode($rpcBody, JSON_UNESCAPED_SLASHES);
$headers = $signer->sign($payload); // timestamp, nonce, signature headers

Http::withHeaders($headers)->withBody($payload, 'application/json')->post($endpoint);

If you only need this, skip the bundle registration entirely and depend on the underlying library — you'll avoid dragging Symfony's container into a Laravel app for one HMAC.

Implementation Patterns

Decorate your JSON-RPC client, don't sprinkle signing calls. Whether you use laravel/http, Saloon, or a hand-rolled client, put signing in one place — a Guzzle middleware or a Saloon request plugin — so every RPC method is signed identically. Signing at the call site is how you end up with one endpoint whose body was serialized with different flags and therefore fails verification.

Verify inbound with middleware, before the RPC layer. For webhook or callback routes, register a route middleware that reconstructs the signature from the raw request body:

$raw = $request->getContent();          // not $request->all()
abort_unless($verifier->verify($raw, $request->headers->all()), 401);

Return 401 on signature failure and 400 on malformed JSON — collapsing the two makes debugging partner integrations miserable.

Per-endpoint configuration, not global config. Secrets, algorithm, and header names usually differ per counterparty. Model this as a config array keyed by integration name and bind the right signer instance via a small factory or a container when() context:

$this->app->when(AcmeRpcClient::class)
    ->needs(SignerInterface::class)
    ->give(fn () => $this->app->make(SignerFactory::class)->for('acme'));

Freeze the clock and nonce source in tests. The two things that make signature tests flaky are time and randomness. Extract a ClockInterface and a nonce generator, bind deterministic fakes in the test container, and assert against a hardcoded expected header value. A test that only asserts "verification passes" won't catch a canonicalization regression; a test with a golden signature string will.

Log verification failures at warning with the reason, not the body. You need to distinguish "bad signature" (config/key mismatch) from "stale timestamp" (clock drift) from "replayed nonce" (a real attack or a retry bug). Never log the secret or the full signed payload — payloads in this domain routinely carry credentials.

Store nonces where multiple app servers can see them. If the package ships an in-memory replay guard, it is single-process only. Swap it for a cache-backed store (Cache::store('redis')->add("nonce:{$n}", 1, $ttl)) with a TTL matching your accepted timestamp window.

Gotchas and Tips

  • The -bundle suffix is a trap in Laravel. Symfony bundles are bootstrapped by Kernel::registerBundles(), which Laravel doesn't have. If the classes you need only exist as DI-managed services, either instantiate them manually or write a thin service provider that re-declares the wiring — don't try to shoehorn Bundle registration into a provider's register().
  • Canonicalization is the failure mode. Signature mismatches are almost never a wrong secret. They're a json_encode flag difference (JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE), a float serialized as 1 vs 1.0, an empty array encoded as [] vs {}, or header keys lowercased on one side. Sign and send the same byte string; never re-encode between signing and transport.
  • Timestamp windows and clock skew. A ±300s default will fail against a partner with a drifting NTP daemon. Make the window configurable, and log the observed delta on rejection so you can tell the partner a number instead of "it doesn't work."
  • Pre-1.0 semver means pin exactly. Use "tourze/json-rpc-sign-bundle": "0.1.*" rather than ^0.1. With no release notes, a 0.1.1 patch could still change a default you depend on. Re-read the diff before every bump and re-run your golden-signature test.
  • Secrets in config:cache. Anything placed under config/*.php is baked into the cached config file. Keep the actual secret in .env and reference it via env() only inside the config file — never pass secrets into a config array built at runtime from a DB, or config:cache will silently freeze a stale value.
  • Extension points. The interfaces bound in services.yaml are your seam — a custom SignerInterface implementation lets you support a new algorithm or header scheme without forking. Bind yours in a service provider after the package's provider so yours wins.
  • Version-specific risk. Because 0.1.0 shipped without notes, treat any integration written against 0.0.3 as unverified. Re-run your golden-signature test against 0.1.0 before touching production, and if the diff shows a changed default algorithm or hash, assume partners on the old version are now mutually incompatible.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource