Cannot get REST API response error messages in Outlook Add-ins - outlook

I was developing a few Office Outlook Web Add-ins and in none of them could I receive an response error message. Independently of the error that API returns I receive the following data object in fail function:
readyState: 0
responseText: ""
status: 0
statusText: "error"
withCredentials: true
Moreover in the Visual Studio or Browser JavaScript Console console I get:
Origin https://localhost:44347 not found in Access-Control-Allow-Origin header.
XMLHttpRequest: Network Error 0x80700013, Could not complete the operation due to error 80700013.
I would like to point out that CORS is enabled on the server, and I got this error independently from the action taken. It is the same when I give wrong parameter or make a typo in url.
I would also like to point out that API is OK, and such a thing does not happen when I request using JS in the browser (out of Office) or applications. I get a normal error messages from the server then.
In the example above the test is from localhost, but exactly the same situation is when hosted on remote web server.
What is wired about this is that I normally get success replies (with code and message).
What I would like to achieve is to get an error response as the server returns them. It is really hard to notify user what may be wrong with his request without this info.
[Edit]
For example, when I do the following request in a Outlook Add-in and I set the fake token I receive the mentioned error (or rather no error):
$.ajax({
type: 'GET',
url: API_URL + "/api/rooms/",
beforeSend: function (xhr) {
$.ajaxSettings.beforeSend(xhr);
xhr.setRequestHeader("Authorization", "Bearer " + token);
},
contentType: "application/json",
});
However, when I do the save request using Advanced REST Client I got 403:
"description": "You do not have permission to perform this action.",
"message": "",
"code": "permission-denied",
"status": "fail"
It happens in all Outlook version for me.

The issue is that the office add-in is sending a request to your web application over HTTP and the web project that gets created (I'm assuming you're using the Office add-in templates from visual studio) is by default configured for SSL, i.e an HTTPS connection. Whilst this is recommended for production apps, for debugging purposes you can simply click on your web project, then in visual studio click view on the Menu Bar - > then select the properties window -> then set SSL enabled to false. (see attached Image)
https://i.stack.imgur.com/Lvybn.png
Hope this helps!

Related

Are Service Workers supported in an Outlook OnSend AddIn?

I'm writing an Outlook OnSend addin (new style web addin, not old style COM), and would like to use a Service Worker to provide functionality when the user is offline. I've written an addin, and when I hit the addin's html page in Edge, I can see the service worker being installed and caching the addin files successfully.
However, when I run the addin in Outlook Desktop, it appears that the service worker is not being installed. I'm testing this by running Fiddler, and I can see that the adding files are being requested on each run, rather than coming from the cache that the service worker should be creating.
My addin HTML references a main.js (see below), which attempts to register the service worker. To provide some tracing/troubleshooting ability, I make an ajax call to a service. What this tells me is that:
The check for service worker support returns true
The call to navigator.serviceWorker.register never returns (successfully or otherwise)
Using Fiddler, I never see a request for the referenced "sw.js" file. I do see an edge process (microsoftedgesh) attempt to open an https connection to my server, but this doesn't request any files. All other traffic in fiddler is from the web view host component
Are service workers supported for outlook addins? I'm running Outlook version 2004 (12730.20270 click to run) and Windows 1909, so I'd expect Outlook to be using Edge rather than IE 11, and therefore to have service worker support.
For reference, my main.js looks like this:
if ('serviceWorker' in navigator) {
sendMessage('1');
try {
navigator.serviceWorker.register('sw.js').then(function(registration) {
sendMessage('2'); // Never sent
}).catch(function(error) {
sendMessage('3'); // Never sent
});
}
catch(err) {
sendMessage(err.message);
}
}
else {
sendMessage('4');
}
function sendMessage(message) {
$.ajax({
url: "../api/schedule",
type: "POST",
crossDomain: true,
//contentType: "jsonp",
contentType: 'application/json; charset=utf-8',
data: message
});
}
Service Workers are currently unsupported in addins and any Service Workers usage will be disabled in the near future.
We track add-in feature requests on our user-voice page. Please add your request there. Feature requests on user-voice are considered, when we go through our planning process

Outlook Addin - getCallbackTokenAsync fails- code 9017

Our company is using the Office js Rest API (via Outlook 2016) to retrieve a token for given user, and it just started failing. Investigation points to:
Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function (result)
returns error code 9017:
{"value":null,"status":"failed","error":{"name": "AccessRestricted", "message": "Internal protocol error: '-2147467259'."}}
We have ensured this request is made after
Office.initialize = function (reason) {...
has completed its operations (also this just started breaking for us this week/today).
Any guidance is greatly appreciated.. since this is a 'simple' call w/o any arguments to change the call signature, we're not really sure how to proceed.
Environment info:
Application: Outlook 2019 V1902 (Build 11328.20438)
Account: https://outlook.office.com/owa/{myUser}
Office.js API URL: "https://outlook.office.com/api/v2.0/me/"
It appears the issue was due to an API error when calling getCallbackTokenAsync - operation returned to normal this morning and we are no longer able to replicate the error.
We're going to chuck this up to an oops at MS. Any additional information regarding this error is much appreciated.
UPDATE: scratch that, error is back, what's going on MS?

Apple Pay completeMerchantValidation cancels session

My backend successfully validates the merchant and a session is returned, but when I complete the validation on the browser, it immediately cancels the transaction. There are a few similar complaints on the Apple Dev forum, but none seem to have been answered; I'm hoping you guys can help!
Out of all the event handlers on the ApplePaymentSession object, only onvalidatemerchant is called, then as soon as completeMerchantValidation with a valid session object (see payload below), oncancel is triggered.
Session config (on browser)
const session = new ApplePaySession(3, {
currencyCode: 'GBP',
countryCode: 'GB',
merchantCapabilities: [ 'supports3DS' ],
supportedNetworks: ['visa', 'masterCard', 'amex', 'discover' ],
total: {
type: 'final',
label: 'My Product',
amount: 9.99,
},
});
Request (on backend)
{
merchantIdentifier: 'merchant.MY.FQDN',
displayName: 'My Company Name',
initiative: 'web',
initiativeContext: 'MY.VERIFIED.FQDN',
}
Response (from Apple to backend, then sent to completeMerchantValidation
{
"epochTimestamp": 1552090296444,
"expiresAt": 1552093896444,
"merchantSessionIdentifier": "LONG_STRING",
"nonce": "XXXX",
"merchantIdentifier": "SAME_AS_IN_MY_MERCHANT_ID_CERT",
"domainName": "MY.VERIFIED.FQDN",
"signature": "XXXXXX-VERY-LONG-STRING-XXXXX"
}
I'm definitely sending this response into completeMerchantValidation as a JSON object and not a string, like so:
console.log('session is a', typeof(result), result); // says: object
session.completeMerchantValidation(result);
The domain name this is all happening from (and hosted on Firebase) is verified against this Merchant ID and I don't get any errors either in the backend or the browser console, no exception is thrown to catch, it just shows the Apple Pay tray, then says "Payment not complete" and hides the tray very quickly. Help!
UPDATE: Looking at the docs, it appears that startSession (which is being returned by onvalidatemerchant is being phased out, so I have tried replacing it with paymentSession (e.g. https://apple-pay-gateway-nc-pod5.apple.com/paymentservices/paymentSession); but I still get the same response and behaviour.
This solution may or may not work for you, but I was experiencing the same issue in that the session was being cancelled as soon as session.completeMerchantValidation() was called.
It boiled down to the merchantSession being created with a domainName value that was not verified (see: https://developer.apple.com/documentation/apple_pay_on_the_web/configuring_your_environment)
I used a local webserver broadcasting through Ngrok to validate a temporary URL by putting the apple-developer-merchantid-domain-association.txt file where it needed to be based on Apple Pay documentation.
After that, as long as I was using a sandbox iCloud account and a test Apple Pay card, passing the ngrok URL as the domainName value for the merchantSession request worked and Apple Pay finally started working locally. Note that I had to interact with my locally running web application through the ngrok url for Apple Pay to work.
I had the same issue where the payment sheet would display then go away without a chance to authorize the transaction. I made sure the domain was verified, the certificate was valid, and that I was actually receiving a response back from the server side request to Apple. Sorting through the process of elimination I came across certain interesting observations:
If the payment sheet disappeared immediately, it was usually due to a configuration issue with the server side request payload (for example, the "initiativeContext" was "something.com" when I was actually using "www.something.com" in the web browser address).
If the payment sheet disappeared after several seconds, it was usually due to a syntax issue or error in the client side JavaScript. In my case, I was not doing session.onpaymentmethodselected and session.completepaymentmethodselection correctly. So I removed all other Apple specific JS functions except for session.onvalidatemerchant and a subsequent call to session.completeMerchantValidation passing the Apple response from the server side request. It then worked.
If the Apple response from the server side request was in any way (even just the casing) changed from what Apple originally sent it would not work (for instance, "epochtimestamp":1668095263534," vs "epochTimestamp":1668095263534,").
Hope that helps.

Send POST AJAX request from Office Add-In

I'm trying to send POST Ajax request for third party service from my Outlook Add-in, but no matter what I tried I receiving Error: Access is denied, and status 0 (request never hit the server).
Assuming we are running IE9 or 8 behind the outlook I tried old school hacks like https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest.
$.ajax({
url: endpoint,
data: JSON.stringify({'1':'2'}),
// headers: {'X-Requested-With': 'XMLHttpRequest'},
contentType: 'text/plain',
type: 'POST',
dataType: 'json',
error: function(xhr, status, error) {
// error
}
}).done(function(data) {
// done
});
Is there is something more I need to implement? Of cause I add my domain to manifest AppDomain property.
Cheers
The following needs to be done to send request to 3rd party service ...
Add the service URI to AppDomain list (you've done it.)
The service MUST have SSL endpoint; "https://your.domain" must be included within of "AppDomain" entry (see above)
The service has to allow CORS requests for your application (hosted Outlook App URI) domain or any domain. This is up to the service creators to allow or disallow client apps connections via Ajax.
As of observation of your code I notices you are sending JSON object, but setting content type to "text/plain". Contact the service creators to get information on what type of the data they accept as request. Usually services allow "application/json", but not plain text.

identity Server - Configuring CORS for bearer options

I am testing the jquery ajax calls to the API server from a different domain. Unfortunately I am getting an OPTIONS error. Here is my request code:
$.ajax({
url: "https://localhost:44356/api/Default/",
headers: {
"Authorization": "Bearer " + user.access_token
},
success: function (res) {
logAjaxResult(res);
},
error: function() {
logAjaxResult('Error');
}
}))
Which gives
XMLHttpRequest cannot load https://localhost:44356/api/Default/. Response for preflight has invalid HTTP status code 405.
Normally this is an easy fix - I install Microsoft.AspNet.WebApi.Cors, set up a provider and allow OPTIONS through always. I can see how I would normally do this on the Identity Server box too as there is a CorsProvider you can register up. My issue however is on the API box I am using IdentityServerBearerTokenAuthenticationOptions and I see no CORs options. When I try to set up the WebAPI.cors provider though I get an error saying there are multiple origins set on the server to allow. This indicates to me (correct me if I'm wrong) that the WebApi box has somehow got the CORs settings from my identity server box that is registered as it's authority. Is this right?
How do I configure to allow pre-flight requests with app.UseIdentityServerBearerTokenAuthentication(options)?
Many thanks
This issue was resolved when I found the documentation uses
Microsoft.Owin.Cors
I was using the package
Microsoft.AspNet.WebApi.Cors

Resources