The session you inherit and cannot see
Enough OAuth, SSO and cross-context cookie behaviour to avoid designing an agentic surface that cannot ship — because a widget that needs its own login has already lost the argument with the host’s platform team.
The review gate has to show this user’s run. Not a run: theirs, the one the agent just executed on their behalf, with their data in it. So the component makes a request, and the request needs to say who is asking.
The design that gets drawn on the whiteboard is a small sign-in inside the component. It is a bad design, and its badness has nothing to do with cryptography. A user who is already logged into the host’s product is being asked to authenticate to a vendor they have never heard of, inside a page they trust, in a widget. The host’s platform team will not ship that, and they are right not to. A widget that needs its own login has lost the argument before the security review starts.
The question is not which auth. It is which origin.
Every delivery mode in this course puts your code in one of two places, and the session consequences follow from that and almost nothing else.
- In the host’s document. A custom element in their page runs on their origin. Their cookies are your cookies, in the sense that a request your code makes to their backend is a same-site request and carries their session by default. You are inside the trust boundary, which is a gift and a responsibility.
- In an iframe on your origin. Your document is a third-party context. Its cookies are cross-site cookies, and the browser decides whether they travel.
The mechanism that decides is SameSite. MDN’s Set-Cookie reference is direct about the two facts that matter: browsers restrict cookies sent with cross-site requests by default, and SameSite=None requires the Secure attribute. A cookie that has not opted in with both is simply not present on a cross-site request, and your API sees an anonymous caller.
This catches people in the case that looks safest. Your custom element is in the host’s page, so you assume you are same-site — but the request it makes to api.your-service.example is cross-site, because the site is theirs and the API is yours. Living in their document gives you their session. It does not give you yours.
What is actually true about third-party cookies today
This is the paragraph in the course most likely to be wrong if written from memory, so here is the state of the world as checked on 2026-09-05, per browser, with the confidence each claim deserves.
- Safari and Firefox block third-party cookies by default.
- Chrome does not. Google abandoned the forced Privacy-Sandbox phase-out — the reversal was announced in July 2024 — and shipped a user-facing choice prompt instead. Third-party cookies remain available in Chrome unless a user opts to block them.
Two things about that second bullet. It is a vendor product policy, not a specification, so there is no spec page to cite for it; the finding is triangulated across multiple 2026 reports that agree on the reversal and on the current behaviour, which is the right confidence level for a product decision and a lower one than anything else cited in this course. And it is a moving target. Re-check it before you write a date into a contract, and treat any undated statement about it — including this one, a year from now — as suspect.
Where people get burned
Most writing on this subject dates from 2020 to 2023 and says “browsers are phasing out third-party cookies.” That framing is now wrong for the browser with the largest share, and repeating it in front of a platform engineer who has followed the story costs you the room. The opposite error is just as expensive: “Chrome allows them” is not a design, because Safari and Firefox users exist, and a Chrome user can turn them off from a prompt the browser put in front of them. Design as if the cookie will not arrive, in every engine.
The Storage Access API, which is the mechanism either way
Whatever the defaults do this quarter, the platform’s answer to embedded state is the Storage Access API, and it exists for exactly this problem. MDN: “cross-site resources embedded in a third-party context are not given access to the same state that they would have access to when loaded in a first-party context”. Its named use cases include single sign-on with a federated identity provider, and utility widgets embedded across domains — which is the shape of this course written down by somebody else.
It is invoked per frame, through Document.requestStorageAccess(), and requires a secure context. The name is the important part: it is a request, and a request can be refused. Nothing you build may assume it succeeds.
// inside a cross-site iframe that needs its own cookies
if (document.requestStorageAccess) {
const hasAccess = await document.hasStorageAccess()
if (!hasAccess) {
await document.requestStorageAccess()
}
}Read that code as a cost, not a feature. Every branch of it is a state your interface has to render: access granted, access refused, API absent entirely. A review gate that shows a spinner in the refused branch is a review gate that hangs forever in some fraction of every host’s users, and no error will be logged anywhere, because nothing threw.
The design that ships
Work backwards from the failure. If your surface has no session of its own, none of the above can go wrong. That is not a trick — the host already knows who the user is, and the integration you want is the one where they tell you.
Two shapes do that, and both are requests you make of the host team, in the section of the graft contract that lists what you need back from them.
- The host hands you a credential. Their code, which already has a session, obtains something scoped to your service and passes it to your element as a property. Your component never authenticates anybody. Your API validates what it was given.
- The host proxies your API under their own origin. Requests go to
/agent/api/…on their domain, which makes them same-site requests carrying the host’s own session, and their backend forwards to yours. There is now no cross-site cookie anywhere in the design, so no browser default and no user prompt can break it.
The second is more work for the host and is usually the one their platform team prefers once they understand it, because it keeps every credential inside their perimeter and gives them a place to log, rate limit and switch you off. Ask for it early. It is a routing change if raised in week one and an architecture argument if raised in week nine.
Check your recall
Answer from memory — no scrolling back.
Retrieval check
A host’s platform engineer asks: “does your widget still work if the user has third-party cookies blocked?” Answer in three sentences, without hedging.
Check your answer
Yes, because it has no third-party cookie in its design. The component carries no session of its own: either your code hands it a credential you already hold, or your backend proxies our API under your origin, so every request the component makes is a same-site request with your session on it.
The honest version of the same answer, if you have not yet secured either arrangement, is worth practising too: today it depends on the browser, since Safari and Firefox block third-party cookies by default and Chrome does not as of the date checked, and that is exactly why we would like one of these two integrations rather than shipping something that works in some of your users’ browsers.
Hands on
Write the session path for each host
Done when: ARTIFACT.md carries a session-inheritance path for all three hosts: for each one, the origin the component runs on, whether any request it makes is cross-site, what the component gets for free, what it would have to ask for, and which of the two integration shapes you are requesting — with the ask written into the graft contract, not just noted.
- For each of the three hosts, write down the origin your component would run on and the origin of every request it would make. Two columns. Mark each request pair same-site or cross-site.
- For any cross-site row, write what happens in Safari, in Firefox, and in Chrome today — and put the date beside it. This is the row that will be out of date first, and a dated wrong answer is repairable in a way an undated one is not.
- Decide, per host, which of the two shapes you are asking for: the host hands you a credential, or the host proxies your API under their origin. Write the reason. “Whichever is easier” is not a reason and will be read as one.
- Add the ask to the graft contract, in the section listing what you need back from the host team, phrased as a request with an owner and a shape: what you need, from whom, and what your component does in the meantime.
- Write down, for each host, what your interface renders when the credential is absent. Not what it logs — what a user sees. If any host’s answer is a spinner, that host has a hang in it.
- Bring the three paths into the chat. I will ask which cross-site row you checked today and which you remembered.
What this does not cover
No auth implementation, no token format, no OAuth grant. That boundary is deliberate and the research behind this module respects it: cookie and storage mechanics were verified against MDN, and the OAuth specifications were not read, so no flow is recommended here even in passing. The identity engineering belongs to the host’s identity team, and your job is to arrive with a request they recognise.
The isolation properties of the iframe that make its session story so awkward — and the cases where paying that price is still the right call — belong to the micro-frontends module, alongside the response headers that decide whether an iframe is even permitted. What remains here is the demo: brand inherited, session inherited, one unchanged bundle, three hosts that disagree with each other. That is the last lesson, and it is the one that turns everything above into evidence.
Read this next — primary source
Storage Access APIMDN Web Docs — free. Fetched 2026-09-05
This lesson takes from it the reason embedded surfaces lose their state at all, and the fact that its own named use cases are single sign-on with a federated identity provider and utility widgets embedded across domains — which is precisely the shape of an agentic surface dropped into ninety products. Read the whole page, including the security section, because the parts this lesson skips are the parts a host’s security reviewer will ask about: what a granted permission covers, how long it lasts, and what a browser is entitled to refuse.
Stuck, curious, or think this lesson is wrong? Ask your teaching agent. The lessons are the scaffold; the conversation is where the learning gets unstuck.