I do an HTTP POST request to the microsoft login to get an access token to use with the mail API, the request succeeds but the code goes to the error clause of my code.
requestAccessToken(code: string)
{
console.log("request access token");
if (code) {
var headers = new Headers();
headers.append("Content-Type", 'application/x-www-form-urlencoded');
headers.append('Accept', 'application/json');
var requestoptions = new RequestOptions({
headers: headers
});
var body = `grant_type=authorization_code&
redirect_uri=http://localhost:4200&
code=`+ code + `&
client_id=4e[................]5ab&
client_secret=CE[..............]BC`;
this.http.post("https://login.microsoftonline.com/common/oauth2/v2.0/token", body, requestoptions).map((res: Response) =>
{
console.log("response given");
const data = res.json();
}).subscribe( (data) => {
console.log("The data is = " + data);
}, error => {
console.log("The error is = " + error)
});
}
The browser console shows this: XMLHttpRequest cannot load https://login.microsoftonline.com/common/oauth2/v2.0/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. zone.js:2019 XHR failed loading: POST "https://login.microsoftonline.com/common/oauth2/v2.0/token". outlook.service.ts:96 The error is = Response with status: 0 for URL: null
here's a screenshot to show it better
Now the real problem is that my request succeeds as shown below:
and the response shows my access token. So why cannot I get it from code? Why does it go the error-clause.
You already tagged your post correctly with "cors". Modern browsers does not allow accessing endpoints across domains, unless the endpoint sends cors-headers which allows you to access it.
If you check your network tab, there should be an OPTIONS-request to https://login.microsoftonline.com/common/oauth2/v2.0/token. This s called he preflight-request, which checks for Access-Control-Allow-Origin and Access-Control-Allow-Methods headers. Access-Control-Allow-Origin must contain your domain or *, and Control-Allow-Methods must contain POST or *.
I'm not familiar with the office apis, but i think there must be a way to configure your app as an valid endpoint. Perhaps this post will help you: https://msdn.microsoft.com/en-us/office/office365/howto/create-web-apps-using-cors-to-access-files-in-office-365
What you’re seeing is expected behavior when sending a cross-origin
POST
to a server that doesn’t include theAccess-Control-Allow-Origin
response header in its response.Specifically, as long as your cross-origin request has no characteristics that will cause your browser to do a preflight
OPTIONS
request before doing yourPOST
request (which your request doesn’t) then thePOST
request will succeed on the server side—but, because the response from the server to thatPOST
request doesn’t include theAccess-Control-Allow-Origin
response header, your browser blocks your frontend code from being able to actually see the response the server sends.However, if you open browser devtools you can still see the response there. But just because the browser received the response and you can see it in devtools, it doesn’t mean the browser will expose the response to your code. It’ll only expose it when it has
Access-Control-Allow-Origin
.That all may seem counter-intuitive but it all makes sense if you remember that the browser is the only point at which cross-origin restrictions are enforced. Servers don’t block cross-origin requests.
When the server you’re sending that
POST
request to receives the request, it doesn’t check the origin to decide whether to respond. The server just accepts thePOST
request and processes it and then sends a response. But then the browser blocks your code from access to that response.But it’s also important to remember that the browser doesn’t block your code from sending that
POST
request cross-origin. Browsers only block cross-origin requests from being sent when the requests have qualities (like special headers) that trigger the browser to do a preflight.So since your
POST
request isn’t one that triggers a preflight, the browser sends it and it succeeds.For the sake of comparison, consider what happens for cross-origin
GET
requests. In that case too, as long at theGET
request isn’t one that triggers a preflight, the browser doesn’t refuse to send it cross-origin. Instead, the browser sends the request to the server, regardless. And the server receives thatGET
request and sends a response.It’s only when that response comes back to the browser that something different happens—because again, in that case, if the response doesn’t include the
Access-Control-Allow-Origin
response header, then your browser won’t allow your frontend JavaScript code to access it.But obviously since the entire point of making a
GET
request is to do something with the response, then in that case if your code can’t access the response, that’s a hard, total failure—in contrast to the case of thePOST
request, where the request body does actually still get posted as expected, but you just don’t have a way for your code to check the response to see if the request succeeded.