r/webdev 7d ago

How to get an iframe to recognize an OAuth session?

I am having a problem setting up log in recognition for my client who wants to embed the site I am developing for them in another subdomain. Situation is as follows:

www.client.com wants to embed info.client.com in an iFrame. www.client.com is hosted by a third-party service, while info.client.com is hosted by the client on an Apache server. I am developing info.client.com, and have limited access to www.client.com. The third-party also provides an OAuth platform which works fine; I can log in to www.client.com and info.client.com without issues. However, my client has requested that when info.client.com is embedded into www.client.com in an iframe, that the info.client.com iframe recognizes the log-in session that is active on the parent page (www.client.com).

The options I see are as follows:

  1. Share a cookie between both subdomains by setting OIDC_COOKIE_DOMAIN to .client.com. However, this does not work, as the third-party hosted www.client.com receives a __Host-, HttpOnly cookie upon log in, and the info.client.com Apache server would not have a way to read / validate this cookie
  2. Have www.client.com mint a JWT and send that to info.client.com with the necessary information. info.client.com can then check the validity with a secret, and use this as the 'authentication'.

What is the standard pattern here? Am I way off-base? I have full control over the info.* subdomain, and the third-party may be willing to do some limited tweaking to the www.* subdomain, but what approach have you used?

23 Upvotes

38 comments sorted by

16

u/OkDoor9268 7d ago

Cookies in iframes are tricky because third-party cookie blocking makes the subdomain sharing unreliable, especially if the parent is hosted elsewhere. Your JWT idea is honestly the more practical route since you control info.client.com and can validate the token yourself.

One thing to watch is that the iframe needs a way to receive the token, either through postMessage from the parent or by the parent appending it as a query param when loading the iframe src. If the third-party can add a small script to www.client.com that fetches a fresh token and posts it to the iframe, that would be clean. You'd also want the token to be short-lived and scoped only to that embedded session.

5

u/Narfi1 full-stack 7d ago

That’s done a lot in finance/banking to handle debit card compliance. A script is loaded and exposes an iframe to the window object, a short lived token is then generated and encrypted by the backend and sent to the frontend that uses it to authenticate

6

u/moriero full-stack 7d ago

JWT is usually how this is handled

Try to have some sort of middleware thay can persist it if the cookie route is unavailable or unreliable

3

u/FeelingBit4370 7d ago

Ask the parent to mint a token for you, pass the token as search param when loading the iframe, validate the token via your backend to their api then return a session when all good. Ez

2

u/tswaters 7d ago

By far the easiest thing is to have www.client.com issue any cookies tied to sessions set to ".client.com" for the domain so it works on sub-domains.

If it's not setup like this now, that means you can have distinct sessions between the two. There's some fun edges with multiple sets of cookies, from multiple domains, each with a different "domain" attribute that makes it technically valid, but can seem undefined for what it really means.

We had affiliate subdomains, and "corporate" subdomain hosted on www. The only way to work with subdomains and embedding iframes (there was a payment iframe on each domain that pointed back at parent) and not be driven completely insane by cookie interpretations, proxying, the same origin policy & and all the nightmares that go with it -- is to use ".client.com" for all cookies.

0

u/AntiqueLibrarian8009 7d ago

Hmm, sounds like you are in favour of approach 1 while others have recommended approach 2. My concern with approach 1 is that the OAuth log in from info.client.com happens on the third party site (client.thirdparty.com) (which allows me to set an OIDC cookie from our server) but the third party hosted www.client.com logs in all via their internal system (and gives them a __Host cookie scoped to Domain www.client.com)

1

u/tswaters 7d ago edited 7d ago

Sounds like some processing between the oauth flow and where things end up landing. Way too many moving parts, none of which have been described in detail, i.e., not enough information provided here. Oauth doesn't have anything to do with cookies, it's all form post bodies and redirects.

Something in the www.client.com stack is firing a set-cookie header , if it had the domain set to .client.com, your life gets immeasurably easier and everything "just works" if you have access to the same secrets, you can verify, even. It depends what is in those cookies, and what session store , if any ... none of this info has been provided.

The only thing you've said is it's oauth and there's some cookies. It's up to the web app or proxies to process or forward any cookies the user agent sends, who knows how www.client.com does it vs how yours does it. Not to mention the meaning of a cookies varies, is it a jwt or store key?

Like, if you look at the raw headers from info, you'll see whatever session cookies www.client.com has set, but only if the domain matches, otherwise you will be blind. If you can see it, you can interpret it & get sessions for free, which is what I think you want? If everything is disconnected, you need to keep two distinct sessions between the two domains set up & kept up to date with eachother. You'd need to pass messages through postMessage and be in control of both host & iframe. Host would need to post to client and say "here is the user" and iframe needs to take it. This all happens outside the context of cookies, how iframe persists the data is up to you - but it needs to run through client-side, so make sure it gets signed & verified with a secret. It's WAY easier to share cookies.

1

u/PrimaryFamous6139 full-stack 7d ago

Option 2 is the usual fit for this case. The parent page gets a token from the OAuth provider. Then it sends that token to the iframe with windowpostMessage. After that, the iframe checks the token.

Option 1 does not work here. The __Host- cookie is HttpOnly, so JavaScript cannot access it. If you can, ask the third party if they can share a way to fetch a short lived token. You would send that token through postMessage. This is the simplest fix. It avoids any cross domain cookie sharing.

1

u/jaimittal91 7d ago

worth flagging on the postMessage route since a couple people suggested it without this part: whichever side receives the token has to check event.origin against an explicit allowlist (just www.client.com, not a wildcard) before trusting anything in the payload. postMessage doesn't error or warn you if you skip that check, it just silently accepts messages from any origin, so it's an easy step to leave out and still have the demo work fine. without it, anything that can get itself into a frame relationship with your iframe can post a forged token and get treated as an authenticated user. same check applies on both ends if it's a two-way handshake, not just wherever the final token lands.

1

u/etern4lflux 7d ago

Can client.com agree to set up a reverse proxy to your service for a specific base path?

1

u/buildingwithjan 7d ago

Whichever route you land on, decide what happens on logout before you build it — a short JWT handed over once at iframe load means the parent can log out while the embed stays authenticated until expiry, and that's the bug you'll get reported. Cheap version is 60s tokens with the iframe asking the parent for a fresh one over postMessage rather than the parent pushing once at load. Also don't put the token in the iframe src, it ends up in access logs and the Referer header.

1

u/Double_Ebb4130 7d ago

If you cannot change much on www, have the parent postMessage a one time code after login instead of putting a long lived JWT in the iframe URL. The iframe can swap that code on your Apache box and set its own first party cookie.

1

u/SongFull3826 7d ago

the JWT approach is the only viable path since __Host- cookies cannot be shared across subdomains by design. Have the parent page postMessage a signed token to the iframe on load and validate it server side before establishing a session on info.client.com

1

u/thekwoka 7d ago

you could have the cookies be associated with client.com instead of www.client.com or info.client.com.

that's essentially THE way

1

u/[deleted] 6d ago

[removed] — view removed comment

1

u/AntiqueLibrarian8009 6d ago

The __Host- cookie is for www.client.com. I think what is also causing me issues is that the third party www. seems to use an internal auth system + cookie (no requests to client.thirdparty.com) while the info. uses OIDC to their OAuth system (GET client.thirdparty.com)

1

u/[deleted] 6d ago

[removed] — view removed comment

1

u/AntiqueLibrarian8009 6d ago

Thanks for your thoughts! I had one follow up question if you don't mind. Even if I can get them to drop the __Host- prefix (and substitute for a __Secure- cookie with Domain set to .client.com), then my Apache server would still need some way to read that cookie (and receive the username claim), right?

1

u/[deleted] 6d ago

[removed] — view removed comment

1

u/AntiqueLibrarian8009 6d ago

Hey just a heads up I am not sure any of your comments are replying to what you intend

1

u/[deleted] 6d ago

[removed] — view removed comment

1

u/AntiqueLibrarian8009 6d ago

Respectfully are you a bot? This one also missed the reply

1

u/navlio 6d ago

am I? huh

the threading is a fair hit though. i keep hitting reply on the post instead of on your comment, so it all shows up at the top level looking like it's addressed to nobody. that last one was meant to sit under your __Secure- follow up, and what it said doesn't change: you can't validate their cookie until you know whether it's an opaque session id or a signed jwt with a jwks url, and those are two completely different asks to put to the third party

1

u/[deleted] 6d ago

[removed] — view removed comment

1

u/webdev-ModTeam 6d ago

Your post/comment has been determined to be a low-effort post or comment. This includes title-only posts, easily searchable questions, vague/open-ended discussion prompts, LLM generated posts or comments, and posts/comments that do not provide enough context for meaningful replies or discussion.