I'm trying to create an SPA with auth and roles.
I've been reading a lot of tutorials that explains how to do it and everyone tells the same strategy:
Save the permissions on localstorage, for example accessToken and is_admin=0|1.
So when you login the backend response fills this data.
Then the vue routing is just checking these 2 fields for granting or preventing the access.
This is so unsecure, anyone can access to develop tools and see this data and change it, just writing a random accessToken grants access on this site... and then is_admin = 1 and wala.
Okay, is difficult to KNOW this but... And every single API call checks this accessToken on the backend.
So there is something we can do to prevent this? Or if we want this "agility navigation" we can't protect 100% route navigation middleware?
One of the guides I followed:
https://scotch.io/tutorials/vue-authentication-and-route-handling-using-vue-router
On the questions section so many people is comenting this, and their response is that is a frontend demo... but how can I rely this on the backend? If I want this every navigation click will refresh the page.
A SPA will only load once. After that navigation is handled by the frontend. However the data needed for the next page is loaded using ajax from the backend. Meaning you can still validate access in the backend before exposing the data you want to protect.
Related
I'm building a CMS with vue 3 and want to know if using global store store.store.auth = false/true is a secure way of rendering in/out components that are supposed to be seen only by authenticated users. It goes like this:
User enters credentials in login form
Credentials are sent via HTTP request to backend and checked by laravel sanctum
Response arrives in frontend which sets store.store.auth = true
Components and routes that are supposed to be seen only by authenticated users are rendered via v-if
Is this a secure approach or can it be improved?
The security, in this case, depends almost entirely the backend.
Sanctum does not use tokens of any kind. Instead, Sanctum uses Laravel's built-in cookie based session authentication services. Typically, Sanctum utilizes Laravel's web authentication guard to accomplish this. This provides the benefits of CSRF protection, session authentication, as well as protects against leakage of the authentication credentials via XSS.
src
It seems like sanctum handles the authentication, so you should be fine as long as
store.store.auth value is kept up to date, and
the API does it's own authentication and authorization.
Because the entirety of the application is visible through the js source someone could potentially modify state and display options that they shouldn't see. This would be really-really difficult to prevent in SPA, that's why it is paramount that the backend handles this correctly.
You may be able to use code splitting, to prevent loading parts of the application that require authentication, but this is not security measure.
I am curious if anyone has a solution to this unique situation as I have a solution currently, though I feel it is not the most optimal.
The Situation.
I have built an MVC style web application that talks to a web API through http (authenticating via JWT). My web application is secured by appending authorization to its view controllers and redirecting to a Microsoft login endpoint - then directing back to the view where whichever given controller/function handles the request, connects to the API, appends data to the view, etc.
Preferably I would like to use JQuery/Ajax to submit http requests client-side and update a given view with whatever data the user may wish to see relative to the webpage they're on. This way I could control exactly what the user should see landing on the page any which way and submitting requests from web app to API. Also would enable better continuity between requests as there isn't actually a full refresh of the view. All in all it is my line of thought that this execution would lead to a nice user experience.
The Problem.
So the big issue that I have had to circumvent is CORS Policy. I initially attempted to use JS just as I said above but requests would be redirected to the login endpoint and blocked due to there being no CORS header appended to the request.
'So include a policy in your application and append an authorized header to your Ajax outgoing request' you might say, well... you cannot override CORS security around Microsoft's login endpoint.
My Solution.
What I have done simply instead is create HTML Forms around fields the user would pick and chose to specify what data they wanted from the API. Then carry over input data to the returned view via 'ViewData'
and using razor pages of course I can actually initialize JS variables via C# input.
Side Note
I use JS to transform the API data into graphs for the user to see. I am doing this with a JavaScript Library.
My Question to you.
This all leads me to ask then, is there a way to dynamically update a view without using JS? I require a method that can hit the login redirect without being blocked because the request initiated client-side.
Every solution I am aware in some way, shape, or form utilizes JS to make the request. So I am at a loss for how to truly get the functionality I am after without having my requests get blocked due to CORS Policy.
Thanks in advance y'all.
I have more conteptual question, how exactly should I handle social login in my project.
The use case is that I would like to allow user to login with Facebook, and keep on my backend information about this user (email, firstname, lastname)
I have some proposal Flow, but I'm not sure if it's a proper approach.
Let's say that I have application architecture as above. Now I would like to explain step-by-step full success flow.
Client (Vue application) make a call to AuthProvider (Facebook)
AuthProvider returns access_token
Client after reciving access_token make a call to backend endpoint like /fb_profile with access_token and userID (?)
Backend make a call to AuthProvider to check if given by client access_token is valid or not.
AuthProvider returns information about user. Backend after getting information about user, save it to database and generate new JWT token
Backend returns generated token to user
Now my question is - Is this good approach? Or should i handle it in other way? Like keep more logic to backend part? Instead of make a call to Facebook from Client, maybe should I make a call to backend, and backend make a call to Facebook?
You seem to be on right track. There could me many ways to do the same thing, here is the way which is working for me using vue/laravel/passport/socialite/github.
Trigger redirect in controller from frontend,
Provider(here github app) is triggered in browser with its url using client id/app name saved in back end config/env. Fill out your login details
It will redirect as created in provider and configured in backend-> show it on frontend, in my case its
http://localhost:8080/authorize/github/callback
From frontend now trigger callback in controller, it will check if user details already exist and will insert if its first time user as per logic. Then it will send back access_token to frontend which can be used in frontend for all the operations
DB
The above will be the sequence of the request flow ( same as yours ).
This would be the standard practice we used to integrate with Facebook. In this case, I strictly advise you to use the JavaScript SDK for Facebook.
Refer below link in case if you run into the following issue:
Vuejs component wait for facebook sdk to load
I've created a web application that uses the built-in authentication method for the web, once the user is authenticated he/she is presented with a dashboard page. At this moment Ajax calls to an API need to be made to fetch data for the logged-in user. What would be the correct approach to this to make it is secure?
As a next step, I would like to be able to use the API "stand-alone" as well, so a 3rd party could access the dataset through the API as well.
Right now I am looking into Laravel Passport as well as Spatie Permission package to help me with access control.
If you are using ajax calls in same domain it won't be problem with built-in authentication to give access to authorized users only, because tokens & sessions are accessible for laravel and you can get authenticated users by default.
If you want to make external api as well the best approach will be to use Laravel Passport and pass token in Authorization header as usual.
Hope this helps you
I'm learning both Sails and Vue.js and making a full REST app to do that.
So far from now, I've made a multi-step sign-up page in Vue which is working fine and POST all needed informations in my different Controllers in Sails, it also creates the user.
Now, I'm working on my login page. Again, no problem to PUT informations in my Login Controller and I receive an OK (200) response which let me know the user is logged on my backend server.
Now, I would like to understand how I could keep the information the user is logged-in my server and let him access to private content on my front-end app -> securely. I have understood that Sails use Sessions (alias of cookies ?). Also in the common example on the web, people tend to use JWT which transmit a crypted JSON between the two environnement (and so desactivate the cookies ?).
So, could you please give me a semantic explanation on how I can make both app exchange securely and manage it in Vue Js. I just need some "track" to follow.
SOLUTION
For those who like me are blocked at this initial step, I resolved my problem this way.
1) My backend Sails app generates a JWT (token) on each login.
2) My frontend Vue app stores that information thanks to Vuex and set the header of each request with an Authorization parameter composed of : 'Barear ' + token.
3) All frontend resquests to any Sails controller are verified thanks to a Policy which compares the token in the header of the request with the one generated at the first step.
Now I just wonder if using built in sessions in Sails is relevant or not.