Hi,
I was testing IdentityServer4 RC3 and noticed the redirect after login does not work anymore in the Edge Browser. In the developer console of Edge it complains about the Content Security Policy in the header. At Stack Overflow someone else had the same kind of issue:
http://stackoverflow.com/questions/31720023/microsoft-edge-not-accepting-hashes-for-content-security-policy
I saw that this enhancement was made under issue #242 Add CSP/XFO security headers.
Is it possible to make the Content Security Policy in the header backwards compatible for browsers that don't support it?
Best Regards,
Jan
Chrome v54.0.2840.99 m (64-bit) also complains:
Refused to send form data to 'http://admin:5003/signin-oidc' because it violates the following Content Security Policy directive: "form-action http://admin:5003".
Until this is fixed, as a development-time workaround for Edge, issue into the console: 'document.forms[0].submit();'. That is the inline script it refuses to run. This will complete the flow.
In order to have Edge continue on its way, the following can be done to push it along:
Startup.cs::Configure
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy", "script-src 'unsafe-inline'");
await next();
});
Taken from reading here, this will allow un-hashed, inline scripts to execute. Do this only after understanding what it means to allow un-hashed scripts to execute. Further checks could also be done to only append this header on the page that is causing the issue, leaving all other pages un-touched. (The permanent fix will likely entail adding a hash to the inline script.)
@slepoiKot You might find the appropriate header for your case at Content Security Policy Level 2, form-action.
well, that sucks that edge is lagging.
It's not ... lagging. It's actually doing what it's supposed to, under CSP, that was turned on in #242. It's not supposed to run inline JS, anymore. When the page goes to run the 'document.forms[0].submit();', CSP tells it no, it's not signed.
So, either add the sha hash of the inline JS --or-- remove the inline JS, in favor of an external script --or-- remove the change to add CSP.
It's not ... lagging. It's actually doing what it's supposed to, under CSP, that was turned on in #242. It's not supposed to run inline JS, anymore. When the page goes to run the 'document.forms[0].submit();', CSP tells it no, it's not signed.
So, either add the sha hash of the inline JS
Is this the hash you're suggesting I add: https://github.com/IdentityServer/IdentityServer4/blob/dev/src/IdentityServer4/Endpoints/Results/AuthorizeResult.cs#L126
Yep. Though there seems to be something wrong with it, according to Edge. Here are the CSP-related complaints:
CSP14304: Unknown source ''sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY='' for directive 'script-src' in Content-Security-Policy - source will be ignored.
CSP14306: No sources given for directive 'script-src' for Content-Security-Policy - this is equivalent to using 'none' and will prevent the downloading of all resources of this type.
CSP14309: Unknown directive 'form-action' in Content-Security-Policy - directive will be ignored.
CSP14312: Resource violated directive 'script-src 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY='' in Content-Security-Policy: inline script. Resource will be blocked.
This hash matches the hash that was added so I'm not 100% certain what it's complaining about. Likely it's expecting a different hash. Also notice that Edge is having the same form-action issue that @slepoiKot is having with Chrome.
Ok, I figured out what's happening: Edge only supports CSP 1.0. SHA hashing isn't until version 2.
But. I have some good news. If you set it to:
script-src 'unsafe-inline' 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY='
Then all down-level browsers will allow unsafe-inline and all more recent browsers will require the hash.
For example, Edge with the new headers still complains it is going to ignore the source w/ sha256. However, it no longer registers a resource violation and works as expected. This means that it stays at 'unsafe-inline'.
So then it is lagging :)
Good news on the workaround -- I tested that and it does seem to work well (enough). Thanks.
I added this to dev. Not sure if we want to move back to old-style CSP, so I'll leave this open for now.
CSP2 is in development in Edge, so I'm leaning towards leaving this as-is (rather than reverting to CSP1).
I agree it's better to keep the CSP2 support. The unsafe-inline will keep the older browsers happy now.
Sorry guys to bother you, but how to step forward with this? After migrating from RC3 to 1.0.0 I got violation errors:
Refused to send form data to 'http://host:5003/signin-oidc' because it violates the following Content Security Policy directive: "form-action http://host:5003".
The source list for Content Security Policy directive 'frame-ancestors' contains an invalid source: 'http://host:5003'. It will be ignored.
The source list for Content Security Policy directive 'form-action' contains an invalid source: 'http://host:5003'. It will be ignored.
...
the same repeats 8 times
I've partially read document @kellystuard mentioned, thank you for this. And still confused and don't understand what to do next.
Post request sent back from IdSrv contains these headers:
default-src 'none'; frame-ancestors http://host:5003; form-action http://host:5003; script-src 'unsafe-inline' 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY=';
default-src 'none'; frame-ancestors http://host:5003; form-action http://host:5003; script-src 'unsafe-inline' 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY=';
@brockallen You said you have tested it and it does work fine.
could you please point me to right direction, I'm stuck.
Which browser are you in @BobBoba?
@brockallen these ones:
Chrome 55.0.2883.87 m (64-bit)
Firefox 50.1.0
and both are failing? are you running in an iframe that's not from that origin? do our samples work?
unfortunately, yes 8(
Do our samples work in your environment?
Yes, I confirm, examples works fine. I will try to find difference what makes my app screw.
Sorry to interrupt you, issue must be somewhere on my side.
Are you using an external IdP, such as google? We found a strange behavior/bug in chrome that causes CSP issues.
Nope, I use only identity server 4 1.0.0 and mvc6 client. This issue didn't happen on RC3. It happen only after updating to RC4 and newer versions.
Well, look into comparing the sames to your solution that is not working. I bet there's some URL mismatch somewhere.
@BobBoba I just committed code that removes the form-action from CSP on the authorize response. Can you test against the MyGet feed build to see if it fixes your problem. Thanks.
BTW @BobBoba we're tracking your issue here: https://github.com/IdentityServer/IdentityServer4/issues/659
Is it correct to leave unsafe-inline for older browsers from security site and possible XSS attacks? @brockallen are You consider move script to js file, in this way server will be more secure on browser with only CSP 1.0 supporting
@brockallen Let me just quote CSP specification:
In either case, developers SHOULD NOT include either 'unsafe-inline', or data: as valid sources in their policies. Both enable XSS attacks by allowing code to be included directly in the document itself; they are best avoided completely.
Why IdentityServer can't just use simple and secure policy like default-src 'self'? It would be more secure solution and is compatible with older browsers (CSP1 is widely supported). Chrome uses pretty similar policy for its extensions, and I see no reason why IdentityServer should be any different. It needs XSS protection as much as any other web application. And it should work properly on every popular browser.
PS CSP article on Chrome Developers portal has some useful hints related to getting rid of inline JS.
@MichalStaruch do you know if we add 'self' for the CSP2 browsers do they then allow any JS, or do they also see the 'sha256' directives and only honor those? IOW, the reason we went with 'unsafe-inline' was that CSP2 browsers ignored it when they say 'sha256' directives.
We have to weigh which is worse -- 'unsafe-inline' for older browser, or 'self' for all browsers.
@brockallen:
do you know if we add 'self' for the CSP2 browsers do they then allow any JS, or do they also see the 'sha256' directives and only honor those?
I ended up via search engine here and just dropping some info regarding this:
Inline scripts won't work on IE Edge (04/2017) even when 'self' is present; you'll need the 'unsafe-inline''. I suppose sha256 directive is supported by Edge tho.
@simison did you mean "unsafe-inline" or "unsecure-inline"?
@brockallen Good catch! :beers: I meant 'unsafe-inline. Updated my comment.
We have hit this issue with one our web vulnerability scanner. Because of this the login process is uncomplete, the form_post (hybrid grant) is not executing on authorizationresult to signinoidc.
This is using latest identityserver4 as on today.
console message - _Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'sha256-VuNUSJ59bpCpw62HM2JG/hCyGiqoPN3NqGvNXQPU+rY='"_
Thats using quickstart samples
We faced this issue for a customer that where running an old version of Edge (v38). After reading this issue and looking at the source I see that there is now an option to support CSP 1.0 browsers (documented here). As this was not mentioned in this issue I want to point it out to anyone else facing this problem:
c#
services.AddIdentityServer(options =>
{
options.Csp.Level = CspLevel.One; // For old Edge
});
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
We faced this issue for a customer that where running an old version of Edge (v38). After reading this issue and looking at the source I see that there is now an option to support CSP 1.0 browsers (documented here). As this was not mentioned in this issue I want to point it out to anyone else facing this problem:
c# services.AddIdentityServer(options => { options.Csp.Level = CspLevel.One; // For old Edge });