Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I load images if I use token-based authentication

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?

like image 569
Ildar Avatar asked Dec 04 '15 20:12

Ildar


People also ask

How do I use token based authentication?

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.

Where should authentication tokens be stored?

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.

For what purpose is token based authentication used in websites?

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.


Video Answer


2 Answers

There are three methods to solve it, the best approach to solve it is using the signed URLs


  1. The first method simply creates a route without authentication (anonymous access) with a signature hash parameter that indicates if the resource can be loaded or not.
<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


  1. The second method is passed the token by querystring with the image URL.

    • This method is not recommendable because expose clearly the url and many servers sometimes write and expose public logs of URL accessed. The bad notice is that the JWT exposed normally the user can get control a lot of features further the image load.
<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.


  1. The third method creates an authenticated cookie to validate the access of the image.

    • This method is not recommendable because is out of API pattern (webapi/token based authentication in general).

When the server receives the request you need to validate if the validate cookie is valid.

like image 90
Jeferson Tenorio Avatar answered Oct 12 '22 22:10

Jeferson Tenorio


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.

like image 31
Kyle Crossman Avatar answered Oct 12 '22 21:10

Kyle Crossman