https://github.com/bsv-blockchain/auth-express-middleware
BSV Blockchain mutual-authentication express middleware
https://github.com/bsv-blockchain/auth-express-middleware
Last synced: 3 months ago
JSON representation
BSV Blockchain mutual-authentication express middleware
- Host: GitHub
- URL: https://github.com/bsv-blockchain/auth-express-middleware
- Owner: bsv-blockchain
- License: other
- Created: 2025-01-03T02:10:14.000Z (10 months ago)
- Default Branch: master
- Last Pushed: 2025-07-18T22:08:58.000Z (4 months ago)
- Last Synced: 2025-07-19T03:06:06.604Z (4 months ago)
- Language: TypeScript
- Size: 478 KB
- Stars: 0
- Watchers: 5
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# @bsv/auth-express-middleware
An **Express.js** middleware that implements **BRC-103** [Peer-to-Peer Mutual Authentication](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md) via **BRC-104** [HTTP Transport](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md). This library makes it easy to **mutually authenticate** and exchange **verifiable certificates** between clients and servers in a standardized way.
By layering **BRC-103** on top of Express, you can:
- Perform a **cryptographic handshake** between two peers (your server and an external wallet/user).
- Request or respond with **certificates** that verify user identity or attributes.
- Enforce mutual authentication for your APIs, ensuring that each side proves its identity, without passwords or reliance on centralized authentication providers.
- Optionally enable **selective disclosure** of certificate fields.
---
## Table of Contents
1. [Background](#background)
2. [Features](#features)
3. [Installation](#installation)
4. [Quick Start](#quick-start)
5. [Detailed Usage](#detailed-usage)
- [Creating the Middleware](#creating-the-middleware)
- [Injecting the Middleware into Express](#injecting-the-middleware-into-express)
- [Handling Certificates](#handling-certificates)
- [Interpreting Authenticated Requests](#interpreting-authenticated-requests)
6. [API Reference](#api-reference)
7. [Examples](#examples)
8. [Security Considerations](#security-considerations)
9. [Resources & References](#resources--references)
10. [License](#license)
---
## Background
**BRC-103** is a specification for **mutual authentication** and **certificate exchange** over a **peer-to-peer** channel. It uses nonce-based challenges, digital signatures, and an optional selective disclosure mechanism for certificates. **BRC-104** defines how to transport these messages specifically over **HTTP**, describing custom headers and the `.well-known/auth` endpoint.
**`@bsv/auth-express-middleware`** abstracts the complexities of these specs behind a typical **Express** middleware. It verifies BRC-103/104–compliant requests and properly signs responses, all while letting you continue to write normal Express code for your routes.
---
## Features
- **Seamless Integration**
Plug straight into your existing Express application—no need for rewriting your entire HTTP handling logic.
- **Mutual Authentication**
Authenticates **both** the server and the client cryptographically, preventing impersonation or MITM attacks.
- **Certificate Handling**
Request, receive, and verify BRC-103 identity certificates. Includes utility methods to request additional certificates from the client.
- **Selective Disclosure**
Supports BRC-103’s concept of revealing only certain fields in a certificate, helping to preserve privacy for you and your users while verifying necessary information.
- **Extendable**
Provide a custom `SessionManager` or plug in advanced logic for verifying user attributes.
---
## Installation
```bash
npm i @bsv/auth-express-middleware
```
This package depends on [Express.js](https://www.npmjs.com/package/express) (4.x or 5.x) and a BRC-100–capable wallet (e.g., the `@bsv/sdk` implementation or your own code).
---
## Quick Start
Below is the minimal setup to enable BRC-103 mutual authentication in your Express server:
```ts
import express from 'express'
import bodyParser from 'body-parser'
import { createAuthMiddleware } from '@bsv/auth-express-middleware'
import { ProtoWallet as Wallet } from '@bsv/sdk' // You need a wallet that supports BRC-100 keys & signing
// 1. Initialize your BSV wallet (manages keys and signs messages)
const wallet = new Wallet(new PrivateKey('...', 16))
// 2. Create the auth middleware
// - Set `allowUnauthenticated` to false to require mutual auth on every route
const authMiddleware = createAuthMiddleware({
wallet,
allowUnauthenticated: false
})
// 3. Create and configure the Express app
const app = express()
app.use(bodyParser.json())
// 4. Apply the auth middleware globally (or to specific routes)
app.use(authMiddleware)
// 5. Define your routes as usual
app.get('/', (req, res) => {
if (req.auth && req.auth.identityKey !== 'unknown') {
// The request is authenticated
res.send(`Hello, authenticated peer with public key: ${req.auth.identityKey}`)
} else {
// Not authenticated
res.status(401).send('Unauthorized')
}
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
```
When the server receives a **BRC-103** handshake or "general" message, `@bsv/auth-express-middleware` automatically handles the cryptographic checks. Once verified, `req.auth.identityKey` will hold the **public key** of the authenticated peer.
---
## Detailed Usage
### Creating the Middleware
Use the factory function:
```ts
createAuthMiddleware({
wallet: myWallet,
allowUnauthenticated?: boolean,
sessionManager?: SessionManager,
certificatesToRequest?: RequestedCertificateSet,
onCertificatesReceived?: (senderPublicKey, certs, req, res, next) => void
})
```
#### Options
- **`wallet`** *(required)*: A wallet instance that implements signing and key management, typically from `@bsv/sdk` or your own custom build.
- **`allowUnauthenticated`** *(default: `false`)*: If `true`, requests without valid BRC-103 authentication will **not** be rejected. Instead, `req.auth.identityKey` is set to `"unknown"`.
- **`sessionManager`** *(optional)*: Customize session management (nonce tracking, etc.). By default, an internal `SessionManager` is used.
- **`certificatesToRequest`** *(optional)*: A specification of which certificates (by type, fields, issuer) to request automatically from the peer.
- **`onCertificatesReceived`** *(optional)*: Callback invoked when the peer responds with **Verifiable Certificates**.
### Injecting the Middleware into Express
Simply call:
```ts
app.use(express.json()) // required before the middleware is used
app.use(createAuthMiddleware({ wallet: myWallet }))
```
You can also place the middleware at the route level:
```ts
app.post('/secure-upload', createAuthMiddleware({ wallet: myWallet }), (req, res) => {
// ...
})
```
### Handling Certificates
If you set `certificatesToRequest`, the middleware will attempt to request certificates from the client during the handshake. When certificates arrive, the `onCertificatesReceived` callback (if provided) will fire:
```ts
function onCertificatesReceived(senderPublicKey, certs, req, res, next) {
// You can inspect the provided certificates here
console.log(`Received ${certs.length} certificate(s) from ${senderPublicKey}.`)
// Continue to next middleware or route handler
next()
}
const authMiddleware = createAuthMiddleware({
wallet,
certificatesToRequest: {
certifiers: ['<33-byte-pubkey-of-certifier>'],
types: {
'age-verification': ['dateOfBirth', 'country']
}
},
onCertificatesReceived
})
```
In your server logic, you can then verify or store these certificates as needed. Replace fields like `age-verification` with an actual base64 certificate type.
### Interpreting Authenticated Requests
Once a peer is authenticated, you'll have:
- `req.auth.identityKey` ⇒ the authenticated user's **33-byte compressed public key** (hex-encoded).
- `req.body` ⇒ your normal request body (parsed by `express.json()` or similar).
- Standard `req.headers` ⇒ includes `x-bsv-auth-*` headers with BRC-103 handshake data (for debugging).
If `allowUnauthenticated` is **false**, any request without a valid handshake or signature is **rejected** with `401` automatically.
---
## API Reference
### `createAuthMiddleware(options: AuthMiddlewareOptions)`
Returns an Express middleware function. **Options**:
- **`wallet`**: (required) A BRC-100 object implementing your signing and verification logic.
- **`sessionManager`**: (optional) Manage nonces & state across requests.
- **`allowUnauthenticated`**: (optional) If true, non-authenticated requests are allowed but marked as `identityKey: 'unknown'`.
- **`certificatesToRequest`**: (optional) Automatic certificate request data structure.
- **`onCertificatesReceived`**: (optional) A callback triggered when certs arrive from the client.
---
## Examples
### 1. Minimal Setup
```ts
import express from 'express'
import { createAuthMiddleware } from '@bsv/auth-express-middleware'
import { Wallet } from '@your/bsv-wallet'
const app = express()
const wallet = new Wallet({ /* config for your keys */ })
app.use(express.json())
app.use(createAuthMiddleware({ wallet }))
app.get('/protected', (req, res) => {
if (req.auth && req.auth.identityKey !== 'unknown') {
return res.send('You are authenticated via BRC-103!')
}
res.status(401).send('Unauthorized')
})
app.listen(3000, () => console.log('BRC-103 server listening on port 3000!'))
```
### 2. Requesting Certificates at Handshake
```ts
import express from 'express'
import { createAuthMiddleware } from '@bsv/auth-express-middleware'
import { Wallet } from '@your/bsv-wallet'
const wallet = new Wallet()
function onCertificatesReceived(senderPublicKey, certs, req, res, next) {
console.log(`Received certs from ${senderPublicKey}`, certs)
next()
}
const authMiddleware = createAuthMiddleware({
wallet,
certificatesToRequest: {
certifiers: [''],
types: {
'someCertificateType': ['fieldA', 'fieldB']
}
},
onCertificatesReceived
})
const app = express()
app.use(express.json())
app.use(authMiddleware)
app.listen(3000, () => console.log('Server up!'))
```
---
## Security Considerations
1. **TLS Encryption**: Although BRC-103 messages are authenticated, the protocol does **not** encrypt the entire payload. It's recommended to serve your Express app over **HTTPS** to maintain confidentiality.
2. **Nonce Replay Prevention**: This library implements a `SessionManager` that automatically rejects nonces not bound by the server's private key.
3. **Transport-Only**: BRC-104's HTTP specification focuses on message authenticity, not on anonymizing request metadata.
4. **Certificate Revocation**: BRC-103 allows for revocation references (`revocationOutpoint`). Ensure your app checks the blockchain or an appropriate certificate revocation overlay service if you require strict revocation handling.
---
## Resources & References
- [BRC-103 Spec](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md) – Mutual authentication & certificate exchange.
- [BRC-104 Spec](https://github.com/bitcoin-sv/BRCs/blob/master/peer-to-peer/0103.md) – HTTP Transport for BRC-103.
- [@bsv/sdk](https://www.npmjs.com/package/@bsv/sdk) – BSV TypeScript SDK (often used for cryptographic utilities, wallet logic, etc.).
- [Express.js](https://expressjs.com/) – Web framework for Node.js.
---
## License
[Open BSV License](./LICENSE.txt)
---
**Happy hacking!** If you have questions, suggestions, or want to contribute improvements, feel free to open an issue or PR in our repository.