Table of Contents

Class ContentSecurityPolicy

Namespace
Fdyay.IdentityServer.Configuration
Assembly
Fdyay.IdentityServer.Core.dll

Builds the policies this server sends, from CspOptions.

public static class ContentSecurityPolicy
Inheritance
ContentSecurityPolicy
Inherited Members

Remarks

Two policies, and they differ in the one way that matters: the interactive pages must not be framed, and the check-session iframe exists to be framed. Built in one place so that neither can be changed without the other being looked at โ€” a blanket policy would break OpenID Connect Session Management quietly, and a policy applied only to the iframe would leave the consent screen open to being clicked through.

Methods

ForCheckSessionIframe(CspOptions, string)

The policy for the check-session iframe, which is embedded by relying parties on purpose.

public static string ForCheckSessionIframe(CspOptions options, string scriptHash)

Parameters

options CspOptions
scriptHash string

Returns

string

Remarks

It carries no frame-ancestors, deliberately: OpenID Connect Session Management 1.0 ยง4 has relying parties embed this page, and forbidding that would stop them noticing sign-outs with nothing anywhere reporting an error.

Framable is not unprotected. The page's own script is named by its hash and nothing else may run, so being embedded does not make it somewhere to execute from.

ForInteractivePage(CspOptions)

The policy for a page a user interacts with: login, consent, device, backchannel approval.

public static string ForInteractivePage(CspOptions options)

Parameters

options CspOptions

Returns

string

Remarks

default-src 'none' because these pages run no script at all, so the policy can refuse everything rather than allow-list sources. Two exceptions, both load-bearing:

  • img-src permits remote https images, because the consent screen renders Client.LogoUri and a policy that forbade it would take every configured logo away silently.
  • style-src 'unsafe-inline', because the shared layout carries one inline stylesheet. Hashing it would be stricter and would turn an unrelated whitespace edit into an unstyled page, which is a worse failure than the one it prevents: a style cannot execute.

No form-action, since 0.177.0, as Duende's templates have none. The HTML Standard checks a form submission's navigation against the submitting page's form-action at every redirect it follows (create navigation params by fetching, with CSP Level 3's pre-navigation check), and Chrome and Safari do: the sign-in and consent posts redirect to the authorize endpoint, which redirects to the client's own origin, so form-action 'self' stopped the user at the last hop. The client's origin is not known to the policy โ€” it is any registered redirect URI, a custom scheme for a native app, or an upstream provider's sign-out โ€” and these pages carry no script and render nothing a visitor wrote, so there is no injected form for the directive to stop.