ory / oathkeeper

A cloud native Identity & Access Proxy / API (IAP) and Access Control Decision API that authenticates, authorizes, and mutates incoming HTTP(s) requests. Inspired by the BeyondCorp / Zero Trust white paper. Written in Go.
https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=hydra
Apache License 2.0
3.23k stars 355 forks source link

Add GraphQL support #470

Open christian-roggia opened 4 years ago

christian-roggia commented 4 years ago

This ticket has been created with the intent to collect consensus and feedback from the community for future GraphQL integration and support.

If you would like to see GraphQL natively integrated with oathkeeper please add a :+1: or a :heart: to this post rather than writing "+1" in the comments.

If you want to contribute with your personal input and use-case regarding GraphQL please do so in this ticket.

aeneasr commented 4 years ago

I'd be interested to hear ideas how we could implement this:

  1. Filtering based on the GraphQL methods
  2. Filtering based on GraphQL arguments

Both in terms of the access rule semantics as well as the actual code base given that we don't actually know the GraphQL schema, implying that all of this needs to be more or less as generic as possible!

christian-roggia commented 3 years ago

Animeshon RFC for Oathkeeper Integration with GraphQL

This is an early stage RFC proposal for an integration of oathkeeper with GraphQL. A Proof-of-Concept of this RFC is being developed at Animeshon under the project name "graphql-proxy" and will likely be open-sourced once it is ready for an early alpha and custom business logic has been decoupled from the main repository.

In the current state, oathkeeper is not able to perform any useful operation when a GraphQL request is intercepted.

Lets first analyze why this is the case:

Due to the reasons explained above, you are currently limited in the following core operations:

Taking the example from Oathkeeper and Istio

In the past year, we at Animeshon had to deal very frequently with both Istio and Oathkeeper as the two services are the most important components in routing and dispatching requests to the right service, authenticated, authorized, and hydrated. This is the main reason why we took the request flow example from these two technologies to design a proxy for our GraphQL Gateway service (we use Apollo Federation internally).

The current request flow looks very often like the following diagram:

GraphQL Proxy - Current Status

Requests get through a load balancer, which forwards them to a reverse-proxy (e.g. oathkeeper-proxy, Ambassador, Istio, ...) which in turn will authenticate and authorize (hydrate, mutate, etc.) the requests through Hydra, Kratos, etc. This flow does not work with GraphQL as previously mentioned.

The Proof-of-Concept that we are implementing is an additional component that is placed in front of the GraphQL Gateway or Server and intercepts all the requests awaiting authorization (it is designed to work in the same manner as a sidecar):

GraphQL Proxy - Proof-of-Concept

The final RFC should (hopefully) look similar to the following diagram:

GraphQL Proxy - RFC

That is - GraphQL requests are natively managed by oathkeeper with a logic similar to the one implemented in the PoC. We believe this is a very important feature as the GraphQL community is growing fast and many companies use it as an alternative to REST APIs.


Analyzing GraphQL requests

What is left to be discussed is how to actually implement Authentication and Authorization, and more specifically how to translate the path and methods from REST APIs to the GraphQL logic.

The following request is a very basic GraphQL request:

mutation {
  updateLibrary(input: {name: "Test", id: "47b3f42a-65c2-46b1-93d5-47ff4e92cf5b"}) {
    id
  }
}

Analyzing the request the following information might be relevant to oathkeeper:

The best way to extract this information is to parse the request with a GraphQL parser, we use https://github.com/graphql-go/graphql/blob/master/language/parser/parser.go for this purpose. The output is an Abstract Syntax Tree which is surprisingly easy to use.

Through the AST the information mentioned above can easily be extracted to generate a meaningful context for oathkeeper.

Once this information is known it can be used according to the requirements of the client, and rules might look similar to the following structure:

- id: "graphql:libaries:update"
  match:
    name: "updateLibrary"
    operations: [ mutation ]
  authorizer:
  - handler: remote_json
    config:
      remote: http://keto-api.keto:4456/engines/acp/ory/exact/allowed
      payload: |
        {
          "subject": "identities:{ print .Subject }",
          "action": "library.set",
          "resource": "libraries:{ print .Arguments.input.id }"
        }

This implementation should be enough to cover the most common use-cases and through Go-Templates / Jsonnet the rules should be flexible enough to also allow for complex scenarios. This implementation is also completely schema-agnostic and authorizes requests based on the information provided by the rules.


While this example covers only Authorization, once the AST is in place it should be easy to also mutate or hydrate the requests in the same manner as REST APIs. As an example, new arguments can be injected into the requests in transit to hydrate the request with more information such as metadata, user identity information, and more.

This is an early draft for potential future implementation, any feedback is as always more than welcome.

aeneasr commented 3 years ago

@christian-roggia thank you for the super detailed post! I just wanted to post this as an acknowledgement - I will try to get to this ASAP, probably tomorrow!

aeneasr commented 3 years ago

Nice, this sounds great! I wasn't aware that there is an AST parser for GraphQL but given that there is, your approach seems very sensible, very sensible! We are currently at full capacity unfortunately so we'll not be able to spend time on this at the moment. However, if you plan on contributing this, I'd be more than happy to help!

christian-roggia commented 3 years ago

We are still evaluating some details regarding the RFC for the PoC, I will get you a new proposal once it is finalized on our side :+1:

aeneasr commented 3 years ago

Awesome, looking forward to it!!

wraix commented 3 years ago

I would be interested in this. Is there any code anywhere to play around with?

christian-roggia commented 3 years ago

The project was momentarily put on hold while keto "new generation" was being developed.

The development of this authorization flow will resume on our side in the next months.

github-actions[bot] commented 2 years ago

Hello contributors!

I am marking this issue as stale as it has not received any engagement from the community or maintainers a year. That does not imply that the issue has no merit! If you feel strongly about this issue

Throughout its lifetime, Ory has received over 10.000 issues and PRs. To sustain that growth, we need to prioritize and focus on issues that are important to the community. A good indication of importance, and thus priority, is activity on a topic.

Unfortunately, burnout has become a topic of concern amongst open-source projects.

It can lead to severe personal and health issues as well as opening catastrophic attack vectors.

The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone.

If this issue was marked as stale erroneous you can exempt it by adding the backlog label, assigning someone, or setting a milestone for it.

Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you!

Thank you šŸ™āœŒļø

gitn00b1337 commented 2 years ago

@aeneasr hi, is this completed or being left for now?

If the latter, @christian-roggia do you have any code from the previous POC you could share?

aeneasr commented 2 years ago

Closed in error

amirzahavi commented 1 year ago

@aeneasr / @christian-roggia is this issue still being considered?

aeneasr commented 1 year ago

Sure, but it's not on Ory's roadmap right now as we focus on other priorities.

arnemolland commented 1 year ago

Hey, @christian-roggia!

We're interested in picking this up @gameflow-tv, would you mind sharing some of the progress you made?

github-actions[bot] commented 1 week ago

Hello contributors!

I am marking this issue as stale as it has not received any engagement from the community or maintainers for a year. That does not imply that the issue has no merit! If you feel strongly about this issue

Throughout its lifetime, Ory has received over 10.000 issues and PRs. To sustain that growth, we need to prioritize and focus on issues that are important to the community. A good indication of importance, and thus priority, is activity on a topic.

Unfortunately, burnout has become a topic of concern amongst open-source projects.

It can lead to severe personal and health issues as well as opening catastrophic attack vectors.

The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone.

If this issue was marked as stale erroneously you can exempt it by adding the backlog label, assigning someone, or setting a milestone for it.

Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you!

Thank you šŸ™āœŒļø

murray484 commented 1 week ago

Iā€™m still very interested in this feature!