When I need to do a front and back which speaks to each other with APIs, I do like this:
the user connects with their login/password
the back checks and if it is good returns a token to the front
the front stores this token in the localStorage
and for all future requests, the token is added in the form of Bearer
and for each request, the back checks the presence/validity of this token (middleware)
Perfect. Everything works.
Except that I read that storing the token in localStorage is not secure at all. And that it is better to use cookies. And this is precisely what Sanctum allows with Laravel. If I understand correctly, with Laravel Sanctum no more need for a token, everything happens with cookies between front and back. This is what I see with my different tests. I understood well?
I am disturbed by this.
Related
How can I authenticate a user with sanctum when the whole login process happens server side? The question I am asking is kind of hard to phrase so I will explain my situation.
I have a Vue SPA for my front end and a Laravel app as a backend api (they run on the same domain). Normally, to authenticate with the laravel api using sanctum, you would send the credentials in a post request, and if the login was successful, you would get the session information returned. However, I want to use steam login for authentication. I already have to whole process on the backend figured out in terms of actually logging in, however I am unsure how to pass the session data back to the SPA. Currently I have a link on my site that takes the user to the login endpoint on the api, and that endpoint will have them authenticate with steam, so the entire login process is handled on the backend. Now I just need to figure out how to send the session data back to the SPA. I guess it world be similar to using sanctum with socialite.
So far I've tried usisng Sanctums Mobile Aplication Authentication. I did this by having the user log in into the laravel app using steam, then once authenticated, a access token for their account would be created, and they would get redirected back to the Vue apps call back file, with the token as a part of the query string. Then the token would be stored and . This worked, however it presented some security issues.
The token was passed back in the url, so anyone could screenshot it and use it
Anyone who obtained the token by some other method could use it.
Here is the code for what I tried: https://gist.github.com/DriedSponge/4e8549486c2bfa33e4c0b21a539bdf85
So in summary, I want the entire login process to take place on the server, but somehow at the same time authenticate the SPA. If you have any ideas on how I can make this work, please let me know. If you have any questions just leave a comment. Thanks in advance.
Can someone assist me here, i have succeeded in setting up my passport on laravel 5.4 everything seems to work perfected. My question is once token is generated, am i supposed to save it for subsequent usage? i am just confused on the workflow. I am using password grant. I want to know how to pass token to another route that is making another call to another endpoint once token has been generated.
You append the token generated for each and every subsequent request that needs to be authenticated.In this case attach to the Authorization header of the request. Something like this:
Bearer eJ0eXAiOi.......
Maybe I searched with the wrong keywords but I never found anything about the following scenario:
I have both an API with JWT auth (Laravel + tymon/jwt-auth) and a PHP application that should query that API protected by a JWT token.
How can I make sure that the app always is authentificated? After reading a lot of tutorials and article about JWT auth I'm left with this ideas:
using a never expiring token which is stored permanently in the consuming application. If I understand it right this could be a security concern because someone who has access to that token has access to the api as long as he want? But I don't understand why this token shouldn't be invalidated if the token has been stolen?
refresh the token on every request and invalidate the old one. This implies that the consuming application have to update the token after each request in it's storage (database would make the most sense, I guess). In my opinion this produces a lot of overhead and it doesn't prevent for jwt-auth's refresh_ttl setting.
using an additional API request (perhabs cron based?) to a refresh route to prevent the token from expiring. Again there is the jwt-auth's refresh_ttl problem I think.
I wonder why there seems to be no discussions/articles about that scenario.
Any help on that subject I would very much welcome!
You don't want your user logging in every time but you also don't want them to be logged forever.
Here are my thoughts
I have worked with 1 year tokens for comercial applications, I was using it for low level third party developers, the api concept was already overwhelming for them so I went easy on the auth thingy. Once every year their application broke and they had to reach out to get the new token, bad design but it worked.
Refreshing your token on every request will kill your performance and let attackers have a consistent way to break/predict your key, no good.
In my opinion, this is your most elegant suggestion. You could use some PWA features to accomplish that.
I would suggest increasing the refresh_ttl to 30 days and keep the ttl on one hour.
If you're using SPA or heavy js apps:
On your javascript you could do an ajax setup (or prototype or whatever your javascript framework uses for oop) and have a call to refresh whenever you get a .
If you're using just common page refresh for your apps, store you JWT on a cookie, then your application can refresh it whenever it needs and there will be no special js to make. HTTPS will take care of security.
If I understand correctly, in a CSRF attack a malicious website A tells my browser to send a request to site B. My browser will automatically include my B cookies in that request. Although A cannot see those cookies, if I'm already authenticated in B the request will look legit, and whatever action was asked will be successfully performed. To avoid this, every time that I visit a page of B containing a form, I receive a CSRF token. This token is associated to my session, so if I make a POST to B I MUST include such token; otherwise B rejects my request. The benefit of this scheme is that A will not have access to that token.
I have two questions:
Is the above description correct?
If so, why can't site A first tell my browser to send a GET to B, obtain the CSRF token from the response, and then use the token to send now a POST to B? Notice that the token will be valid and associated to my session, as the GET also contains all my B cookies.
Thanks!
Your description is correct.
If site A tells your browser to go to B and get the token, that's fine, but as it is a cross-domain request, A will not have access to the token in Javascript (this is a browser feature). So when A tells your browser to go back to B and actually do something, it still cannot include the token in the request.
That is, unless B set the token as a cookie. Evidently, that would be flawed, because the token cookie would also be sent, thus negating any protection. So the token in this case must be sent as either a form value or a request header (or something else that is not sent automatically like a cookie).
This also means that if B is vulnerable to cross-site scripting, it is also vulnerable to CSRF, because the token can then be stolen, but CSRF is the smaller problem then. :)
Correct.
Site A can't get site B's csrf token because of the browser's CORS strategy.
And we need to validate the request's referer(It can be forged).
https://en.wikipedia.org/wiki/HTTP_referer
It is also a good practice to validate the crsf token in url(AKA query string).
FYI,Laravel, a popular web framework, uses a hidden CSRF token field in the form to prevent csrf attack.
Now I think securing ajax calls, sometimes normal forms with a token is pretty common. It works like this. 1) The user requests a page 2) a token is put into the html, and into the session 3) on submit these values are checked.
Now one major obstacle I am facing with this is caching. I do not have a lot of changing content, so I want to be able to cache for at least 24 hours. On the other hand, I do some ajax calls on the front-end, and good practice is to have them a little secured.
Now I was thinking of this, but I do not know if it will work. Maybe you can help.
user requests a site, and the cached site is given.
On the site, the first ajax call is made, which only asks a token
In the backend, a token is generated, stored in the session and sent to the front-end
The token is stored in a var in the frontend, and now sent with every call
On every call we check the session and the given token
If they match we do our DB stuff, if not we make a call to the FBI
The FBI takes over the case
Just kidding about the last part. But will this work, because you are not sending a piece of the actual website.
Maybe you can make it a little smarter by storing an identifier of the form the user requests.
Actually, I have no idea if this will work, I actually doubt it. Maybe someone can explain to me why this will not work.
In order to prevent csrf with a token, each user must have a unique token that an attacker cannot guess. If you serve the same cached page to everyone, then the token isn't a secret and an attacker can forge requests.
That being said. You could have some JavaScript use an XHR to pull that users token from the user's session data store and populate a form or in ajax calls.