M ove authorization to BUD-11 and clarify

This commit is contained in:
hzrd149
2026-01-13 19:48:31 -08:00
parent 1305788e98
commit 6fbc2e05da
7 changed files with 117 additions and 93 deletions

View File

@@ -1,6 +1,6 @@
# 🌸 Blossom - Blobs stored simply on mediaservers
Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private keys for identities. Users are expected to sign authorization events to prove their identity when interacting with servers
Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private keys for users identities.
## What is it?
@@ -27,6 +27,7 @@ BUDs or **Blossom Upgrade Documents** are short documents that outline an additi
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
- [BUD-09: Blob Report](./buds/09.md)
- [BUD-10: Blossom URI Schema](./buds/10.md)
- [BUD-11: Nostr Authorization](./buds/11.md)
## Endpoints
@@ -35,26 +36,26 @@ Blossom Servers expose a few endpoints for managing blobs
- `GET /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob)
- `HEAD /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob)
- `PUT /upload` [BUD-02](./buds/02.md#put-upload---upload-blob)
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
- `Authentication`: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#upload-authorization))
- Return a blob descriptor
- `HEAD /upload` [BUD-06](./buds/06.md#head-upload---upload-requirements)
- `GET /list/<pubkey>` [BUD-02](./buds/02.md#get-listpubkey---list-blobs-unrecommended) _(optional, unrecommended)_
- Returns an array of blob descriptors
- `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional)
- `Authentication` _(optional)_: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#list-authorization))
- `DELETE /<sha256>` [BUD-02](./buds/02.md#delete-sha256---delete-blob)
- `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required)
- `Authentication`: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#delete-authorization))
- `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob)
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
- `Authentication`: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#upload-authorization))
- `HEAD /media` [BUD-05](./buds/05.md#head-media)
- `PUT /media` [BUD-05](./buds/05.md#put-media)
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
- `Authentication`: Signed [nostr event](./buds/11.md) (see [BUD-05](./buds/05.md#upload-authorization))
- `PUT /report` [BUD-09](./buds/09.md)
## Event kinds
| kind | description | BUD |
| ------- | ------------------- | ------------------ |
| `24242` | Authorization event | [01](./buds/01.md) |
| `24242` | Authorization token | [11](./buds/11.md) |
| `10063` | User Server List | [03](./buds/03.md) |
## License

View File

@@ -20,55 +20,6 @@ The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a
Every time a server sends an error response (HTTP status codes >=400), it may include a human-readable header `X-Reason` that can be displayed to the user.
## Authorization events
Authorization events are used to identify the users to the server
Authorization events must be generic and must NOT be scoped to specific servers. This allows pubkeys to sign a single event and interact the same way with multiple servers.
Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete`
Events MUST have the `content` set to a human readable string explaining to the user what the events intended use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc
All events 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 event should be considered expired.
Authorization events MAY have multiple `x` tags for endpoints that require a sha256 hash.
Example event:
```jsonc
{
"id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
"kind": 24242,
"content": "Upload bitcoin.pdf",
"created_at": 1708773959,
"tags": [
["t", "upload"],
// Authorization events MAY have multiple "x" tags.
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
["expiration", "1708858680"]
],
"sig": "d0d58c92afb3f4f1925120b99c39cffe77d93e82f488c5f8f482e8f97df75c5357175b5098c338661c37d1074b0a18ab5e75a9df08967bfb200930ec6a76562f"
}
```
Servers must perform the following checks in order to validate the event
1. The `kind` must be `24242`
2. `created_at` must be in the past
3. The `expiration` tag must be set to a Unix timestamp in the future
4. The `t` tag must have a verb matching the intended action of the endpoint
5. Additional checks for specific endpoints. `/upload`, `/delete`, etc
Using the `Authorization` HTTP header, the kind `24242` event MUST be base64 encoded and use the Authorization scheme Nostr
Example HTTP Authorization header:
```
Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQxNDA5ZDhiOTBjY2RiNGI0M2Y4ZjBmYzlkMGMiLCJwdWJrZXkiOiI5ZjBjYzE3MDIzYjJjZjUwOWUwZjFkMzA1NzkzZDIwZTdjNzIyNzY5MjhmZDliZjg1NTM2ODg3YWM1NzBhMjgwIiwiY3JlYXRlZF9hdCI6MTcwODc3MTIyNywia2luZCI6MjQyNDIsInRhZ3MiOltbInQiLCJnZXQiXSxbImV4cGlyYXRpb24iLCIxNzA4ODU3NTQwIl1dLCJjb250ZW50IjoiR2V0IEJsb2JzIiwic2lnIjoiMDJmMGQyYWIyM2IwNDQ0NjI4NGIwNzFhOTVjOThjNjE2YjVlOGM3NWFmMDY2N2Y5NmNlMmIzMWM1M2UwN2I0MjFmOGVmYWRhYzZkOTBiYTc1NTFlMzA4NWJhN2M0ZjU2NzRmZWJkMTVlYjQ4NTFjZTM5MGI4MzI4MjJiNDcwZDIifQ==
```
## Endpoints
All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST be accessible from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs
@@ -103,14 +54,14 @@ include a file extension in the URL that reflects the blob type (e.g. `.bin`, `.
The server may optionally require authorization when retrieving blobs from the `GET /<sha256>` endpoint
In this case, the server MUST perform additional checks on the authorization event
In this case, the server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then perform the following additional checks:
1. A `t` tag MUST be present and set to `get`
2. The event MUST contain either a `server` tag containing the full URL to the server or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved
2. The authorization token MUST contain either a `server` tag (limiting the token to specific servers) or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved (scoping the token to specific blob hashes). see [BUD-11](./11.md#tag-scoping).
If the client did not send an `Authorization` header the server must respond with the appropriate HTTP status code `401` (Unauthorized)
Example event for retrieving a single blob:
Example authorization token for retrieving a single blob:
```json
{
@@ -128,7 +79,7 @@ Example event for retrieving a single blob:
}
```
Example event for retrieving multiple blobs from single server:
Example authorization token for retrieving multiple blobs from single server:
```json
{
@@ -140,7 +91,7 @@ Example event for retrieving multiple blobs from single server:
"tags": [
["t", "get"],
["expiration", "1708857340"],
["server", "https://cdn.example.com/"]
["server", "cdn.example.com"]
],
"sig": "e402ade78e1714d40cd6bd3091bc5f4ada8e904e90301b5a2b9b5f0b6e95ce908d4f22b15e9fb86f8268a2131f8adbb3d1f0e7e7afd1ab0f4f08acb15822a999"
}

View File

@@ -53,12 +53,12 @@ servers may rely on the file extension to serve the blob correctly.
### Upload Authorization (Optional)
Servers MAY accept an authorization event when uploading blobs and SHOULD perform additional checks
Servers MAY require an authorization token when uploading blobs. The server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then perform the following additional checks:
1. The `t` tag MUST be set to `upload`
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the body of the request
2. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the body of the request. The `x` tag scopes the token to specific blob hashes (see [BUD-11](./11.md#tag-scoping)).
Example Authorization event:
Example authorization token:
```json
{
@@ -88,15 +88,13 @@ The endpoint MAY support `since` and `until` query parameters to filter the list
Servers MAY reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### List Authorization (optional)
### List Authorization
The server MAY optionally require Authorization when listing blobs uploaded by the pubkey
In this case the server MUST perform additional checks on the authorization event
The server MAY require a `list` authorization token when listing blobs uploaded by the pubkey. If a server requires authorization it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then it MUST perform the following additional checks:
1. The `t` tag MUST be set to `list`
Example Authorization event:
Example authorization token:
```json
{
@@ -119,20 +117,16 @@ Servers MUST accept `DELETE` requests to the `/<sha256>` endpoint
Servers MAY reject a delete request for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### Delete Authorization (required)
### Delete Authorization
Servers MUST accept an authorization event when deleting blobs
Servers SHOULD perform additional checks on the authorization event
Servers MAY require a `delete` authorization token when deleting blobs. If a server requires authorization it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
1. The `t` tag MUST be set to `delete`
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
2. MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted.
When multiple `x` tags are present on the authorization event the server MUST only delete the blob listed in the URL.
**Multiple `x` tags in the authorization token MUST NOT be interpreted as the user requesting to delete multiple blobs.**
**Multiple `x` tags MUST NOT be interpreted as the user requesting a bulk delete.**
Example Authorization event:
Example authorization token:
```json
{

View File

@@ -19,12 +19,6 @@ Clients MUST pass the URL of the remote blob as a stringified JSON object in the
}
```
Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-optional). When using authorization, the event MUST be of type "upload".
The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob
**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting to mirror multiple blobs.**
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful
or a `4xx` status code and error message if it was not.
@@ -36,11 +30,20 @@ Servers MAY use the `Content-Length` header to determine the size of the blob.
Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection.
### Upload Authorization
Servers MAY require an `upload` authorization token when mirroring blobs. The server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
1. The `t` tag MUST be set to `upload`
2. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the downloaded blob. The `x` tag scopes the token to specific blob hashes (see [BUD-11](./11.md#tag-scoping)).
**Multiple `x` tags in the authorization token MUST NOT be interpreted as the user requesting to mirror multiple blobs.**
## Example Flow
1. Client signs an `upload` authorization event and uploads blob to Server A
1. Client signs an `upload` authorization token and uploads blob to Server A
1. Server A returns a [Blob Descriptor](./02.md#blob-descriptor) with the `url`
1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization event
1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization token
1. Server B downloads the blob from Server A using the `url`
1. Server B verifies the downloaded blob hash matches the `x` tag in the authorization event
1. Server B verifies the downloaded blob hash matches the `x` tag in the authorization token
1. Server B returns a [Blob Descriptor](./02.md#blob-descriptor)

View File

@@ -18,12 +18,10 @@ Servers MAY reject media uploads for any reason and should respond with the appr
### Upload Authorization
Servers MAY require a `media` [authorization event](./02.md#upload-authorization-required) to identify the uploader
If a server requires a `media` authorization event it MUST perform the following checks
Servers MAY require a `media` authorization token to identify the uploader. If a server requires a `media` authorization token it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
1. The `t` tag MUST be set to `media`
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
2. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the body of the request.
## HEAD /media
@@ -45,4 +43,4 @@ Clients MAY let a user selected a "trusted processing" server for uploading imag
Once a server has been selected, the client uploads the original media to the `/media` endpoint of the trusted server and get the optimized blob back
Then the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob
Then the client can ask the user to sign another `upload` authorization token for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob

View File

@@ -18,7 +18,7 @@ The `HEAD /upload` endpoint MUST use the `X-SHA-256`, `X-Content-Type` and `X-Co
### Upload Authorization
The `HEAD /upload` endpoint MAY accept an `upload` authorization event using the `Authorization` header similar to what is used in the [`PUT /upload`](./02.md#upload-authorization-required) endpoint
The `HEAD /upload` endpoint MAY accept an `upload` authorization token using the `Authorization` header similar to what is used in the [`PUT /upload`](./02.md#upload-authorization) endpoint
If the server requires authorization to upload it may respond with the `401` status code, or if authorization was provided and is invalid or not permitted it may respond with `403` status code

77
buds/11.md Normal file
View File

@@ -0,0 +1,77 @@
# BUD-11
## Nostr Authorization
`draft` `optional`
Defines the authorization token format used by blossom servers to identify users. Authorization tokens are optional and servers MAY require them for various endpoints.
## Authorization tokens
Authorization tokens are signed nostr events proving to a server that the user (`pubkey`) has permitted an application to take an action on their behalf.
The authorization token MUST be a nostr event of kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, `delete`, or `media`
Authorization tokens MUST have the `content` set to a human readable string explaining intended use. For example `Upload Blob`, `Delete old blobs`, `List Images`, etc
All authorization tokens 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.
## 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 domain name only (e.g., `cdn.example.com`), not a full URL.
- **`x` tag**: Scopes the token to specific blob hashes (similar to how `server` scopes to servers). 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": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
"kind": 24242,
"content": "Upload bitcoin.pdf",
"created_at": 1708773959,
"tags": [
["t", "upload"],
// Authorization tokens MAY have multiple "x" tags.
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
["expiration", "1708858680"]
],
"sig": "d0d58c92afb3f4f1925120b99c39cffe77d93e82f488c5f8f482e8f97df75c5357175b5098c338661c37d1074b0a18ab5e75a9df08967bfb200930ec6a76562f"
}
```
## Base validation
Servers must perform the following checks in order to validate the authorization token
1. The `kind` must be `24242`
2. `created_at` must be in the past
3. The `expiration` tag must be set to a Unix timestamp in the future
4. The `t` tag must have a verb matching the intended action of the endpoint
5. If `server` tags are present, the server MUST verify that its domain name is present in at least one `server` tag. If no `server` tags are present, the token is valid for all servers.
## HTTP Authorization header
Using the `Authorization` HTTP header, the authorization token (kind `24242`) MUST be base64 encoded and use the Authorization scheme Nostr
Example HTTP Authorization header:
```
Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQxNDA5ZDhiOTBjY2RiNGI0M2Y4ZjBmYzlkMGMiLCJwdWJrZXkiOiI5ZjBjYzE3MDIzYjJjZjUwOWUwZjFkMzA1NzkzZDIwZTdjNzIyNzY5MjhmZDliZjg1NTM2ODg3YWM1NzBhMjgwIiwiY3JlYXRlZF9hdCI6MTcwODc3MTIyNywia2luZCI6MjQyNDIsInRhZ3MiOltbInQiLCJnZXQiXSxbImV4cGlyYXRpb24iLCIxNzA4ODU3NTQwIl1dLCJjb250ZW50IjoiR2V0IEJsb2JzIiwic2lnIjoiMDJmMGQyYWIyM2IwNDQ0NjI4NGIwNzFhOTVjOThjNjE2YjVlOGM3NWFmMDY2N2Y5NmNlMmIzMWM1M2UwN2I0MjFmOGVmYWRhYzZkOTBiYTc1NTFlMzA4NWJhN2M0ZjU2NzRmZWJkMTVlYjQ4NTFjZTM5MGI4MzI4MjJiNDcwZDIifQ==
```
## Endpoint-specific requirements (example)
Individual endpoints may extend the base validation with additional requirements. The following are examples of how endpoints use authorization tokens:
- **`/upload`** ([BUD-02](./02.md#upload-authorization)): May requires at least one `x` tag matching the sha256 hash of the blob being uploaded
- **`DELETE /<sha256>`** ([BUD-02](./02.md#delete-authorization)): May requires at least one `x` tag matching the sha256 hash of the blob being deleted
- **`PUT /media`** ([BUD-05](./05.md#upload-authorization)): May requires at least one `x` tag matching the sha256 hash of the media being uploaded
- **`GET /<sha256>`** ([BUD-01](./01.md#get-authorization)): May require either a `server` tag or at least one `x` tag matching the sha256 hash of the blob being retrieved
- **`GET /list/<pubkey>`** ([BUD-02](./02.md#list-authorization)): May require a `server` tag limiting the token to specific servers
- **`PUT /mirror`** ([BUD-04](./04.md#put-mirror---mirror-blob)): May requires at least one `x` tag matching the sha256 hash of the blob being mirrored
See the respective BUD documents for the exact requirements for each endpoint. All endpoints that accept authorization tokens MUST perform the base validation checks defined above before performing any endpoint-specific checks.