I have a Blazor Server app deployed to an Azure App Service using the built in authentication feature.
Traffic comes in via Azure Front Door, and a Content-Security-Policy is set (by the front door service) using an Overwrite rule that sets Content-Security-Policy to:
base-uri 'self'; default-src 'self' https://*.<myapp.com> wss://*.<myapp.com> https://dc.services.visualstudio.com/v2/track; object-src 'none'; script-src 'self' https://*.<myapp.com> https://az416426.vo.msecnd.net; img-src 'self' data:; style-src 'self'; frame-ancestors 'self'; form-action 'self'; upgrade-insecure-requests;
This works fine except for a single script which is involved in the authentication flow. According to Chrome dev tools the URL is still <myapp.com>, so I am unsure why it is being blocked. The script I am dealing with is:
<script>
function redirectToLoginPage() {
if (window.location.hash) {
document.cookie = "PreLoginUrlFragment=" + window.location.hash + "; path=/";
}
window.location.replace('https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=code+id_token\u0026redirect_uri=https%3A%2F%2F<myapp.com>%2F.auth%2Flogin%2Faad%2Fcallback\u0026client_id=<myappid>\u0026scope=openid+profile+email\u0026response_mode=form_post\u0026nonce=<A-Nonce-That-Changes-Every-Time>');
}
</script>
This page source is loaded in the client under my top level url - the interesting part is that this is in fact content presented by the Auth middleware container which runs inside the same VM on the App Service. This architecture is described in the Azure App Service auth documentation here: https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization#feature-architecture
The problem is that even though it is within the same host (though not the same container), the client somehow thinks it doesn't comply with the policy. I would expect it to be captured as 'self' based on the url, but it isn't... Example error from Chrome dev tools:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' https://*.<myapp.com> https://az416426.vo.msecnd.net". Either the 'unsafe-inline' keyword, a hash ('sha256-+3E1vW0Im9gtvTYo1w9L7vcEGlzuoxrOvvGJc+ABSZ4='), or a nonce ('nonce-...') is required to enable inline execution.
Normally for something like this I would add the hash to the policy - however the script contains a login destination URL with a nonce in it which is different every time the page loads, so the hash for the script is also different every time.
I cannot add a nonce to the script (or edit it in any way) because it's part of the auth middleware which I do not control.
I expected that by having both 'self' and the top-level domains of my app in the header that it would work. It currently only works if I add 'unsafe-inline' which is not an option due to security requirements.
The above CSP seems like it's really close to what I need, it's just this one script generating an error now (and unfortunately, preventing login, so it's a blocking problem).