How to Reduce Security Risks in API Architectures: GraphQL Architecture Master Class
We recently read this as the lead-in to an article on API security:
So you’ve built out your GraphQL API, and you’re almost ready to deploy it to production. Time to talk security!
We disagree! As part of our GraphQL Architecture Master Class series > How to Reduce Security Risks in API Architectures, we explored security risks in API architectures and a fundamental premise is to avoid thinking like this. We believe that it's just a bad idea to design your API first and your security as an afterthought. Read on for why we hold that point of view and more.
REST vs. GraphQL API security
You know how to secure REST endpoints. But are you worried about securing GraphQL? GraphQL has an entire graph of capability underneath one endpoint; REST APIs have different endpoints for different capabilities, and developers are familiar with protecting those endpoints using standard things.
- Authentication and authorization are important
- Since calls are over HTTP; worrying about standard HTTP attacks matters
- Things like cross-site scripting are relatively easy to understand and well known
GraphQL is more powerful. It enables you to ask for exactly what you need, and get back tailor made information. Everything that you used to expose under many APIs is now available under a single endpoint. The request URL is always the same - it's what's in the request payload that must be managed. This leads to a belief among some, mistaken, in our view, that GraphQL is inherently less secure.
GraphQL: Security opportunity or a great risk?
Being careless with one endpoint that does everything can be a risk. Hence, being thoughtful from the start and having a mindset that designs your API for security eliminates a bunch of “after-the-fact” work - and, importantly, makes security an intentional design choice rather than an retrofit afterthought.
It used to be that security was done after the API - “Okay, now the API does what I want, so I need to secure it.” Instead, you should design your API and your security schema simultaneously. That is, you can now have a security model that you can reason about across all of your assets consistently instead managing multiple possibly inconsistent fragments which are hard to keep aligned with each other. If you do this well, you can end up with a more maintainable, more reusable, and not surprisingly, a more secure system.
API Security Concerns
API Security is reasonably well-understood and supported by relatively mature products. This should be a cause for comfort, because these work well and tend to be hardened and bug free. Things you should know and understand are:
- Authentication / Authorization (don't confuse the two!)
- Network attacks - what happens if someone gets through the firewall? It's good to have some redundant measures in place.
- OWASP - the organization has been doing great work for a long time, helping us understand the types of attacks we're seeing and how to mitigate those.
As you transition to GraphQL, our best recommendation is not to throw away all the best practices and security considerations you currently use:
- Continue best practices around XSS, input validation, SQL injection, etc.
- Infrastructure: Don't throw away your NGINX proxy, etc.
- Consider API management tools - some are starting to provide GraphQL-specific capabilities.
- Test, Monitor, and Automate!
GraphQL Security
So let's get to specific concerns about GraphQL API security. We'll think about the considerations and our perspective and recommendations in three dimensions:
- Information leakage
- Request complexity
- Authorization
Information Leakage
We think about information leakage a little through the lens of “security through obscurity.” Consider what you want to make easily available to people, and co-design a type system and security policies that reflect your point of view. Everything that you make hard to get at must add more in terms of security than the frictional pain caused. Do not fall into the trap of designing a very secure API that provides no information of value.
What to watch out for
- Introspection - a powerful feature of GraphQL that allows you to query the graph for data and metadata and really navigate and understand an API. This can be of real value to a developer using your API - it could also be useful information for malicious actors who want to take advantage. So be thoughtful about what you expose, but at the same time, don't lock it down wholesale.
- Field suggestions - GraphQL servers will often make field suggestions for you. Handy - but an opportunity for attackers to send in fields - and the field suggestions can reveal things you don’t want to reveal. Again, be thoughtful, but not draconian.
- Error messages - gives you details of an error - much like REST API. You don’t want to reveal backend info about what the error happened, so you need to curate your exception messages carefully.
Recommendations
- Design your schema thoughtfully. Note that when you generate the schema automatically, you’re not finished. So go back in and consider your design for security implications.
- Expose introspection thoughtfully.
- Expose field suggestions thoughtfully.
- Don't simply return errors as-is think about what would be helpful, but not harmful.
- Automate testing
- Ongoing monitoring - continually think about security and use the requests to understand what people might be trying to do!
Request Complexity
With REST APIs, all you can provide are query parameter flags that allow people to change what request returns in controlled ways. Thus, you're typically in a much smaller domain, so it’s a lot easier to understand that you’re not going to let someone try to download a database through your REST API. But because of how you can define the schema in GraphQL and make relationships between types, you can build up a relatively complex request in GraphQL. You can batch requests in a single GraphQL call and nest things deeply.
What to watch out for
- Multiple operations
- Nested queries
- Query complexity - There's complexity in terms of what is happening on the backend - handling N+1 problems, for example.
Recommendations
- Design your schema thoughtfully
- Validate requests
- Configure timeouts, query depth, page size and other limits to make wholesale attacks less profitable.
- Test! Test! Test!
Authorization ++
Authorization consideration goes beyond authorization just for making the request. What’s the nature of that request? Is the user authorized to get all of that?
For example, you might have a large graph connecting customers and orders. Customers may have detailed purchasing records. You may not want everyone to be able to find that information - even if the API is internal to your organization. We have security controls on data for a reason, so it's important to carry those same security controls through to your GraphQL API.
What to watch out for
- Access to the entire graph from one endpoint
- Access to all fields of a type
- Queries and mutations through the same HTTP request
Recommendations
- Do user authentication via JWT for example, not just API keys
- Use attribute-based access control
- Be thoughtful about attaching access requirements for every entry point
- Be thoughtful about attaching access requirements to restrict field access
Demo
Drop into the video around the 37’15” timestamp for a short demo that demonstrates a problem that can arise in an auto-generated schema.
Summary
GraphQL APIs should be carefully designed. And Security considerations are a very important part of the design. If you do this well, you will have a more secure, more useful, more re-usable, and better performing API. It's win, win, win, win. The only way to make this a losing proposition is to think about Security after you have designed your API. Don't fall into that trap.
More from the GraphQL Architecture Master Class
The blogs from the GraphQL Architecture Master Class are:
Subsequent blogs in the series will cover:
-
How to Implement a GraphQL Layer when Data Resides in more than a Database. If you have more than PostgreSQL or any one database backend, this session is for you.
-
Federated Data: How to Massively Simplify your Approach. Current approaches to federated data access are much more complicated than necessary.
-
How to Design GraphQL for a Global Scale. Your applications are global. How to ensure that your infrastructure keeps pace.
And if you want to jump ahead, you can find the videos of each webinar on-demand at the YouTube GraphQL Master Class Playlist
Start For Free | | Request StepZen Demo | | Connect With The Team On Discord