Realtime/GraphQL: AppContext carries no request origin, so a resolver cannot enforce an embed allowlist
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- graphql, typescript
- Domain
- api, authorization, backend, security
Research direction
Start in packages/MJServer/src/context.ts at contextFunction and the existing requestDomain calculation. Confirm the agreed AppContext shape, then ensure the normalized request origin or request information reaches resolvers; done means a resolver can inspect the request origin for authorization decisions, including when the client sends no Origin header.
Written by the indexing model from the issue text.
Description
Summary
AppContext gives resolvers { dataSource, dataSources, userPayload, providers } and nothing about the HTTP request. So a consumer that wants to make an authorization decision based on where the request came from — an embed origin allowlist, the browser equivalent of an IP allowlist — cannot, at any layer it owns.
MJ already computes the value. packages/MJServer/src/context.ts does:
const requestDomain = parseRequestHostname(req.headers.origin);
and threads it through authentication and login auditing. It is simply never put on the context the resolvers receive (contextFunction returns { dataSource, dataSources, userPayload, providers }).
Verified on next @ 6.1.0-edge.2.
Why a consumer cannot work around it
Three routes, all bad:
- Take the origin as a mutation argument. Client-supplied and trivially forged, so it is not a control — but it looks like one in the Studio, which is worse than not offering it. This is the "authored field that silently does nothing" failure mode of #3374 / #3859 / #3854, in its most dangerous form: a security setting.
- Enforce in Express middleware instead. Works only for routes the consumer owns. An embedded widget on a customer's own site talks to
/graphqldirectly, which is exactly the case an embed allowlist is for. - Read it from an async-local store. Nothing exposes one, and reaching around the context to grab the request would be depending on an implementation detail.
The ask
Surface what is already computed. Either shape works:
export type AppContext = {
…
/** The request's `Origin` header, normalized, or undefined when the client sent none. */
requestOrigin?: string;
};
or the raw headers / req itself, if that is more in keeping — the origin is what is needed, but a consumer with the request can answer questions nobody has asked yet.
requestDomain already exists a few lines away in the same function, so this looks like roughly a field on a type and a line in contextFunction. Happy to open the PR if the shape is agreed — I did not want to guess between "just the origin" and "the whole request".
What it unblocks downstream
A downstream product with an embeddable widget needs origin allow-listing, and today there is no MJ-side primitive to build it on — the host application cannot even SEE the request origin at the resolver layer, so any origin control has to be reinvented outside MJ per product. The column, grammar and inheritance for an allowlist are built and merged behind this; the authoring UI is deliberately withheld until the check can actually run, precisely so it does not become another silently-ignored setting.
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 295
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MemberJunction/MJ
-
next-protect requires only one status check, so PRs merge red and break the branch for everyone Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
MemberJunction/MJ#4609 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
MemberJunction/MJ#4603 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
MemberJunction/MJ#4570 ·
-
bug priority: high
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
MemberJunction/MJ#4548 ·
-
bug priority: high
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
MemberJunction/MJ#4547 ·
All issues in MemberJunction/MJ
Similar issues
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100