Trying to connect to an on-premise Web API using SPFx and Azure AD / Application Proxy through SharePoint Online. Unfortunately I've hit about every blog and article on the matter and have worked through multiple suggestions which ultimately brought me to finally post the question in case something is amiss here.
An Azure Application Proxy was created to point to an on-premises Web API. Hitting the Web API directly through the browser prompts for credentials and returns an accurate response so that piece in itself appears to be setup correctly.
The issue is when trying to use SharePoint Online to get the correct data response. The SPFx solution package was deployed to the tenant and the API permissions were approved within the SharePoint Admin. So performing the following call appears to return the correct client and token information - but then has a CORS preflight request failure on the actual API call:
this.context.aadHttpClientFactory
.getClient('https://<ClientUrl>/')
.then((client: AadHttpClient): void => {
console.log(client);
client.get('https://<ClientUrl>/api/Account/CETEST', AadHttpClient.configurations.v1).then((response: HttpClientResponse): void => {
console.log(response);
})
.then((orders): void => {
// process data
});
});
Returned Message
Access to fetch at 'ClientURL/api/Account/CETEST' from origin 'https://Tenant.sharepoint.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I understand the CORS aspect, but allowing the origin on the IIS site where the Web API is hosted almost has no effect on the preflight through the Azure Proxy. When hitting the service directly, I can clearly see that the SPO Tenant is added as an allowed origin in the response. Also added the CORS configuration to the Web API itself with no difference. It's almost as if the preflight is hitting the Azure Application Proxy where CORS isn't even a thing and just denying moving forward.
Is there a strange configuration option that may be missed within the proxy to account for CORS that is under the radar?
One strange thing we had to do is that another SharePoint tenant must have already created the "SharePoint Online Client Extensibility Web Application Principal - Authentication" app registration in Azure, so we needed to add additional Redirect URIs to point at the correct Tenant.
Any help or additional troubleshooting steps would be greatly appreciated.
Thank you!
Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.
Unfortunately, I don't think this issue has to do with SharePoint... this is going to come down to the request from the browser => endpoint. I think you need to research this with the Azure App Proxy forums to have better luck as this forum is exclusively focused on SP dev.
In your code, when you run console.log(client);, use the URL to create a fetch request to the same endpoint. If you get the same result, that confirms what I've said above. SPFx's HTTP pipeline wraps the underlying browser fetch API.
@Cyan005 said:
Is there a strange configuration option that may be missed within the proxy to account for CORS that is under the radar?
Nope... not WRT to SP/SPFx.
@Cyan005 said:
One strange thing we had to do is that another SharePoint tenant must have already created the "SharePoint Online Client Extensibility Web Application Principal - Authentication" app registration in Azure, so we needed to add additional Redirect URIs to point at the correct Tenant.
Every tenant has that same Azure AD app... it's provisioned by MSFT the first time permissions are granted to an API.
@andrewconnell Thanks for the response! Appreciate it.
Yeah, I figured everything was working from a wrapper perspective as it appears to authenticate the client and make the token available for additional calls.
To the second point on the SPO Web Application Principal, the strange part was that having multiple SPO tenants within the same Azure environment, it did not add the second set of Tenant URIs after an API permissions approval. For instance, 3 months ago someone must have submitted an API permissions request was that was approved on Tenant-A.
When Tenant-A approved the API, the Azure AD app was created for Tenant-A.sharepoint.com and the corresponding Redirect URIs. When Tenant-B approved an API, the SPO Azure AD app was not updated with a new set of Redirect URIs for Tenant-B.sharepoint.com. The first part of the issue was that it wasn't working correctly until we copied all of the URIs created for Tenant-A and added them in for Tenant-B within the app registration.
Just in case anyone else runs into that issue in the future. That's how I hurdled getting the first part of the service call to work setting the AadHttpClient and move into actually performing the web API request:
this.context.aadHttpClientFactory
.getClient('https://<ClientUrl>/')
.then((client: AadHttpClient): void => {
Thank you!
@Cyan005 said:
To the second point on the SPO Web Application Principal, the strange part was that having multiple SPO tenants within the same Azure environment.
Can you clarify exactly what you mean by Azure environment?
Are you saying you have multiple O365 tenants connected to a single AAD tenant (ie: one AAD tenant ID)?
@andrewconnell, I need to do some legwork to confirm some things here. Unfortunately (or fortunately) I don't own the administration of these tenants and I belong to a rather large organization.
I'm not sure if it's multiple O365 tenants or just multiple SPO tenants. All I can confirm for now is that my same Azure AD credentials appear to work fine in both SPO tenants.
Going to reach out to some resources who may be able to map some IDs together to confirm. Will get back to this thread.
@andrewconnell So I received confirmation of what's going on here...
In my description Tenant-A is the primary SPO and Tenant-B is actually Tenant-ACAN setup as multi-geo. So URL is specified as "
So another user must have deployed SPFx requesting API permissions somewhere in the Canada GEO which originally configured the SharePoint Online Client Extensibility Web Application Principal - Authentication.
So that may actually be a bug that when the primary (non-GEO) then approved API permissions, no RedirectURIs were added/modified to account for what may technically be a new path. Until I added the non "can" URI as a redirect, the initial authentication for setting the client never succeeded in getting the token.
@Cyan005 said:
I'm not sure if it's multiple O365 tenants or just multiple SPO tenants.
...
In my description Tenant-A is the primary SPO and Tenant-B is actually Tenant-ACAN setup as multi-geo.
That's not what my original question was... my question was about the Azure AD tenant.
The Azure AD principal SharePoint Online Client Extensibility Web Application Principal exists only once in an Azure AD directory. When you grant permissions to SPO, you're really granting it to that service principal... you aren't granting it to that service principal in the context of the M365/O365/SPO tenant.
@Cyan005 said:
To the second point on the SPO Web Application Principal, the strange part was that having multiple SPO tenants within the same Azure environment.
Can you clarify exactly what you mean by _Azure environment_?
Are you saying you have multiple O365 tenants connected to a single AAD tenant (ie: one AAD tenant ID)?
It appears that it's a single O365 tenant connected to a single AAD tenant. Thanks for all of the timely responses, greatly appreciated.
From my experience, the issue here is that Azure App Proxy doesn麓t support CORS. This links tries to solve some CORS issues with Az App Proxy, but I had no luck in the past.
One "expensive" solution is to create a Proxy for the App proxy (yeah, I know), meaning an Azure Web API that uses server side code to call the Az App Proxy, and your spfx webpart calls your custom proxy. This is described here: https://stackoverflow.com/questions/43955808/cors-prelight-issue
You can also check here, as it says clearly that Proxy doesn麓t support CORS, and there麓s another solution posted there that might work for you (not ideal): https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/19335826-cors-for-app-proxy
For now, in the case of our SPfx webpart, we're redirecting the users to a redirect page on the proxy. We inform them we first need to "authenticate their request". This redirect page will simply redirect the user back to the page with the SPfx webpart. This way, the proxy authentication process takes place and subsequent XmlHttpRequests have the necessay authentication cookies for the proxy. Not ideal, but it works.
@luismanez Thank you for the response and information. I'll just assume moving forward that this is not possible unless we put a middle-man in-place to perform the service calls through the proxy.
I'll close this out with those final comments.
Thank you!
Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues