nft.storage icon indicating copy to clipboard operation
nft.storage copied to clipboard

Upload via UCAN token receives 500 with code: TypeError "Cannot read properties of null (reading 'split')"

Open 0x00000010 opened this issue 3 years ago • 1 comments

Trying to upload a file with

curl --verbose -X POST \
-H "Authorization: Bearer $API_TOKEN" \
-H 'accept: application/json' \
-H 'Content-Type: */*' \
-H "x-agent-did: $DID" https://api.nft.storage/upload \
--data-binary '@x'

fails when

  • x is a local file called x containing 2 characters
  • $DID is the one registered with the normal API key with the POST user/did endpoint
  • $API_TOKEN is the $UCAN_TOKEN token issued via the steps below

When $API_TOKEN is swapped with the normal API key $STORAGE_API_KEY the token is linked to this works fine

Failing UCAN Token Creation

Step 1 - Make API Key

Login to the NFT.storage site and generate a standard API token called $STORAGE_API_KEY

Step 2 - Make Keys

Use the ucan-storage keypair command to make a primary keypair mapped to the following new variables

> npx ucan-storage keypair

DID:           $DID
Public Key:    $PUBLIC_KEY
Private Key:   $PRIVATE_KEY

Step 3 - Link the new Keypair with the API token

> curl -X POST \
-H "Authorization: Bearer $STORAGE_API_KEY" \
-H 'Content-Type: application/json' \
--data "{\"did\": \"$DID\"}" \
https://api.nft.storage/user/did

{"ok":true,"value":"$DID"}

Step 4 - Issue own primary long lasting token and receive $UCAN_TOKEN

> npx ucan-storage ucan \
--audience $DID \
--with $DID \
--can 'upload/*' \
--expiration 2099-04-20 \
--issuer $PRIVATE_KEY

{
  "aud": "$DID",
  "att": [
    {
      "with": "storage://$DID",
      "can": "upload/*"
    }
  ],
  "exp": 4080326400,
  "iss": "$DID",
  "prf": [
    null
  ]
}
UCAN:
$UCAN_TOKEN

Step 5

Try to upload a file with the new UCAN token

> curl --verbose -X POST -H "Authorization: Bearer $UCAN_TOKEN" -H 'accept: application/json' -H 'Content-Type: */*' -H "x-agent-did: $DID" https://api.nft.storage/upload --data-binary '@x'

*   Trying 104.x.x.x:443...
* Connected to api.nft.storage (104.x.x.x) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=San Francisco; O=Cloudflare, Inc.; CN=nft.storage
*  start date: Dec  9 00:00:00 2021 GMT
*  expire date: Dec  8 23:59:59 2022 GMT
*  subjectAltName: host "api.nft.storage" matched cert's "*.nft.storage"
*  issuer: C=US; O=Cloudflare, Inc.; CN=Cloudflare Inc ECC CA-3
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f7e3480ca00)
> POST /upload HTTP/2
> Host: api.nft.storage
> user-agent: curl/7.84
> authorization: Bearer $UCAN_TOKEN
> accept: application/json
> content-type: */*
> x-agent-did: $DID
> content-length: 3
>
* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 500
< date: Fri, 26 Aug 2022 05:08:07 GMT
< content-type: application/json;charset=UTF-8
< content-length: 102
< access-control-allow-origin: *
< expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< server: cloudflare
< cf-ray: 740a0c3c18b022d8-HKG
< alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400
<
* Connection #0 to host api.nft.storage left intact

{"ok":false,"error":{"code":"TypeError","message":"Cannot read properties of null (reading 'split')"}}

Step 6

Also tried using this token as a parent token and issuing child tokens through the CLI and the JS SDK but received the same error message.

I created a child token in the CLI like this:

> npx ucan-storage ucan \
--audience $DID \
--with storage://$DID \
--can 'upload/*' \
--expiration 2099-04-20 \
--issuer $PRIVATE_KEY \
--proof $UCAN_TOKEN

{
  "aud": "$DID",
  "att": [
    {
      "with": "storage://$DID",
      "can": "upload/*"
    }
  ],
  "exp": 4080326400,
  "iss": "$DID",
  "prf": [
    "$UCAN_TOKEN"
  ]
}
UCAN:
$CHILD_UCAN_TOKEN

to include a proof but the result is the same

0x00000010 avatar Aug 26 '22 05:08 0x00000010

Not 100% sure here, but I think what's going on is that the token you create in Step 4 should have a token from the nft.storage service's /ucan/token endpoint in its proof chain (the prf array).

If you request a token from /ucan/token and pass it to the --proof flag when creating your token, that should hopefully work. Please let us know either way - if it does work, we at least need to update our error messages in the case where you use a token without any proofs.

yusefnapora avatar Sep 05 '22 14:09 yusefnapora

Closing as this ticket is over 1 year old. If you still need support, please re-open this issue and provide more detail. Thanks!

elizabeth-griffiths avatar Apr 25 '24 12:04 elizabeth-griffiths