How do I write ajax endpoints for my vue app to grab data from database while allowing only my vue app to call them? - vue.js

When a user changes a dropdown, I need to make an ajax call to an endpoint, that grabs the data and return it as a JSON.
I can do the event stuff with Vue, to make the request, but how do I guarantee that Vue is the requestor?
I can't really put an API key or something in the JS as that can be viewed through source. Someone could also watch the network tab in chrome and replay the requests to retrieve the data.

Unless you want to ask people to login first, there is no way you can do this. There is a HTTP header you can look for that most libraries add for Ajax requests, but that can be faked as well.

You cannot hide any information from the request you are making. It's the server side on which you can make your code strong. To prevent fake request you can use CSRF token, you need to also validate if the user is logged in, you can check session etc. before you send the result to the client.

Related

How to keep user logged in using Vuex?

I am managing performing a login and the login state using Vuex. It is a standard procedure of:
User submits their login details on a form
The form dispatches a Vuex action to make an axios API call to a Node/Express endpoint /api/login with the credentials
The response from the API if successful will send back the user's data which is stored in the state.user object through a setUser mutation. A flag of state.user.isLoggedIn is also set to true.
A JWT access token is sent to the user's browser and stored in a secure cookie to use over and over again until it expires. If it expires, a refresh token is used to generate a new JWT access token.
The site's header displays the user's login information .e.g name
The above all works as expected. However if the user refreshes their browser, then Vuex state gets emptied and the site header no longer shows the user information. To overcome this I stored state.user into localStorage in the browser as persisted data and repopulate the Vuex store using the data in localStorage on page refresh. If the user logs out, the localStorage is cleared.
There are many routes that require checking if the user is logged in. I cannot rely on localStorage because it can be manipulated by the user. If the user deletes their cookies which contains a JWT, then localStorage is not being emptied and the site header still displays their log-in information. Therefore I need to do an API call on almost every page to check if the user is logged in and if not then to delete the localStorage as well.
My question is:
Where do I perform a log-in check every time a page/view is accessed? Is it whenever the Vue app is mounted or within vue-router using the beforeEach navigation guard?
If I use beforeEach in vue-router, is it going to crash the site by making an API call to /api/login every time a user changes route? Is it normal practice to do this on every route?
Are there any other alternative patterns to keeping track of if the user is logged in or not?
Application decisions like this tend to be subjective because every application is different, with different requirements and different architectures. It sounds like this is a single page application, so I'll go from there.
First, the fact that your JWT is set up and working is great - that can be a lot of hard work, so be proud that you made it that far.
If your application has certain pages that are accessible without first being logged in (like a login page, or an access denied page, etc.), then you have to consider that in the design as well. In this case, a beforeEach route guard is the perfect solution to keep a route from loading or to catch those not-logged-in users before they attempt to request content that will likely just give them an error.
You probably shouldn't have to make an API call to the server each time the user navigates to a new page. That would probably be a little slow. Because your application uses JWT, complete with refresh tokens, you should be able to rely on them, so that if a user is logged in, they will continue to be logged in until they close their browser and walk away.
This is why you should not use localStorage. When a tab closes or even after a reboot, the user will still appear to be logged in. Instead of using localStorage, use sessionStorage - Helpful MDN link.
Now, the login event to retrieve the user object should only happen once per browser tab, but stay active during the visit.
I wonder why you don't just request a new user object from the server when the browser is refreshed. It's not strange to force a re-check to the server for a full page load. Doing that would mean you wouldn't have to use anything outside of Vuex to store the user's state
Next, is there a way to check the validity of their JWT during the navigation event? Depending on the way you handle the JWT, you may have access to it, and can possibly decode it (like through the oidc-client-js library), and that way determine for yourself if the token is expired. However, if the token is expired, your token refresh system may just refresh it and not tell you about it.
You can also watch your HTTP requests and look out for 401 or 403 responses (however your back-end handles logged-out users), and direct the user back to the login screen if you see one of those. You can use Axios' global interceptors to catch them, or do it yourself if you centralized the location from where Axios is called.
Overall, you're on your way, and clearly have a good grasp on this. Great progress so far, having done probably 90% of the heavy lifting already.

Is it possible to redirect back to a POST or PUT request URL after a successful SAML SSO assertion?

I have read about the relayState parameter in SAML SSO, and how the SP can redirect the user back to the original incoming URL by making use of relayState, but to my knowledge HTTP redirect only works for GET requests.
I am wondering if the same can be done for POST, PUT and DELETE requests, considering these requests usually come with data in the request body as well. I thought of returning a self-submitting form for POST requests, but this won't work for any other HTTP verb, and the original request must be a form based request too, unless the framework supports treating all types of parameters (query string, form field, json element) similarly. I also thought of making the frontend reconstruct the original request and sending it back to SP with AJAX, but I'm not sure if AJAX can actually update the browser's current page address.
My compromise solution in the end was to only relay URLs that result in a whole new page rendering with a GET verb only, and for any other requests, use the referrer URL for relaying instead. This means for the latter, the user will have to perform the task manually again after landing on the page he last saw before the SSO flow.
Not sure what the common practice in the industry is.
Thank you!
you would to maintain / save the POST data on the SP end and re-use them after SAML flow succeed. SAML as such does not provide any mean to achieve this.

vue-resource and JSONP working example

I'm struggling to make JSONP request using vue-resource. Can anybody provide some working examples demonstrating the proper way of defining jsonp callback, handling the call within Vue component and so on.
Thanks
**EDIT:**For other fellows, let’s clarify the situation a bit. What was the point - I have a non-authenticated user on the site and I wanted to let him do some action that requires authentication (create post e.g.). However, at the very end of creating post I wanted to show him sign-in modal window, let him log in using social oAuth providers and on successful login, let the post being approved and so on. Problem was that this call from the front-end toward different domains (social providers) was blocked (CORS issue) and than I tried to use JSONP to overcome the obstacle. Trying to setup JSONP call had spent a really lot of my time and finally I decided to go with totally different approach:
At the end of the process of creating the post, a cookie is created, caring the info what was the action that was interrupted with all necessary details. After that, a login modal is shown. Whole login process is done from the server side, and at the end, when identity of an user is confirmed, redirect to initial page is made. Further on, cookie is checked and based on the data, interrupted action continues execution successfully since the user is authenticated now.
#bryceadams thanks again for the answer!
How you handle it in your component will depend on your implementation, but typically it's done in a method - like if you had a form and then on submitting the form you called a method that made a JSONP request.
Here's an example call. Note that the important part is the jsonp option where you set the callback. This can vary based on where you're making the request to. Often it will be callback, but in my case I was working with MailChimp where it was c.
var options = {
jsonp: 'c'
}
this.$http.jsonp('https://website.com', options).then(function(data){
console.log(data.json());
}, function(error) {
// handle errors
});

Keeping cookies between outbound HTTP calls

I've got a Mule application that listens for requests from one application, then responds by calling a JSON API multiple times to authenticate and then retrieve several data, doing some transformation, and returning the results. The API requires HTTP basic authentication. When an account authenticates, the application that provides the API 1) returns a session/authentication cookie that can be used to identify the current user in subsequent calls, and 2) updates the database to record the last authentication timestamp for the current user. The API also has a call to check to see if the session/authentication cookie is still valid.
I currently have a flow that invokes the authentication method, then goes on to make a bunch of calls with the session/authentication cookie.
The issue is when the Mule application gets many requests at once, the application that provides the API deadlocks trying to update the authentication timestamp, since the flow will authenticate once for each request. Is there a way (possibly using the object store) to store the session/authentication cookie for use by subsequent requests to the Mule flow? Basically, I want the flow to suspend all other requests to the same flow, check to see if there are stored cookies, check to see if they are still valid, authenticate (again or for the first time) to get a new session/authentication cookie if needed, store the new cookie, then continue.
Is that a reasonable way of doing that, and is it even possible? If not, I think you can get the gist of what I'm trying to accomplish. What better way is there? Thanks!
edit: I've done a little experimentation, and I can definitely use the object store to hold on to the cookie. The part I'm stuck on now is how I get the only first request to re-authenticate if there is no valid cookie while any near-simultaneous requests wait. I'm looking into VM queues and the Mule Requester, but I'm not sure that that will work. I will post the code for a fully functional test when I'm done.

Can you send sub-sequential HTTP POST request to a sever

I'm just getting started in HTTP POST requests. So much so that I've got no idea if this is even going to solve my problem, but it seems like an interesting thing to learn about either way. Anyway, I currently do the following with a webbrowser control:
Navigate to a page
Enter username and password
Click the 'login' button
Enter some text into textboxes
Click another button (which loads a confirm page)
Click the confirm button
My question is does the HTTP POST request thing allow for the webclient to stay logged into the webpage, does it allow for posting to the page and then posting again once the update page has been received (steps 4, 5 and 6).
So you want to scrape some web content or manipulate a site from a program or script, but you're having a hard time. No, just switching to a POST will not help you here. Often, the problem has to do with authentication. What you need to do is preserve your session across more than one HTTP request, whether the requests are POST, GET, HEAD, DELETE, PUT, UPDATE, etc.
As mentioned in a comment, HTTP requests are stateless, where each request is independent of the others. However, web servers will still maintain some information for individual sessions, and so you usually still need more than one request. However, I find that much of the time, exactly two requests are enough to accomplish an action on a web site.
The first request will POST your login information to the site. At this point, the web site will issue a response. You need to analyze this response, because somewhere in there will be a session key. Now when I tell you to analyze the response, I don't mean that you write code to do this... that will come later. You need to actually send a sample request record the response, and read through it with your own eyes to find the session key. You also need to know how the web server expects to find the session key on future requests.
In this process, it's important to remember that a response consists of more than just HTML. In fact, the most common location for this key is in a cookie. Once you know how to get the session key, you need to make sure your next request includes that session key as part of the request. This is how the web site will know who you are, that you are authorized to perform the desired action, and what information to return.
The second request will actually perform the desired action. This could be a simple GET request, if all you want to do is retrieve some information from the site. It may also be POST, if you need to tell the site to perform some action.
To know what your requests need to look like, you can use a special kind of http proxy. Fiddler is a popular choice. You install the proxy to your computer, and then perform the desired action from a regular web browser. Fiddler will then tell you what requests and responses were sent. Even if you need to view a number of pages to complete your action via your web browser, often you still only need the final request to actually accomplish your goal. You use the information provided by fiddler to find and duplicate the required requests.
In the .Net world, the best tool for sending these requests and evaluating the responses is generally not the WebBrowser control. Instead, take a look at the System.Net.WebClient class, or look at System.Net.HttpWebRequest/System.Net.HttpWebResponse.