Where this server is willing to send a browser
Registration decides whether a redirect target is honoured. It does not decide whether the target is a location at
all, and the two are different questions once a client registration can come from an administration screen, a
registration API or a SAML metadata document. ValidationOptions is where the
second question lives. The code on this page is included from
samples/Interaction.Checks,
whose test sends an authorize request for a client registered with a refused redirect URI and checks the browser is
not sent there.
The refused prefixes
// Added to the schemes this server will never send a browser to: these clients are all web applications.
options.Validation.InvalidRedirectUriPrefixes.Add("intent:");
The defaults, listed in the configuration reference, are javascript:,
data:, vbscript:, file:, blob:, about: and view-source: — schemes a browser asked to navigate to either
executes, or answers with a document carrying its own origin. The list is settable: a deployment can add to it, as
above, or take one away with Remove. They are refused wherever this server hands a browser a registered address:
redirect_uri at the authorize endpoint (to the error page, never to the client), post_logout_redirect_uri at the
end-session endpoint, the front-channel logout iframes, the consent screen's link to Client.ClientUri, and the SAML
assertion-consumer and single-logout endpoints. The client configuration validator refuses a registration naming one in
its RedirectUris or PostLogoutRedirectUris too, judged by the same check (Duende's messages).
It is a deny list, not an allow list of http and https, because a native client legitimately registers
com.example.app:/callback and an allow list would refuse it in order to catch a hostile registration. The comparison is
made — ignoring case — against a normalised copy of the URI: tab, carriage return and line feed removed from anywhere,
leading control characters and spaces trimmed. That is what a browser does before deciding what scheme it is looking at,
so java	script:alert(1) is javascript: to a browser and would otherwise be nothing at all to a StartsWith.
IsAllowedRedirectTarget is the check, for a page or
endpoint of your own.
Client.LogoUri is deliberately outside this. The consent screen renders it as <img src>, which does not execute a
javascript: URI, and a data: logo embedded in a registration is a legitimate thing the page's own CSP already
permits. Applying the rule there would break a working feature to prevent nothing.
New in 0.39.0. The sharpest of those sites is SAML. The HTTP-POST binding answers a service provider by returning an HTML form that submits itself on load, with the registered reply address as its
action; HTML-encoding stops markup escaping the attribute and leavesjavascript:intact, and the page is written by an endpoint rather than served as a Razor page, so the interactive pages' Content-Security-Policy is not over it. The refusal has to happen before the first form is built and leave by the error page — the SSO endpoint's own refusal path posts itsNoPassiveanswer to that same reply address, so a check one line later would have announced the refusal through the address it was refusing.