Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/chilled-baboons-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@apollo/composition": patch
"@apollo/federation-internals": patch
---

Automatically propagate authorization requirements from implementing type to interface in the supergraph.

Authorization requirements now automatically propagate from implementing types to interfaces during composition. Direct auth specifications on interfaces are no longer allowed. Interface access requires satisfying ALL implementing types' requirements (`AND` rule), with these requirements included in the supergraph for backward compatibility with older routers.
22 changes: 22 additions & 0 deletions .changeset/eleven-maps-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"@apollo/composition": patch
"@apollo/federation-internals": patch
---

Fix transitive auth requirements on `@requires` and `@fromcontext`

Adds new `postMergeValidation` check to ensure that all fields that depends on data from other parts of the supergraph through `@requires` and/or `@fromContext` directives explicitly specify matching `@authenticated`, `@requiresScopes` and/or `@policy` auth requirements, e.g.

```graphql
type T @key(fields: "id") {
id: ID!
extra: String @external
# we need explicit `@authenticated` as it is needed to access extra
requiresExtra: String @requires(fields: "extra") @authenticated
}

type T @key(fields: "id") {
id: ID!
extra: String @authenticated
}
```
10 changes: 10 additions & 0 deletions .changeset/rotten-trainers-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@apollo/composition": patch
"@apollo/federation-internals": patch
---

Restrict usage of auth directives on interfaces

Restricts usage of `@authenticated`, `@policy` and `@requiresScopes` from being applied on interfaces, interface objects and their fields.

GraphQL spec currently does not define any interface inheritance rules and developers have to explicitly redefine all interface fields on their implementations. At runtime, GraphQL servers cannot return abstract types and always return concrete output types. Due to the above, applying auth directives on the interfaces may lead to unexpected runtime behavior as they won't have any effect at runtime.
59 changes: 59 additions & 0 deletions .changeset/tasty-snails-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
"@apollo/composition": patch
"@apollo/federation-internals": patch
---

Stricter merge rules for @requiresScopes and @policy

Current merge policies for `@authenticated`, `@requiresScopes` and `@policy` were inconsistent.

If a shared field uses the same authorization directives across subgraphs, composition merges them using `OR` logic. However, if a shared field uses different authorization directives across subgraphs composition merges them using `AND` logic. This simplified schema evolution, but weakened security requirements. Therefore, the behavior has been changed to always apply `AND` logic to authorization directives applied to the same field across subgraphs.

Since `@policy` and `@requiresScopes` values represent boolean conditions in Disjunctive Normal Form, we can merge them conjunctively to get the final auth requirements. For example:

```graphql
# subgraph A
type T @authenticated {
# requires scopes (A1 AND A2) OR A3
secret: String @requiresScopes(scopes: [["A1", "A2"], ["A3"]])
}

# subgraph B
type T {
# requires scopes B1 OR B2
secret: String @requiresScopes(scopes: [["B1"], ["B2"]]
}

# composed supergraph
type T @authenticated {
secret: String @requiresScopes(
scopes: [
["A1", "A2", "B1"],
["A1", "A2", "B2"],
["A3", "B1"],
["A3", "B2"]
])
}
```

This algorithm also deduplicates redundant requirements, e.g.

```graphql
# subgraph A
type T {
# requires A1 AND A2 scopes to access
secret: String @requiresScopes(scopes: [["A1", "A2"]])
}

# subgraph B
type T {
# requires only A1 scope to access
secret: String @requiresScopes(scopes: [["A1"]])
}

# composed supergraph
type T {
# requires only A1 scope to access as A2 is redundant
secret: String @requiresScopes(scopes: [["A1"]])
}
```
3 changes: 3 additions & 0 deletions .cspell/cspell-dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ iface
impelementation
implemenations
implementationt
impls
inacessible
incopatibilities
ineffectient
Expand All @@ -112,6 +113,7 @@ insteances
instrospection
Inteface
Intelli
intf
invalidities
isnodelike
issuels
Expand Down Expand Up @@ -191,6 +193,7 @@ Renamers
reoptimized
repeateable
reponse
Reqs
resovable
Reviwed
Rhai
Expand Down
Loading