Skip to content

Instantly share code, notes, and snippets.

@CraigglesO
Created February 17, 2022 03:27
Show Gist options
  • Save CraigglesO/57f0c190a88cae316791225ecbfd5ef9 to your computer and use it in GitHub Desktop.
Save CraigglesO/57f0c190a88cae316791225ecbfd5ef9 to your computer and use it in GitHub Desktop.
PUT signedURL for clients without threat of bad actors
import { AwsClient } from 'aws4fetch'
let b2
// accessKeyId -> B2 keyID
// secretAccessKey -> B2 AppKey
export const prepB2 = (accessKeyId, secretAccessKey) => {
if (!b2) b2 = new AwsClient({ accessKeyId, secretAccessKey, service: 's3' })
}
export const createSignedURL = async (path, contentLength, contentType, contentEncoding, cacheControl) => {
// NOTE: i replaced bucket and endpoint. you can set these how you want
// bucket is the NAME of your bucket not your bucket id
// endpoint will be something is like "s3.us-west-000.backblazeb2.com"
const location = new URL(`https://{{bucket}}.{{endpoint}}/${path}`)
// MUST put a content length. This is crucial to not allow bad actors to put whatever they want at the key
if (!contentLength) return { err: 'Missing contentLength.' }
if (!contentType) return { err: 'Missing contentType.' }
const signHeaders = new Headers()
signHeaders.set('Content-Length', contentLength)
signHeaders.set('Content-Type', 'application/json')
if (contentEncoding) signHeaders.set('Content-Encoding', contentEncoding)
if (cacheControl) signHeaders.set('Cache-Control', cacheControl)
const signedRequest = await b2.sign(location, {
method: 'PUT', // if not supplied, will default to 'POST' if there's a body, otherwise 'GET'
headers: signHeaders, // standard JS object literal, or Headers instance
// body, // optional, String or ArrayBuffer/ArrayBufferView – ie, remember to stringify your JSON
aws: {
signQuery: true, // set to true to sign the query string instead of the Authorization header
appendSessionToken: true, // set to true to add X-Amz-Security-Token after signing, defaults to true for iot
allHeaders: true // set to true to force all headers to be signed instead of the defaults
}
}).catch(() => null)
if (!signedRequest) return { err: 'Failed to sign request.' }
const { method, url, headers } = signedRequest
return { method, url, headers: [...headers] }
}
// CLIENT/BROWSER SIDE added for posterity:
function clientBrowserSideCode () {
const { method, url, headers } = res
await fetch(url, { method, body, headers })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment