Handling unauthenticated responses in Apollo - apollo

I am using Apollo Server and Apollo Client and am having trouble handling unauthenticated responses. On the server, I throw AuthenticationError when a request is made and the user is not authenticated. On the client side, executing a query/mutation when unauthenticated sends an error to the catch block where I can see a graphQLErrors with "code":"UNAUTHENTICATED", exactly as expected.
What I would like to do is handle all of these unauthenticated responses in one central location so that if any request, ever, returns as unauthenticated I can redirect the user to the login page. The documentation for apollo-link-error shows how to use onError as an error handler with an example about unauthenticated responses.
The code I wrote in onError says if there are graphQLErrors that have the code "UNAUTHENTICATED", set "response.errors" to "undefined" and redirect to the login page. This logic seemingly works as expected as any unauthenticated requests are redirected to the login page.
However, the addition of response.errors = undefined as indicated in the "Ignoring errors" section of the apollo-link-error documents results in all unauthenticated requests throwing a Error writing result to store for query error. If I remove the response.errors = undefined logic, then the graphQLErrors "code":"UNAUTHENTICATED" error ends up in the catch block of every unauthenticated query/mutation which means I would need logic in every catch block to ignore that error but show others.
Am I doing something wrong here? How can I use onErrors to trap all "unauthenticated" errors and prevent them from appearing in the query/mutation catch blocks without the error listed above?

This answer helped me break down the problem and with enough troubleshooting I was able to arrive at the following answer for my particular situation.
By setting "response.errors" to undefined, request promises were resolved instead of rejected and the data being read in the "then" block did not exist which resulted in the error.
I'm writing the longer answer below from recollection as I have completely changed all of this logic in my application and no longer use any part of this process. I just wanted to provide an answer to anyone else having a similar issue.
My goal was to check all responses for authentication errors and redirect to the login page if necessary or otherwise continue as planned. Ideally, I would remove the authentication error from the response so that I could still handle other GraphQL errors at the query/mutation. Maybe it's my inexperience with Apollo (or JS in general), but I just could not get that to work.
Here's what I found. When using the onError method of apollo-link-error, you intercept all responses with errors and can perform whatever logic you desire (e.g. redirect if unauthenticated). However, this doesn't end the process. The calling query/mutation is still going to receive this response and the error may still need to be addressed. For example, if you have a catch statement that displays a notification to the user, an error handled in the onError method will still exist in the response. One way around this is to add response.errors = undefined to the onError method. Doing so will clear the unauthenticated error (and any other errors) from the response and continue.
This is where I was getting hung up. By clearing the errors from the response, the query/mutation promise will resolve instead of reject. Because it resolves, any logic inside the "then" block is executed which means the data that attempts to be parsed from a successful response is now attempting to be parsed from an error response. Sure, the "then" block could have been updated to check for data but in my view that defeats the purpose of the promise in the first place.
It was at this point that I decided to write a custom error handler and eliminate the use of onError. I found it easier to handle everything myself than try to delegate a portion to apollo-link-error but still have to handle some error handling logic elsewhere.

Related

XSRF and SOP, different outcome with apparently similar requests

I'm trying to learn more about XSRF and thus about SOP, I'm reading a lot and I have a more or less clear idea about what should happen and what should not, but I can't figure out why i'm obtaining different result while performing the same thing (I assume) in two different ways.
Same basic scenario of may similar questions, goodsite.com and badsite.com; badsite would like to make a GET request on goodsite.com using user's cookies.
I was able to make this work in a few different ways, a form with an onload send, a button with with an onclick function, they are all working correctly, the query is issued (and ofc i cannot see the response due to SOP).
However i can't figure out why this is not working
xhReq = new XMLHttpRequest();
xhReq.open("GET", "https://goodsite.com/doStuff");
xhReq.withCredentials=true;
xhReq.send();
This code, with the same settings/parameters of all the other working solutions is blocked by my browser with this error.
Access to XMLHttpRequest at 'https://goodsite.com/doStuff' from origin 'https://badguy.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What am I missing? Thanks.
Is the javascript CORS policy. Servers send a header to tell browsers "Hey, i don't want anyone outside my white list to send me requests using javascript".
Is a security mechanism to avoid things like read the request cookie headers etc.
You can avoid it using a server. There are some online like https://cors-anywhere.herokuapp.com/
Just add the url to this link if you are feching some content cross origen.
Extended: https://portswigger.net/web-security/cors

Postman inconsistent behaviour with cURL request

I have the following API downloaded in JSON from Swagger Editor:
PUT http://10.37.64.243/m2m/fim/items/fim:device:manager/operations/getAllDeviceTypes?exclude={{exclude}}
with exclude being an environment variable set as : href,metadata,name,arguments
Nominal use requires basic authentication, in this case it works and I get a JSON body with expected result. It properly works in Postman (so I think my import is correct)
If no authentication is provided:
in Swagger Editor : nominal behaviour, request is rejected with error code 401
in Postman : UNEXPECTED behaviour, I end up with status code 200 and it returns a response body identical to the one that I get when authenticated
if I generate the cURL code snippet from Postman and launch it out of Postman: nominal behaviour, I get the same error as the one I get in Swagger Editor (the one expected)
Why do Postman behave differently from the cURL request ??
I probably do something wrong, but I can't figure out what
Thanks for any help
Alexandre
I finally found out that the server returns a cookie that holds authentication validation. So after a valid authentication, whatever the request (with or without authentication) it will be considered as authentified.
Unfortunately, the only way to overcome that problem is to remove the cookie by hand through the "Manage cookies" window. Postman does not implement a function that erase it (even through the pm.cookies and pm.cookies.clear() function).
Postman developpers are aware of that, but there's no scheduling for this feature ...
EDIT: the feature is followed here https://github.com/postmanlabs/postman-app-support/issues/3312

HTTP status for different conflict scenarios

I'm implementing user registration for a Web Service.
When somebody wants to register an account, my WS sends an activation link to his/her mail. Until this link is clicked, user account is not activated (but the info is persisted in database, so the resource exists).
So my question is, if you try to register the same mail several times, you will get a 409 CONFLICT code. But there are two scenarios right there:
User account pending on confirmation
User already registered and activated
I would like to know what is the right approach. Should I "invent" an HTTP status 4XX to distinguish them, or send 409 with a JSON with info? other solutions?
Thx!
EDIT:
I have found this response -> https://stackoverflow.com/a/3290369/1171280 where Piskvor suggest to use 409 status and request header to explain the reason why it failed and/or body. Which one? header? body? both?
What do you think?
EDIT 2:
HTTP status + body with detailed error (with machine-parseable codes even) is OK, Twitter does that (https://dev.twitter.com/docs/error-codes-responses) and RESPECT :) . But I still doubt with 403 vs 409... :S
Pending account is a special type of a user account, so I think both accounts (already registered and pending) are same in the context of your question. You should return 409 in both cases. For the REST API both are same cases because that resource already exists in the system.
Regarding your updated question, I would suggest using body (JSON) to send out error(s) instead of using a custom HTTP header to explain the reason why the call failed. Reason is that in the body can you have multiple error messages (each one as a separate JSON object/array element) where as in the header you can have only one (though you can split based on some character). Other reason is that you can have one generic error handling method which looks for an "error" object in the JSON instead of looking for different custom headers for each failure scenario.
HTTP codes:
403 - The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be
repeated.
409 - The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in
situations where it is expected that the user might be able to resolve
the conflict and resubmit the request.
I think it should be 409 because the conflict can be resolved by re-issuing the request with different email address.
HTTP status codes are not meant to "invented".
409 CONFLICT sounds OK to me. Including details in the body ist OK, too, if your client needs to know.
Don't use 409. Use 403.
[409] is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request.
It's for a request that should have been OK, but has a problem that can be resolved. If you edit a document and PUT the revised text but someone else did the same thing before you did, you should have a chance to look at the other person's work so you don't accidentally undo all their work. You'd get a 409 which means, if you want to revise it, you should send your revision with an indication that you've seen the latest revision by the other person -- i.e. you know what you're doing.
There's no way to 'correct' a redundant attempt to register. The only way to avoid the conflict is to register with a different username, but that's very incorrect.
I'm imagining a POST request that takes a username and email address and creates a new resource dedicated to that new user (which should now be used for validation), sending that resource's URL in an email. So you're dealing with the refusal of the POST request handler to create a new resource, for a reason specific to the business model of your application (rather than an HTTP-related reason like bad syntax).
There's no status code more specific to what you want than 403. In this case, all you should use HTTP's vocabulary to communicate is 'that's not allowed' -- use the layer on top of HTTP to communicate why, like a polite HTML page or a JSON object for the client to understand and render as a polite HTML page.
409 should be ok; for the details https://datatracker.ietf.org/doc/html/draft-nottingham-http-problem-04 might be of interest.

Is it proper to use HTTP response code representing business exception on server side?

The background is like this:
The client web browser send a request to the server;
The server program will launch some biz check rules before doing the real work.
If check fail, some tips should be feed back to the client browser.
So, here is the question. Should I use an error response http code to indicate this, or use 200 directly, and then parse the message from response body.
Sometimes, this is not a problem. But, some client component give some util methods if error code returned. So, that's a hard decision to make:
return 200,and error message. parse and show them myself;
return some code like 500, let the client component to show it directly.
I would suggest to use as many http status codes as possible. That is a standard and why should you not use them?
Here are some examples where IMHO the usage of http status codes makes sense:
Somebody wants a dataset wich is not aviable use 404 not found
A secured ressource needs an authentification use 401
A ressource which is not aviable for the currient user should get a 403 forbidden
A error accours which you cannot handle well write out an 500 status
And so on
Look also for the logic for REST-APIs there you can see the advantages.
Typically, you'll want to indicate the reason the service failed. Returning custom errors can also potentially allow the client application to respond in an appropriate way. If an input validation check fails, for instance, I imagine the user would appreciate the chance to fix and resubmit the request. An HTTP error won't be enough to indicate what exactly went wrong.

OAuthException (#368) The action attempted has been deemed abusive or is otherwise disallowed

I'm trying to post a feed on my wall or on the wall on some of my friends using Graph API. I gave all permissions that this application needs, allow them when i make the request from my page, I'm having a valid access token but even though this exception occurs and no feed is posted. My post request looks pretty good, the permissions are given. What do I need to do to show on facebook app that I'm not an abusive person. The last think I did was to dig in my application Auth Dialog to set all permission I need there, and to write why do I need these permissions.
I would be very grateful if you tell me what is going on and point me into the right direction of what do I need to do to fix this problem.
Had the same problem. I figured out that Facebook was refusing my shortlinks, which makes me a bit mad...but I get the point because its possible that shortlinks can be used to promote malicious content...so if you have shortlinks as part of your test, replace them w the full url...
I believe this message is encountered for one of the two reasons :
Your post contains malicious links
You are trying to make a POST request over a non-https connection.
The second one is not confirmed but I have seen that behavior. While same code in my heroku hosted app worked fine, it gave this #368 error on my 000webhost hosted .tk domain which wasn't secured by SSL
Just in case anyone is still struggling with this, the problem occurs when you put URLs or "action links" that are not in your own app domain, if you really need to post to an extarnal page, you'll have to post to your app first, then redirect from there using a script or something. hope that helps.
also it's better in my opinion to use HTTPS links, as sometimes i've seen a behaviour where http links would be rejected, but that's intermittent.
I started noticing that recently as well when running my unit tests. One of the tests I run is submitting a link that I know Facebook has blocked to verify that I handle the error correctly. I used to get this error:
Warning: This Message Contains Blocked Content: Some content in this message has been reported as abusive by Facebook...
But starting on July 4th, I started receiving this error instead:
(#368) The action attempted has been deemed abusive or is otherwise disallowed'
Both errors indicate that Facebook doesn't like what you're publishing.