Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access private images with <img> tag in REST with Spring security & JWT

Current Scenario

A Spring project have REST API's protected using Spring Security and JWT. These API's produces JSON response. A UsernamePasswordAuthenticationFilter is implemented for validating JWT sent in Authorization header. Both authenticated and unauthenticated API's are working as intended.

Requirement

Now I need to sent an image in HTTP response for logged in user.

Solution1

Sent a byte[], representing the image as the value to an "image" key along with other information. But, this may take some time for the full JSON response, if the image is large.

Solution2

Sent a link as the value to an "image" key along with other information. The client can assign <img src=the_link>, which will supposed to fetch the large image in a separate request. Then create a request with @RequestMapping, corresponding to that link, which produces a byte[].

My Problem

I prefer Solution2. But it will produce UNAUTHORIZED exception as there is no valid Authorization token. Also, this API must be authenticated.

After some search, found out this, which is the same as my requirement. The accepted answer says,

The OAuth Bearer Token spec supports sending the token as a query parameter.

Is this what I must do?

  • In my Spring filter, get JWT from Authorization header, if it is empty, get it from request.getParameter()
  • In JSON response of first API, send "image":"http://ip/getImage?token=dbscsbCXV"
  • Create an API @GetMapping("getImage") byte[] getImage()

Or is there any better approach? Please guide me.

like image 224
Ramanujan R Avatar asked Feb 08 '17 05:02

Ramanujan R


1 Answers

Your suggestion to include the token in seems to be okay, if you:

  • Use HTTPS for your server, otherwise the JWT token in the request headers are expose (same goes for the Authorization headers).
  • Don't mind the image URL no longer working, when the token changes

Another approach may be to generate a random key with sufficient entropy (eg. combine 3 UUID's into a single string) and store this along with your Image entity, returning it from your REST services, eg:

https://ip/images/824b6854-edcc-11e6-bc64-92361f0026713567fef0-549a-4cdb-9264-5e15166dfd6f/the-file-name.pdf

Make sure you disable the Spring security filter for these "public" paths.

Advantages of this approach:

  • No need to check authentication for this resource
  • (if the image doesn't change alot) You can have this cached or serve the content through CDN, not hitting your servers every time for just streaming images.
  • URL will keep working, even if JWT token for auth changes

You might think this is less secure than the using a per-call authentication, but if the ID's have enough entropy, it's waterproof. Facebook also uses this concept (https://www.quora.com/Are-Facebook-pictures-really-private-and-are-they-hosted-on-Facebook-servers, https://en.wikipedia.org/wiki/Capability-based_security)

like image 189
Frederik Heremans Avatar answered Oct 15 '22 10:10

Frederik Heremans