Build a GraphQL Client Application to Consumer Protected GraphQL API Resources Part 1

This article is the first part of a series to explore usage of the Cloudentity authorization platform for externalized GraphQL runtime authorization along with policy based access controls for GraphQL native constructs. Modern applications require runtime and flexible authorization controls to manage the security and risk of data exposed using technologies like GraphQL to various consuming applications or users.

Power of GraphQL

GraphQL is a query language for APIs and a runtime for fulfilling those queries with existing data objects. GraphQL uses a strong type system to define the capabilities of an API where the object types exposed in the API are defined in a schema using the GraphQL Schema Definition Language (SDL). The schema is a contract between client and server defining how a client can access the data. It also defines the data structure that is agreed to be sent/requested over the network, allowing rapid independent development by frontend and backend developers as producers and consumers. GraphQL gives enormous power to clients to request required data over single hops, reducing network latency to drive better user experience using rich and related data elements.

Importance of Data Authorization

As GraphQL gains traction in the developer community, it becomes essential to focus on the data that is getting exposed in the contract via the APIs, along with the governance, authorization and visibility into data access by numerous consuming applications. It is also imperative that the authorization is externalized, centrally managed, and flexible enough at runtime to be moved away from the core business logic itself. Owners of the data that is being shared via GraphQL endpoints should be able to monitor all data requests and apply sufficient authorization controls over requested data in a flexible manner, especially in this era of very fast evolving data sharing specifications across various jurisdictions.

Cloudentity externalized GraphQL authorization

The Cloudentity authorization platform provides a centralized, externalized and flexible way to provide authorization capability for business applications with all the required governance and real time visibility for data access protection for the GraphQL ecosystem.

How Does the Cloudentity Authorization Platform Enables Application Teams

The Cloudentity authorization platform enables Application developers to:

  • Eliminate embedding data authorization into GraphQL business logic
  • Decouple hard-to-audit local enforcement rules and move them to a centralized location
  • Manage, govern, and enforce the externalized authorization rules independently of the application development

It enables applications to:

  • Transitively support advanced data authorization requirements, including role based access control (RBAC) and attribute based access control (ABAC) style models, without any modification to application code
  • Readily comply with data sharing and privacy controls in emerging OpenData standards such as Open Banking, Open Energy, Open Insurance, and more.
  • Define and maintain all the authorization rules to be enforced as policies that allow policy approval, review, and other governance process.
  • Utilize “Authorization as a service” offering either from Cloud or hybrid or on-prem model

The Cloudentity authorization platform enables:

  • Application security engineers to have more visibility to platforms that are requesting data and enforce conditional policies to restrict based on various conditions.
  • Application authorization policies to be defined in a declarative format, which can be propagated across environments using modern CI/CD and DevOps pipelines.

GraphQL vs REST API Authorization

A common question within the developer community is What is the difference between authorizing a GraphQL API vs REST API request? As a typed system, GraphQL facilitates us to introduce tighter and stricter authorization mechanisms across the various GraphQL native constructs. Let’s dive deeper to understand this.

GraphQL and REST both have the idea of a resource and resource identifiers associated with them. GraphQL exchanges data at a single endpoint whereas REST often involves several endpoints to gather data. This itself changes the authorization control paradigm of each request. With GraphQL, a simple API endpoint protection cannot cover all the authorization requirements, so it is essential to have more fine-grained control to authorize the data that is being requested depending on the query or mutation.

In REST, the shape and size of the resource is determined by the server, so a lot of filtering and response manipulation happens at the server-end to evaluate fine grained decisions for data response. In contrast, in GraphQL the server declares what resources are available, and the client asks for what it needs at the time. GraphQL was designed precisely to limit this problem of overfetching. Overfetching brings extra data in each request which is not required by the client, increasing the payload size and eventually degrading the overall response time of the query. Application developers can sometimes expose all data elements without thinking about the data security or sensitivity of the data fields. Since GraphQL recommends a strict schema agreement, the authorization platforms can clearly see the requested data by the client application. The platform can authorize such requests even before it reaches the final endpoint that serves the business logic. Externalized field level GraphQL authorization offered by the Cloudentity platform can enforce data attribute authorization policies in a granular way, even distinguishing attribute release to different calling applications based on conditions defined in the policy.

In REST, the endpoint you call is the identity of that object. In GraphQL, the identity is separate from how you fetch the object. Underfetching is when one endpoint does not have enough data and multiple network calls slow down the process and degrade the user experience. GraphQL design also allows eliminating underfetching by aggregating data and returning all data in single queries. This is efficient for bandwidth but can also easily expose a lot of data without the developers putting in too much thought about the sensitivity of information that is being aggregated and returned. To be honest, application developers should be developing business logic, and authorization should be treated as a cross-cutting concern that is independent of the business logic. Again, the externalized field and object level authorization can be applied to secure your business applications so that they are exposing only authorized data to authorized applications.

The GraphQL system with a typed strict schema agreement provides us an opportunity to govern the data elements efficiently and systematically. The authorization of data exposed by GraphQL queries to each caller application is extremely critical. Cloudentity GraphQL authorization capabilities at object, field, interface, query and mutation level are exactly built to secure the modern GraphQL applications and provide data attribute level authorization, classification, consent management and privacy management protection with ease and isolate it away from the core business rules and logic.

Cloudentity GraphQL Authorization Features

GraphQL Native Support

The Cloudentity authorization concept for GraphQL is tailored around the native constructs of GraphQL and allows authorization at multiple levels around the following building blocks:

Cloudentity native GraphQL support

Declarative Authorization Policies

Cloudentity takes a declarative approach to authorization which allows externalized authorization that can seamlessly fit into modern deployment pipelines to easily adapt to varying data access requirements with fine grained control. The Cloudentity authorization concept extends the usage of GraphQL directives to allow for authorization declaration. The @auth directive is used to annotate the GraphQL query, mutation, fields, interfaces, etc. at schema level to represent the authorization requirement. The @auth directive just needs a simple policy name, and the authorization policy can be authored using REGO, JSON, YAML, or the Cloudentity policy editor and hosted within the Cloudentity authorization platform.

Cloudentity graphQL API explorer

The authorization policy can be authored using data points obtained from:

  • Input HTTP request payload
  • HTTP request body
    • URL
    • Headers
  • Bearer token
    • Key to identify the authorization context
  • Authentication context
    • Identity and authentication context associated to the Bearer token principal
  • External data providers
    • External systems that can be called to fetch more information and utilize in authorization decision process. For example, entitlement engines, risk engines, etc.

Once a policy is authored using the above data elements, it can be attached to any of the GraphQL constructs using the @auth directive in the GraphQL schema.

Modern CI/CD & DevOps Friendly Platform

At Cloudentity, we facilitate modern application authorization and want to make sure our solutions are aligned with an organization’s DevOps practices. We always make sure to enable configuration as code and API first approaches to ease our platform integration into any modern CI/CD operational pipelines for ease of adoption by development, deployment, security, and operations teams.

Authorization policies can be attached to GraphQL constructs using 2 mechanisms:

  • Cloudentity GraphQL API explorer

    Authorization policies are attached via the Cloudentity GraphQL API explorer screen to GraphQL constructs loaded from the GraphQL schema. Once attached, the modified schema with directives can be exported for source control using JSON/YAML formats and propagated to higher environments. The exported file is a decorated GraphQL schema with @auth directives. This allows rapid development, source control, and deployment of verified authorization policies to environments through modern deployment pipelines.

    Cloudentity graphQL API explorer

  • GraphQL Schema Annotation

    Development teams can also consider a bottom-up approach to annotate the schema directly by bypassing the Cloudentity GraphQL API explorer screen. The Cloudentity platform automatically detects such directives within the schema and then displays accordingly in the API explorer.

    Cloudentity graphQL schema annotation

Irrespective of the way the construct is attached, the annotated schema can be exported to allow fine grained policy administration pipelines within the team and across the environments which can include the following:

  • Policy creation
  • Policy updating
  • Policy approval
  • Policy evaluation
  • Policy storage as code
  • Policy deployments using devops pipelines

Externalized Authorization Runtime Enforcement

The Cloudentity authorization platform utilizes open standards and uses the OAuth specification as the basis for authorization and access to resources. Adhering to the OAuth specification, our GraphQL implementation is considered as an OAuth Resource server, that can be protected as such in the Cloudentity authorization platform. Applications (mobile apps, terminal apps, web apps, etc.) acting as OAuth client applications need to first obtain an access token from the Cloudentity authorization server. Cloudentity also supports access tokens from other authorization servers, which Cloudentity internally exchanges for its own access token at the edge level without the application making any change.

The Cloudentity authorization platform securely and automatically distributes the policy rule to all the runtime decision components, regularly referred as policy decision points. Cloudentity offers various enforcers in the form of sidecars, plugins, lambda functions, and more based on deployment platforms to evaluate and aid in enforcing runtime access protection. Cloudentity decision points, also known as Cloudentity authorizers, are available for most of the widely adopted application deployment patterns and can be seamlessly plugged into deployment architectures to enforce authorization decisions.

Cloudentity authorizers overview

Some of the widely used authorizers that can be easily plugged into modern Cloud providers or for on prem workload protections are:

GraphQL Application Protection Demo

We will dive deeper in the next articles into some use cases to get an overview of the Cloudentity authorization concept applied to a GraphQL API subsystem. For illustrative purposes, we will build a tweet service and a frontend application in this series, powered using a GraphQL API server and a client. The main intent is to highlight various authorization decisions points that could be externalized and how the Cloudentity platform enables externalized policy enforcements for a more flexible development journey. Note that the language chosen for development of sample application is just for illustration purposes.

For many in the developer community, the initial thought would be to embed the authorization requirements into the business logic, but this is not beneficial in the long run. Such an approach will “black box” authorization within business logic, making it hard to refactor and has no visibility in terms of enforcement and data access across various calling applications. Our goal is to enable developers to move away from black-boxing authorizations within business logic code, so that the data authorization and access rules are externalized, have more visibility, and can be approved, modified and distributed to various enforcement points without code refactor.

Some of the authorization scenarios we will exploring in further articles are:

  • Automatically block entire access to the APIs at runtime
  • Authorizing data access based on IP address of the request
  • Enforce users having at least assurance level of NIST AAL 1 (Authenticator Assurance Level) to interact with particular GraphQL queries
  • Enforce users having at least assurance level of NIST AAL 2 (Authenticator Assurance Level) to interact with particular GraphQL mutations
  • Enforce specific authorization for specific data fields
  • Enforce authorization for requests with specific types
Updated: Jul 11, 2022