0

I am building a web application with NodeJs and Angular.

Now I have a routing setup with Angular and an API with NodeJs so Angular can communicate with NodeJs.

But when I set GET routes in NodeJs. They "overwrite" the routes from Angular, or they show plain data.

For example:

In NodeJs I have a GET /authorized which simply checks if the user is authorized, so it sends a true or false back. Now on my secured Angular Routes I am using a resolve which performs a GET on the /authorized route and if it returns true the user receives access to the page.

But the problem is, if the user goes to www.example.com/authorized. It will return a white page with "True" or "False". Now this isn't necessarily a security problem, but it doesn't look really nice. Besides I don't want users to have access to such api calls.

My solution is by making the route a POST call, but I don't think it's the proper way.

So my question is:

  • How would you do this?
  • Are there disadvantages to making everything a POST (even when you're not posting any data)
8
  • 2
    I usually see a path prefix (e.g. /api/) or a separate subdomain for the API. May 10, 2017 at 15:14
  • 1
    It sounds like you are implementing your security checks on the client. If so, this is inherently flawed. Otherwise, I don't understand what you are doing. Every call to the REST services should check authorization. What is goal of this resource?
    – JimmyJames
    May 10, 2017 at 17:03
  • @JimmyJames Every API call for example reading, writing, updating users etc. will have a security check on the backend. But the dashboard page on the clientside has to be secured as well. Which I do by using a resolve on the client-side route, that calls a service to the /authorized API which will return true or false based on the session (session on the server side).
    – Soundwave
    May 10, 2017 at 17:07
  • Do you have any resources for proper authentication with sessions and cookies?
    – Soundwave
    May 10, 2017 at 17:07
  • By 'securing the dashboard page', I presume you mean you need to figure out what to display based on what is actually available. It might not help here but have you considered a single call that returns a list of all the resources the user has access to? And if someone navigates to the page, you can always return whatever HTML you want. The request headers will be asking for HTML.
    – JimmyJames
    May 10, 2017 at 17:20

2 Answers 2

0

Two part answer: General Thoughts and an actual answer below:

General thoughts

From the context of the general application, I think you should specifically not try to do what you are asking how to do. A general rule of thumb I live by is that API endpoints should always return a proper API response.

For example, Marstato's answer will certainly accomplish what you are trying to do, but there are some unintentional downsides that can cause trouble down the road. Mainly, your accept-header is now effectively acting as a routing parameter. What happens if you accidentally remove that header from your request in angular down the road? What happens if another developer joins and attempts to implement the API call themselves not realizing the importance of the accept header? In both cases the result will be the same: they won't get back a true or a false, but instead will get back something else entirely. And that will be very confusing.

Again, there are certainly ways to do what you want to do, but I think the real answer is that you really shouldn't try to do that. Your API endpoints are for your developers only, and any response that can potentially confuse your developers is a bad response and shouldn't be returned by an API endpoint.

Yes, it is possible for users of your site to get to the URL in question and see a white screen with "false". However, your API endpoints should be bundled up and invisible to the end user, so there really is no reason why anyone should end up at example.com/authorized in order to see that screen. Clearly separating your api calls (e.g. api.example.com/authorized or example.com/api/authorized) is a good way of minimizing the chances of someone accidentally stumbling on your API urls, while also making your system a bit more organized.

So my general answer is that the likelihood and harm of someone accidentally stumbling on your API urls is (or should be) low enough that it isn't worth the extra logic in your API calls, especially since a non-standard response from the API may confuse yourself or other developers down the road.

Actual Answer

If you really do want to do this though, another way to do it would be to check for lack of login credentials. Presumably your API call is more than just a simple GET request? The API call is returning true/false depending on whether or not the user is authorized, correct? This means that the API call knows what user is being authorized, which means that user credentials are coming up in the request. Since you are doing a GET request that means that the credentials are either in the header, in a cookie, or in the URL parameters. Cookies shouldn't be used for API calls, so best guess is that the user's credentials are in the HTTP header in some form. However, if a user simply browses to example.com/authorize in their browser, those credentials will not be present. As a result you could just assume that a browser is being used if absolutely no user credentials are present in the HTTP header, and otherwise return a normal API call if credentials are present. The same also holds true if you are accepting the user credentials in the URL parameters (although that would be weird).

1
  • Changing the response content type depending on how authorization was performed seems wery weired to me and isn't very HTTP-like.
    – marstato
    May 10, 2017 at 22:31
2

Making everything a POST kind of works, but as you say, is by far not the proper way.

I see two solutions:

  1. Dont declare conflicting routes. Period.
  2. Use HTTP Content Negotiation: Browsers will send a Accept-Header containing text/html. If that is present, send out the full HTML application. In angular, send application/json (or whatever you encode your data with for http transport) in the Accept header. Detect this in your Node server and send out the raw data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.