Serverless Security
GraphQL vs gRPC: Which One Creates More Secure APIs?
Learn about the security capabilities of GraphQL and gRPC, how they perform authentication/authorization, and how they compare to REST. In addition, discover common attack vectors for both API frameworks and how to prevent them.
An application programming interface (API), the intermediary that allows applications to communicate with each other, has become a standard component in the development process. As there are several frameworks that can be used to build APIs, GraphQL and gRPC have emerged as the two most prevalent solutions.
GraphQL
Developed in 2012 by Facebook and publicly released in 2015, this data query language for APIs acts as a runtime to complete those queries of your data. It was designed to rapidly return precisely what the user requests—and nothing more. GraphQL is popular for being developer-friendly and can be easily deployed within an IDE as “GraphiQL”.
gRPC
Established in 2015 and released the next year, developers Google initially used this open-source remote procedure call framework to connect their internal infrastructure. However, well-established organizations like Netflix, CISCO, and Square, now rely on this language to connect backend services to end-users with devices like mobile apps.
As alternatives to the nearly ubiquitous representational state transfer (REST) framework, GraphQL and gRPC both provide enhanced capabilities over older frameworks, handling thousands of requests easily due to their batching and scaling capabilities. But with these new, more efficient methods of building APIs comes a level of cyber risk.
This article compares the security capabilities of GraphQL and gRPC. You’ll obtain expert insight into how each performs authentication and authorization while exploring both solutions' common attack vectors and potential vulnerabilities. You’ll also obtain suggestions for mitigating risks, helping you determine which solution provides the most robust security.
GraphQL vs. gRPC: which is more secure?
This can be determined by comparing the authentication and authorization capabilities, along with the implementation process for both GraphQL and gRPC. Comparing both methods to REST can also help highlight the added benefits and functionality of each solution.
Performing authentication and authorization
Authentication involves answering two questions:
- Who is trying to access the system?
- Can they authenticate their identity?
The former can be answered by distinguishing user identifiers, such as email address or username. The latter generally requires a password associated with the identifier in question.
Building on authentication, authorization determines the level of access that a validated user will then receive.
GraphQL performs authentication and authorization, whereas gRPC supports several external authorization tools but only performs authentication natively.
Authentication with GraphQL
To understand how GraphQL undertakes authentication, the image below shows how a request flows and the three points where we can perform it:
Every request goes through the HTTP server to the GraphQL server, which builds context and runs the resolver. However, the business logic should remain separate from the resolvers, as it often changes. In such a situation, the separation allows you to implement the changes with just a few lines of code.
There are three points where authentication is implemented in GraphQL:
- Before the HTTP server: The first point where authentication can be reached is directly before a network request reaches the HTTP server. Authentication performed here protects the GraphQL endpoints. Note that authenticating here makes it impossible to connect data from HTTP requests to the GraphQL server, which prevents you from getting access to the logged user.
- Before the GraphQL server: Another point where authentication can be performed is between the HTTP server and the GraphQL server using the GraphQL context. This requires three steps.
- Implement a custom context building function.
- Access the network request and add the context object.
- Add CurrentUser to that context object.
- In business logic: Authentication can also be part of the business logic code. However, implementing authentication at this stage is not recommended, as it exposes too much information to your application.
Authentication in GraphQL differs from that of REST APIs, as the latter performs authentication of requests using API keys or HTTP authentication schemes. These two simple authentication strategies require the credentials to be attached to the request header.
An example of authentication implemented between the HTTP server and the GraphQL server illuminates this difference:
const HEADER_NAME = 'authorization'
const typeDefs = gql`
type Query {
me: User
}
type User {
id: ID!
username: String!
}
`
const server = new ApolloServer({
typeDefs,
context: async ({ req }) => {
let authToken = null
let currentUser = null
try {
authToken = req.headers[HEADER_NAME]
if (authToken) {
currentUser = await tradeTokenForUser(authToken)
}
} catch (e) {
console.warn(`Unable to authenticate using auth token: ${authToken}`)
}
return {
authToken,
currentUser
}
}
})
Authorization with GraphQL
In addition to authentication, GraphQL performs authorization to help determine the level of access a verified user can have.
In GraphQL, authorization is more complex than in REST because it changes how servers and clients interact. In REST APIs, the endpoints and responses are statically defined by the servers. As REST allows for the authorization of individual endpoints, GraphQL, permits clients to submit arbitrary requests to the server, while each mutation and query must be authorized.
The goal of GraphQL should be to build authorization logic as close to the data as possible within the GraphQL API.
This example demonstrates the logic in which only a user can see their password:
var postRepository = require('postRepository');
var postType = new GraphQLObjectType({
name: ‘Password’,
fields: {
body: {
type: GraphQLString,
resolve: (password, args, context, { rootValue }) => {
return postRepository.getBody(context.user, password);
}
}
}
});
Authentication with gRPC
This design supports several authentication mechanisms as well as a simple authentication API, this includes:
- SSL/TLS. Can be used to authenticate the server and encrypt client-server communication.
- ALTS. Supported as a transport security mechanism.
- Goggle’s token-based authentication. Attaches metadata-based credentials to responses and requests.
Unlike gRPC, a REST API doesn’t support sophisticated mechanisms. Instead, it uses simpler authentication strategies that involve attaching credentials, such as API keys, access tokens, or using a username and password for a request.
Additionally, unlike GraphQL, which authenticates each request for data, gRPC creates a contract between a server and a client for fast transport. This enables it to easily handle thousands of requests without compromising its security. Unlike gRPC, GraphQL provides multiple options for where to implement authentication.
Here’s an example of a client-side SSL/TLS gRPC authentication example:
// SSL ChannelCredentials object creation.
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
// Channel creation.
auto channel = grpc::CreateChannel(server_name, channel_creds);
// Creating a stub on the channel.
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Making RPC calls on the stub.
grpc::Status s = stub->sayHello(&context, *request, response);
Authorization with gRPC
The gRPC doesn’t have a built-in authorization mechanism but supports the use of external solutions such as a JSON Web Token (JWT) and an Envoy Proxy.
Authorization with JWT uses gRPC interceptors acting like a middleware function on the client and server sides. A JWT token attached to each request determines what that request is permitted to access.
Unlike gRPC, REST API authentication is only performed on the server-side when a request is made. In gRPC, the server and the client participate in the authorization process via gRPC interceptors.
Vulnerabilities and common attack vectors
Although thorough authentication and authorization practices are useful for maintaining security, both GraphQL and gRPC are susceptible to vulnerabilities. Exploring the more common attack vectors for each API framework and some best practices that can be implemented plays a role in mitigating cyber risk.
GraphQLThis framework includes two primary attack vectors:
gRPCThere soluition includes three primary attack vectors:
Conclusion
GraphQL supports request batching, and gRPC supports the creation of channels that can process thousands of requests. REST, in contrast, handles one request at a time, making it too slow for applications that make many requests simultaneously.
GraphQL reduces duplication and gives lean responses without any unnecessary data. It’s the best solution in cases where a number of requests need to be made from different sources to render a view on a client’s application. gRPC is most effective when building a highly scalable distributed system and very effective when building a backend with hundreds or thousands of interconnected microservices.
gRPC's authentication levels and limited frontend exposure makes it more secure than GraphQL. But while GraphQL's susceptibility to common attacks—such as injection and brute force attacks—make it less safe, there are several proactive steps to mitigate vulnerabilities in GraphQL.
GraphQL and gRPC both provide ways to secure their APIs and build faster and more secure APIs when compared to REST. It’s important to remember that your team doesn’t need to commit to a single API technology, and that both GraphQL and gRPC can be used interchangably based on your team’s requirements and based on each solution’s benefits and functionalities.
It continues to become easier to make applications for the web, and businesses are using them at ever-increasing rates. Unfortunately, not everyone—including developers and those who must defend their systems—knows how to secure them properly. With the interconnection of most web applications and IT systems, this lack of knowledge exposes enterprises to security risks from hackers who know how to exploit vulnerabilities in order to gain access to systems, software, and sensitive data.
Trend Micro Cloud One™ – Application Security is built for speedy deployment, with minimal impact on development streams and performance. It only takes a minute to add the library to your application, and there is no need to change your development code. Application Security bootstraps itself into your application at runtime, as opposed to an SDK that has to be integrated into the application. Learn more about how Application Security minimizes design and deployment risks by protecting against sophisticated hacks from inside the application.