Skip to content

Commit dcfa634

Browse files
queekusmethibmeu
authored andcommitted
Components check now done on params.components rather than on filled variable, Refactored signatureHeaders and signatureHeadersSync common code into getSigningOptions, ran 'npm run lint'
1 parent d5777cd commit dcfa634

File tree

5 files changed

+47
-62
lines changed

5 files changed

+47
-62
lines changed

.github/workflows/pullrequest.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ jobs:
6161
name: Deploy Rust Crates
6262
timeout-minutes: 5
6363
env:
64-
# This token can be regenerated by visiting https://crates.io/me,
65-
# generating a new API token with `publish-update` permissions,
66-
# scoping it to just `web-bot-auth` and `http-signature-directory`
67-
# crates, and uploading to Github.
68-
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_TOKEN }}
64+
# This token can be regenerated by visiting https://crates.io/me,
65+
# generating a new API token with `publish-update` permissions,
66+
# scoping it to just `web-bot-auth` and `http-signature-directory`
67+
# crates, and uploading to Github.
68+
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_TOKEN }}
6969
strategy:
7070
matrix:
7171
os: [ubuntu-24.04]
@@ -87,7 +87,7 @@ jobs:
8787
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
8888
- name: Set rust toolchain
8989
run: rustup override set 1.87
90-
- run: cargo publish -p web-bot-auth # will fail if we don't bump the version
90+
- run: cargo publish -p web-bot-auth # will fail if we don't bump the version
9191
continue-on-error: true
9292
- run: cargo publish -p http-signature-directory # will fail if we don't bump the version
93-
continue-on-error: true
93+
continue-on-error: true

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ This deployment allows to test your implementation.
4343

4444
This repository uses [npm](https://docs.npmjs.com/cli/v11/using-npm/workspaces) and [cargo](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html) workspaces. There are several packages which it provides:
4545

46-
| Package | Language | Description |
47-
| :--------------------------------------------------------- | :--------- | :------------------------------------------------------------------------------------- |
48-
| [http-message-sig](./packages/http-message-sig/) | TypeScript | HTTP Message Signatures as defined in RFC 9421 |
49-
| [jsonwebkey-thumbprint](./packages/jsonwebkey-thumbprint/) | TypeScript | JWK Thumbprint as defined in RFC 7638 |
50-
| [web-bot-auth](./packages/web-bot-auth/) | TypeScript | HTTP Message Signatures for Bots as defined in draft-meunier-web-bot-auth-architecture |
51-
| [web-bot-auth](./crates/web-bot-auth/) | Rust | HTTP Message Signatures for Bots as defined in draft-meunier-web-bot-auth-architecture |
52-
| [http-signature-directory](./crates/http-signature-directory/)| Rust | Validates whether an HTTP message signature directory is correctly signed and valid |
46+
| Package | Language | Description |
47+
| :------------------------------------------------------------- | :--------- | :------------------------------------------------------------------------------------- |
48+
| [http-message-sig](./packages/http-message-sig/) | TypeScript | HTTP Message Signatures as defined in RFC 9421 |
49+
| [jsonwebkey-thumbprint](./packages/jsonwebkey-thumbprint/) | TypeScript | JWK Thumbprint as defined in RFC 7638 |
50+
| [web-bot-auth](./packages/web-bot-auth/) | TypeScript | HTTP Message Signatures for Bots as defined in draft-meunier-web-bot-auth-architecture |
51+
| [web-bot-auth](./crates/web-bot-auth/) | Rust | HTTP Message Signatures for Bots as defined in draft-meunier-web-bot-auth-architecture |
52+
| [http-signature-directory](./crates/http-signature-directory/) | Rust | Validates whether an HTTP message signature directory is correctly signed and valid |
5353

5454
## Security Considerations
5555

crates/http-signature-directory/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ This is an opinionated validator:
1818
- [Security Considerations](#security-considerations)
1919
- [License](#license)
2020

21-
2221
## Usage
2322

2423
```

packages/web-bot-auth/src/index.ts

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export {
66
type SignatureHeaders,
77
type Signer,
88
type SignerSync,
9+
type SignOptions,
910
Tag,
1011
directoryResponseHeaders,
1112
} from "http-message-sig";
@@ -55,13 +56,13 @@ export function validateNonce(nonce: string): boolean {
5556
}
5657
}
5758

58-
export function signatureHeaders<
59+
function getSigningOptions<
5960
T extends httpsig.RequestLike | httpsig.ResponseLike,
6061
>(
6162
message: T,
6263
signer: httpsig.Signer,
6364
params: SignatureParams
64-
): Promise<httpsig.SignatureHeaders> {
65+
): httpsig.SignOptions {
6566
if (params.created.getTime() > params.expires.getTime()) {
6667
throw new Error("created should happen before expires");
6768
}
@@ -75,21 +76,24 @@ export function signatureHeaders<
7576
}
7677
}
7778
const signatureAgent = httpsig.extractHeader(message, SIGNATURE_AGENT_HEADER);
78-
let components: string[] | undefined = params.components;
79-
if(!components) {
80-
// not the ideal check, but extractHeader returns "" instead of throwing or null when the header does not exist
79+
let components: string[];
80+
if (!params.components) {
81+
// `extractHeader` returns "" instead of throwing or null when the header does not exist
8182
if (!signatureAgent) {
8283
components = REQUEST_COMPONENTS_WITHOUT_SIGNATURE_AGENT;
8384
} else {
84-
components = REQUEST_COMPONENTS
85+
components = REQUEST_COMPONENTS;
8586
}
8687
} else {
87-
if(signatureAgent && components.indexOf("SIGNATURE_AGENT_HEADER") === -1)
88-
{
89-
throw new Error(`${SIGNATURE_AGENT_HEADER} is required in params.component when included as a header param`);
88+
if (signatureAgent && components.indexOf("SIGNATURE_AGENT_HEADER") === -1) {
89+
throw new Error(
90+
`${SIGNATURE_AGENT_HEADER} is required in params.component when included as a header param`
91+
);
9092
}
93+
components = params.components;
9194
}
92-
return httpsig.signatureHeaders(message, {
95+
96+
return {
9397
signer,
9498
components,
9599
created: params.created,
@@ -98,7 +102,20 @@ export function signatureHeaders<
98102
keyid: signer.keyid,
99103
key: params.key,
100104
tag: HTTP_MESSAGE_SIGNAGURE_TAG,
101-
});
105+
};
106+
}
107+
108+
export function signatureHeaders<
109+
T extends httpsig.RequestLike | httpsig.ResponseLike,
110+
>(
111+
message: T,
112+
signer: httpsig.Signer,
113+
params: SignatureParams
114+
): Promise<httpsig.SignatureHeaders> {
115+
return httpsig.signatureHeaders(
116+
message,
117+
getSigningOptions(message, signer, params)
118+
);
102119
}
103120

104121
export function signatureHeadersSync<
@@ -108,41 +125,10 @@ export function signatureHeadersSync<
108125
signer: httpsig.SignerSync,
109126
params: SignatureParams
110127
): httpsig.SignatureHeaders {
111-
if (params.created.getTime() > params.expires.getTime()) {
112-
throw new Error("created should happen before expires");
113-
}
114-
let nonce = params.nonce;
115-
if (!nonce) {
116-
nonce = generateNonce();
117-
} else {
118-
if (!validateNonce(nonce)) {
119-
throw new Error("nonce is not a valid uint32");
120-
}
121-
}
122-
const signatureAgent = httpsig.extractHeader(message, SIGNATURE_AGENT_HEADER);
123-
let components: string[] | undefined = params.components;
124-
if(!components) {
125-
// not the ideal check, but extractHeader returns "" instead of throwing or null when the header does not exist
126-
if (!signatureAgent) {
127-
components = REQUEST_COMPONENTS_WITHOUT_SIGNATURE_AGENT;
128-
} else {
129-
components = REQUEST_COMPONENTS
130-
}
131-
} else {
132-
if(signatureAgent && components.indexOf("SIGNATURE_AGENT_HEADER") === -1)
133-
{
134-
throw new Error(`${SIGNATURE_AGENT_HEADER} is required in params.component when included as a header param`);
135-
}
136-
}
137-
return httpsig.signatureHeadersSync(message, {
138-
signer,
139-
components,
140-
created: params.created,
141-
expires: params.expires,
142-
nonce,
143-
keyid: signer.keyid,
144-
tag: HTTP_MESSAGE_SIGNAGURE_TAG,
145-
});
128+
return httpsig.signatureHeadersSync(
129+
message,
130+
getSigningOptions(message, signer, params)
131+
);
146132
}
147133

148134
export type Verify<T> = (

packages/web-bot-auth/test/test_data/web_bot_auth_architecture_v1.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@
7777
"signature_input": "sig2=(\"@authority\" \"signature-agent\");created=1735689600;keyid=\"poqkLGiymh_W0uP6PZFw-dvez3QJT5SolqXBCW38r0U\";alg=\"ed25519\";expires=1735693200;nonce=\"e8N7S2MFd/qrd6T2R3tdfAuuANngKI7LFtKYI/vowzk4lAZYadIX6wW25MwG7DCT9RUKAJ0qVkU0mEeLElW1qg==\";tag=\"web-bot-auth\"",
7878
"signature_agent": "\"https://signature-agent.test\""
7979
}
80-
]
80+
]

0 commit comments

Comments
 (0)