I have a client-side application on domain client-domain.com
and a server-side application on domain server-domain.com
. There is an API on the server-side. The client-side application sends AJAX requests to the server-side application. I use token-based authentication, so the client-side application sends token in headers with each AJAX request, for example: "Authorization: Bearer {some token}". It works fine with AJAX requests, when I need to get or post some data.
But the server-side API also keeps files. For example images. The files are private, only authenticated users can get them. And I need to show this images on the client-side in <img>
tag. I can't get them using <img src="http://server-domain.com/path/to/image">
because in this case browser will not send Authorization header to the server-side.
What is the adopted solution? How client applications load images from server-side API?
Token-based authentication works through this five-step process: Request: The user logs in to a service using their login credentials, which issues an access request to a server or protected resource. Verification: The server verifies the login information to determine that the user should have access.
If any of the third-party scripts you include in your page is compromised, it can access all your users' tokens. To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server.
Token-based authentication for web APIs is the process of authenticating users or processes for applications in the cloud. The user's application sends a request to the authentication service, which confirms the user's identity and issues a token. The user is then able to access the application.
There are three methods to solve it, the best approach to solve it is using the signed URLs
<img src="http://server-domain.com/path/to/image?guid=f6fc84c9f21c24907d6bee6eec38cabab5fa9a7be8c4a7827fe9e56f2">
When the server receives the request you must validate the guid if the expiration time not been reached and, of course, check if guid is a valid signature.
This approach is used by several files/documents servers like Dropbox, S3, CDN providers, etc.
See the technique in some companies.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html#private-content-overview-choosing-duration
https://client.cdn77.com/support/knowledgebase/cdn-resource/how-do-i-set-up-signed-urls
The second method is passed the token by querystring with the image URL.
<img src="http://server-domain.com/path/to/image?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c">
When the server receives the request you must validate the token by querystring and response with the content.
The third method creates an authenticated cookie to validate the access of the image.
When the server receives the request you need to validate if the validate cookie is valid.
My solution to basically this exact same problem, based on Jeferson Tenorio's answer below (option 1), was to sign the URL to my API call with an encryption of the image and the user's JWT token, e.g. path/to/image?token=xxxx
. In laravel this is easily accomplished with encrypt($your_object)
and decrypt($token)
(https://laravel.com/docs/5.7/encryption), and then I used the extracted token to verify the user had access to the file in question. But there are probably many other libraries capable of handling this.
I would be curious if there are any security concerns, but from my perspective the JWT is never exposed via plain text and the encryption relies on a secret key that malicious actors shouldn't have access to, so it seems like it should be fairly secure. My only real complaint is that the token is quite long using this method which does not make for presentable URLs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With