Building Financial APIs

A Guide to Non-Repudiation

Back to all posts

Posted on January 16, 2026

 This article is part of a series on understanding the hows and whys of JSON Web Signatures (JWS).

 There's accompanying code: it's refered to and linked throughout the content. But if you'd rather just read raw code, head over here.

When an issuer claims they never authorized that €50K request, can you prove they did? Learn how JWS provides cryptographic proof that survives disputes, audits, and legal challenges.

We'll cover how to build financial APIs with cryptographic non-repudiation: mathematical proof that survives time, disputes, and regulatory audits. Learn the theory, implementation, security considerations, and operational discipline needed for production JWS deployment.

In This Series

Why Authentication Isn't Enough

The "Who" vs The "What"

There's a critical gap between authentication and non-repudiation in payment scheme APIs: how should it be addressed? If you're building or operating financial platforms where disputes over transaction details could shift six-figure liabilities between participants, it's important to grasp why OAuth tokens and mTLS certificates only prove who connected, not what they actually sent. Through a concrete scenario of a disputed €50,000 authorization approval, you'll learn why authentication logs may not hold up under regulatory scrutiny or chargeback arbitration, how JWS (JSON Web Signature) creates verifiable proof of exact message content, and when you actually need cryptographic non-repudiation versus when authentication alone suffices.

Read on about what non-repudiation is, and why it matters

JWS Implementation with Elixir and JOSE

Theory is nice, but you need working code. Follow along as we build a complete Elixir and JOSE implementation for signing and verifying payment instructions with ES256, including a production-ready Phoenix Plug. Learn critical decisions like compact vs flattened JSON serialization, how to handle clock skew tolerance, and the canonicalization traps that will break your signatures if you're not careful.

Let's build a robust JWS implementation in Elixir

Choosing Algorithms That Hold Up

Cryptographic Hygiene

Algorithm choice isn't academic: it determines whether your signatures survive security audits and legal challenges. This post decodes algorithm names (RS256, ES384, EdDSA), explains the security properties of each family (HMAC, RSA, ECDSA), covers known attacks like the Sony PS3 hack and Bitcoin wallet thefts, and provides a decision framework that balances technical merit with organizational reality.

Dive in to algorithms and security aspects of JWS

Preventing Signature Denial-of-Service

Authentication vs Non-Repudiation

Signature verification is expensive, and attackers can exploit this. This post explains why JWS alone isn't enough for authentication, how Open Banking's three-layer architecture (mTLS, OAuth, JWS) prevents signature-based DoS attacks, and the fundamental principle: expensive operations must be protected by cheap gates. Short but critical for production security.

Keep safe from JWS Denial-of-Service

JWKS and Zero-Downtime Key Rotation

Scaling Trust

Your former employee with key access just left on bad terms. Your runbook says key rotation will take 6-12 hours coordinating with 50+ partner banks—while the compromised key stays active in production processing real money. JWKS (JSON Web Key Set) transforms this nightmare into a 5-minute configuration change by publishing keys at a standard endpoint that clients fetch automatically. Learn the four-phase rotation process that achieves zero downtime, why the kid is critical, and the caching strategies that make JWKS performant at scale.

Learn more about JWKS and key rotation

JWKS in Production

Multi-Tenancy, Security, and Operations

A partner's JWKS endpoint goes down for 2 hours due to DNS issues. Do you reject €300K in legitimate transactions, or keep using cached keys and risk accepting fraudulent signatures if this is actually a compound attack? Learn how to build production-grade JWKS for 200+ partners, implement stale-while-revalidate caching with security safeguards, and create human-in-the-loop verification for potential incidents. Get the operational runbooks for systems handling irreversible transactions.

Read up on considerations for production use

Audit Trails That Win Disputes

The "Forever" Proof

Non-repudiation isn't just about signing requests, it's about preserving proof that survives years, disputes, and regulatory audits. Let's go over what to store (original JWS string, public keys, verification metadata), how to avoid canonicalization traps, implementing replay attack prevention, and building a complete dispute resolution playbook.

On to making audit trails stand up to scrutiny

Maintaining JWS in Production

Testing, Migration, and Troubleshooting

The difference between toy implementations and production systems is operational discipline. Let's discuss critical test cases (including the failures everyone forgets), phased migration strategies that won't break production, contract testing with partners, and a complete troubleshooting guide for when signatures fail in the middle of the night, common issues, and when to escalate to partners.

Make sure your JWS immplementation is production-ready

Accompanying Code

This series includes practical implementation examples in Elixir which demonstrates production-grade JWS signing, verification, JWKS endpoints, audit logging, and more. Technical readers may want to explore the code before, during, or after reading the posts: use whichever approach best fits your learning style.

The code includes:

 This article is part of a series on understanding the hows and whys of JSON Web Signatures (JWS).

 There's accompanying code: it's refered to and linked throughout the content. But if you'd rather just read raw code, head over here.