reactioncommerce / federated-gateway

An access aware federated GraphQL API gateway for the Reaction Commerce ecosystem
Apache License 2.0
6 stars 3 forks source link

Vet and use custom directives for authorization #36

Open rosshadden opened 4 years ago

rosshadden commented 4 years ago

What

GraphQL as a spec supports custom directives. This is how Apollo is able to add things like @key and @external.

We can leverage our own custom directive(s) to better support authorization (for example). The linked docs have an example section on authorization, but we can do something even better since we have our authorization already abstracted into its own service.

Inside our schemas we can annotate types, queries, and mutations with things like their resource path, which would let us implement gateway-level authorization.

For example:

@entity("reaction:pricing:pricebooks")
type Pricebook @key(fields: "id") {
  id: ID!
  name: String!
}

@entity("reaction:pricing:pricebook-entries")
type PricebookEntry @key(fields: "id") {
  id: String!

  @entity("reaction:pricing:pricebook")
  pricebook: Pricebook!
}

type Query {
  @ref(resource: "reation:pricing:pricebooks:*", action: "read")
  getPricebook(id: ID!): Pricebook

  @ref(resource: "reation:pricing:pricebook-entries:*", action: "read")
  @ref(resource: "reation:pricing:pricebooks:*", action: "read")
  getPricebookEntry(id: ID!): Pricebook
}

Some notes on the above:

How

The work required for this issue:

Why

This lets us do some really cool things. It will let us go from have 0% of our authorization checks at the gateway level and 100% at the app level to having most of them (by far) at the gateway level. This means we will be able to determine whether users are authorized to perform certain actions before we even call out to the app in question.

focusaurus commented 4 years ago

~Do we want to define some default mapping or a directive that maps queries and mutations to actions? Like do we want by default to map the name of the query/mutation to the action name directly? For example: graphql query primaryShopId maps to authz action 'primaryShopId`.~

Nevermind I see there's an explicit `action:' annotation parameter

aldeed commented 4 years ago

Here are a smattering of thoughts: