Browser security configuration for the Klarna web SDK
Allow Klarna in your Content-Security-Policy and Cross-Origin-Opener-Policy headers, and configure the iframe attributes the Klarna web SDK needs when it runs inside an iframe.
7 min read
Overview
Use this page when a page that loads the Klarna web SDK sends browser security headers, or when the Klarna web SDK runs inside an iframe. If your checkout page sends neither Content-Security-Policy nor Cross-Origin-Opener-Policy and loads Klarna at the top level, there's nothing to configure here.
Your setup
What to configure
Your checkout page sends a Content-Security-Policy header
Allow Klarna's hosts. These directives extend your existing policy. If you use a default-src policy, make sure these hosts also appear in the corresponding directives.
Klarna injects styles for the loading indicators, the overlay, and the scroll lock applied while the pop-up is open. The content varies per purchase, so it can't be covered by a static hash. This applies to styles only. Klarna doesn't require inline script.
'unsafe-inline' in script-src
Not required. Klarna's scripts load from the hosts above and don't need inline execution. If you use a nonce- or hash-based policy, apply your nonce to the Klarna script tag the same way you do for your own scripts. Klarna needs no exception.
font-src and x.klarnacdn.net in style-src
Klarna's own typeface, loaded through a stylesheet on the CDN.
https://js.playground.klarna.com in script-src
Where the Klarna web SDK loads its code from when you initialize it with a test (playground) client ID. Without it the SDK doesn't load in the test environment.
data: in img-src
The Klarna logo on the payment button is embedded directly in the stylesheet.
https://osm.klarnaservices.com in img-src
The Klarna badge images shown in Payment Presentation when the presentation content can't be loaded.
https://*.klarnaevt.com in img-src
A fallback used to deliver telemetry when the browser blocks the primary transport. Omitting it degrades silently.
https://*.klarna.com in frame-src
Covers js.klarna.com, which hosts the hidden frame the Klarna web SDK uses for its API calls, and the Klarna payment host that the full-screen fallback loads when the pop-up is blocked. Narrowing this to one host breaks one of them.
Info
Run the policy in report-only mode first and watch for securitypolicyviolation events. It shows you exactly which directives your integration needs before you enforce anything.
Cross-Origin-Opener-Policy
The Klarna Purchase Journey opens in a pop-up, and Cross-Origin-Opener-Policy controls the relationship between your page and that pop-up. Browsers only apply this header to the top-level page. If the Klarna web SDK runs inside an iframe, the header that counts is the one on the top-level page around the iframe, and a value on the framed page has no effect. Set it to same-origin-allow-popups, or don't send it. It gives your page the same isolation from documents you did not open that same-origin gives, and it is the value to use with Klarna. Send it as an HTTP response header. Browsers ignore Cross-Origin-Opener-Policy when it's set through a <meta> tag.
Warning
Avoid Cross-Origin-Opener-Policy: same-origin. It cuts the link between your page and the Klarna pop-up, and the Klarna web SDK relies on that link to follow the pop-up while the customer completes the purchase. same-origin-allow-popups gives your page the same isolation from documents you did not open, so use that instead.
Info
Many sites send same-origin without deciding to: several security middlewares set it by default, Helmet among them. Check what your checkout page actually returns before assuming it's required: curl -sI https://your-checkout.example.com/checkout | grep -i cross-origin-opener-policy.
Iframe attributes
Klarna recommends loading the Klarna web SDK in a top-level page. When it runs inside an iframe, the page that owns the iframe element and the document inside it both need the configuration below. The guide for your case says who owns each side.
Side
Who it is
Parent page
The page that contains the <iframe> element. It's the Partner's page when a Partner frames your Hosted Checkout, and your own page when you frame the Klarna web SDK yourself.
Framed document
The document inside the iframe that loads the Klarna web SDK.
Configure the iframe element (parent page)
If the parent page applies the sandbox attribute, include these tokens and delegate the required browser permissions with allow:
Keep the framed document's origin for storage, cookies, and network calls.
allow-popups
Open the Klarna pop-up window.
allow-popups-to-escape-sandbox
Keep the Klarna pop-up out of the frame's sandbox.
allow-forms
Submit the payment form.
allow-modals
Show modal dialogs where needed.
allow-storage-access-by-user-activation
Let a third-party framed document request storage access after customer interaction.
allow-top-navigation-by-user-activation
Allow top-level navigation while user activation is available. Redirects still go through the redirect event and parent navigation, because activation may be gone when Klarna decides to redirect.
The allow attribute delegates separate browser permissions:
allow directive
Why it is required
payment
Delegate the Payment Request API to the framed document.
camera
Capture an ID document when identity verification requires it.
clipboard-write
Copy reference numbers from the Klarna Purchase Journey.
web-share
Open the system share sheet when the flow offers it.
With allow-scripts and allow-same-origin, a same-origin frame can reach its parent, so don't treat the sandbox as an isolation control.
Configure the parent page headers
If the parent page sends a Permissions-Policy header, it must grant the permissions to its own origin, the framed document's origin, and the Klarna origins before the iframe can delegate them. List each origin in full.
If the parent page is the top-level page and sends Cross-Origin-Opener-Policy, set it to same-origin-allow-popups, never same-origin. See Cross-Origin-Opener-Policy.
If the parent page sends a Content-Security-Policy header, add the framed document's origin to frame-src:
The framed document sends the Content-Security-Policy header above, the same as a top-level page. Cross-Origin-Opener-Policy on a framed document has no effect; the top-level page's value applies. Also restrict which pages can embed it with frame-ancestors, listing only the page origins you have agreed. Browsers check frame-ancestors against every page above the frame, not only its direct parent, so if the parent page can itself be framed, list those origins too: