mirror of
https://github.com/hzrd149/blossom.git
synced 2026-10-05 15:38:22 +00:00
92 lines
5.7 KiB
Markdown
92 lines
5.7 KiB
Markdown
# BUD-11
|
|
|
|
## Nostr Authorization
|
|
|
|
`draft` `optional`
|
|
|
|
Defines the format of the authorization token used by Blossom servers to identify users and by users to authorize actions on those servers. Authorization tokens are optional; servers MAY require them for specific endpoints.
|
|
|
|
## Authorization tokens
|
|
|
|
Authorization tokens are signed [nostr](https://github.com/nostr-protocol/nips/blob/master/01.md) events of kind `24242` proving to a server that the user (`pubkey`) has permitted an application to take an action on their behalf.
|
|
|
|
All authorization tokens:
|
|
|
|
- MUST have the `content` set to a human readable string explaining intended use to the user. For example `Upload Blob`, `Delete old blobs`, `List Images`, etc.
|
|
|
|
- MUST have a [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md) `expiration` tag set to a unix timestamp at which the token should be considered expired.
|
|
|
|
- MUST have a `t` tag with a verb of `get`, `upload`, `list`, `delete`, or `media`. The value of the `t` tag MUST correspond to the action performed by the target endpoint, as defined in the section [Endpoint Authorization Requirements](#endpoint-authorization-requirements).
|
|
|
|
## Tag scoping
|
|
|
|
Authorization tokens MAY include `server` and `x` tags to scope the token to specific servers or blob hashes.
|
|
|
|
- **`server` tag**: Limits the token to specific servers by domain name. If no `server` tags are present, the token is valid for all servers. Multiple `server` tags may be present to allow the token to be used on multiple servers. The value MUST be a lowercase domain name only (e.g., `cdn.example.com`), not a full URL.
|
|
|
|
- **`x` tag**: Scopes the token to specific lowercase hex-encoded blob hashes. Multiple `x` tags may be present for endpoints that require a sha256 hash. When `x` tags are present, the token is only valid for operations on the specified blob hashes.
|
|
|
|
Example authorization token:
|
|
|
|
```jsonc
|
|
{
|
|
"id": "7a1735c3852cf3f374edae4b2af2ee18e750e6dec583e19c4795d3b179af6d17",
|
|
"kind": 24242,
|
|
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
|
"created_at": 1772019044,
|
|
"tags": [
|
|
["t","upload"],
|
|
["expiration","1708858680"],
|
|
// Authorization token MAY have multiple "x" tags
|
|
["x","b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
|
|
],
|
|
"content": "",
|
|
"sig": "4b57c22b1797b109530ffe5d04cabac468b1a5942873a5141334ecbc77694fc968a1b941979ba13602fceb1dad8014ab6469c6ae9cef0b5668cc23ad1449e103"
|
|
}
|
|
```
|
|
|
|
## HTTP Authorization Header
|
|
|
|
Using the `Authorization` HTTP header, the authorization token MUST be encoded as Base64 URL-safe without padding (Base64url, as used by JWTs) and use the Authorization scheme Nostr
|
|
|
|
Example HTTP Authorization Header:
|
|
|
|
```
|
|
Authorization: Nostr ewogICJpZCI6ICI3YTE3MzVjMzg1MmNmM2YzNzRlZGFlNGIyYWYyZWUxOGU3NTBlNmRlYzU4M2UxOWM0Nzk1ZDNiMTc5YWY2ZDE3IiwKICAia2luZCI6IDI0MjQyLAogICJwdWJrZXkiOiAiNzliZTY2N2VmOWRjYmJhYzU1YTA2Mjk1Y2U4NzBiMDcwMjliZmNkYjJkY2UyOGQ5NTlmMjgxNWIxNmY4MTc5OCIsCiAgImNyZWF0ZWRfYXQiOiAxNzcyMDE5MDQ0LAogICJ0YWdzIjogWwogICAgWyJ0IiwidXBsb2FkIl0sCiAgICBbImV4cGlyYXRpb24iLCIxNzA4ODU4NjgwIl0sCiAgICAvLyBBdXRob3JpemF0aW9uIHRva2VuIE1BWSBoYXZlIG11bHRpcGxlICJ4IiB0YWdzCiAgICBbIngiLCJiMTY3NDE5MWE4OGVjNWNkZDczM2U0MjQwYTgxODAzMTA1ZGM0MTJkNmM2NzA4ZDUzYWI5NGZjMjQ4ZjRmNTUzIl0sCiAgXSwKICAiY29udGVudCI6ICIiLAogICJzaWciOiAiNGI1N2MyMmIxNzk3YjEwOTUzMGZmZTVkMDRjYWJhYzQ2OGIxYTU5NDI4NzNhNTE0MTMzNGVjYmM3NzY5NGZjOTY4YTFiOTQxOTc5YmExMzYwMmZjZWIxZGFkODAxNGFiNjQ2OWM2YWU5Y2VmMGI1NjY4Y2MyM2FkMTQ0OWUxMDMiCn0
|
|
```
|
|
|
|
## Validation
|
|
|
|
To validate an authorization token, a server MUST perform the following checks:
|
|
|
|
1. The event `kind` MUST be `24242`.
|
|
2. The `created_at` timestamp MUST be in the past.
|
|
3. An `expiration` tag MUST be present and set to a Unix timestamp in the future.
|
|
4. The `t` tag MUST contain a verb matching the intended action of the endpoint.
|
|
5. If one or more `server` tags are present, the server MUST verify that its domain name appears in at least one `server` tag.
|
|
6. If the endpoint requires `x` tags, the server MUST verify that at least one `x` tag matches the blob hash implied by the endpoint.
|
|
|
|
## Endpoint Authorization Requirements
|
|
|
|
The table below defines, for each endpoint, the required `t` tag action, the implied blob hash (if any), and whether at least one matching `x` tag is required.
|
|
|
|
| Endpoint | Required `t` | Implied Blob Hash | `x` Tag Requirement |
|
|
| -------------------- | ------------ | ---------------------------- | ------------------- |
|
|
| `GET /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
|
| `HEAD /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
|
| `PUT /upload` | `upload` | `X-SHA-256` request header | required |
|
|
| `HEAD /upload` | `upload` | `X-SHA-256` request header | required |
|
|
| `DELETE /<sha256>` | `delete` | `<sha256>` from the URL | required |
|
|
| `GET /list/<pubkey>` | `list` | — | not applicable |
|
|
| `PUT /mirror` | `upload` | SHA-256 of the mirrored blob | required |
|
|
| `PUT /media` | `media` | `X-SHA-256` request header | required |
|
|
| `HEAD /media` | `media` | `X-SHA-256` request header | required |
|
|
|
|
## Security Considerations
|
|
|
|
### Unscoped Tokens
|
|
|
|
A token that does not include a `server` tag is valid on any Blossom server that accepts it. If intercepted or leaked, such a token can be replayed against other servers for the duration of its validity (until its `expiration`).
|
|
|
|
This risk is particularly significant for `delete` tokens. An unscoped `delete` token intercepted from one server can be reused to delete the same blob from any other server where it exists.
|