Image resizing with authentication [SOLVED]

Looking for suggestions … I need to use the image resizer on an endpoint that requires authentication.

The use case is that I want to give Cloudflare access to our restricted library of full size images, to resize (to specific dimensions) and serve at an end-user’s requests. So users get a sniff but library remains private (and scrape-free).

We’re currently using Firebase Storage / Google Cloud Storage and can successfully authenticate and return an image (not resized) using a CF worker and route. Access is granted via oauth and passed in the request header Authorization: Bearer XXX.

The problems arise when we attempt to resize the image in the same worker. If we also include e.g. cf: { image: { width: 360 } } in our fetch options we get a lovely error response:

ERROR 9408: Could not fetch the image — the server returned HTTP error 403 Forbidden

Cloudflare support have confirmed that this is by design. They weren’t clear on the details other than to specify that neither cookies nor authentication currently work with image resizing.

Is there another, roundabout way to achieve resizing on an authenticated image? I’m happy to get creative. Perhaps by streaming the image from the worker to a secondary resizer endpoint? Or creating a temporary file?

Any suggestions would be welcomed with open arms.

Thanks.

If you use firebase, you could do a simple technique.
Store your images in a directory that name is a SHA256 any of your choice.

https://your.web.app/040695334EE58D24AEEF8A94F7E71D4F23DBB1053159FE6E8A9657167693ECAEF567C6E6A40E5D2F4DAE823E2B7285BA5F93CA199EA0AEF5B5257EEFC3B8FB2E/image.jpg

then fetch the image with the worker.

Note that from a security point this is very very low.

1 Like

Is it really that low if you add rate-limiting? The chances of hitting any image is very low.

1 Like

Can you elaborate, on the rate limit suggestion?

1 Like

This is a good idea. Building on it can you not block user access to the original images folder using a firewall rule? I’ve not really done anything other than very simple tests with workers but I assume they’d not be affected by this, whilst an end-user would.

So just put the fullsized images in any old path which is blocked in a firewall rule, and have the worker retrieve, resize and return on a different, allowed, path? Obviously this assumes removing the auth is OK.

1 Like

You don’t need the firewall. Use the Web Crypto API to make a unique, URL-safe string (Like 100 chars) and set a path on the worker like /* and then dynamically create the routes in the worker based on a Key-value DB entry. To add basic rate-limiting, you can create a counter that increases if the counter reaches a certain time-increment (There’s no timer in workers, but you can simulate the creation of one using Promises), then block the request if the timer hits that value.

2 Likes

Thanks @adaptive (and @saul @thomas4) - this is a great suggestion. Definitely hadn’t considered it. There is a minor issue (that I neglected to mention) in that the image library is user-generated and uploads happen on the front-end … so the obfuscation/SHA256 would need to be per user.

Which makes me think a public key encryption system might work even better. Firebase generates a revokable token which allows full read access to a specific file from the url while retaining user-level security e.g:

Secure, private IAM access to user: https://your.web.app/filepath
Public access: https://your.web.app/filepath?token=XXX

Given that the tokens are generated per file I didn’t think it was useful at a Cloudflare system level (I would need to give CF significant DB access or create a convoluted structure specifically for this requirement), which is why I was originally looking at IAM with read-only bucket access … But if I provide the end-user a public key to encrypt their own image url (including token) and store the private key in CF Workers KV everything should work great!

Upload url (secure, private IAM access to user): https://your.web.app/filepath
Public access: https://your.web.app/filepath?token=XXX
Public key hashed: https://your.web.app/worker-route/YYY
CF Worker decrypted YYY: filepath?token=XXX

The best part about your crypto solution is that it saves a return journey to the Google oauth servers, and with a public key setup means there is per-image security in place that doesn’t rely on obfuscation.

Unless there are any better solutions out there - I think we can consider the problem solved. This is actually a better solution than CF Image Resizing supporting authorisation headers in this specific use-case.

Awesome. Thank you!

P.S. apologies for the slow response … currently traveling (with children!) and finding it hard to find time to get online

2 Likes