Frequently Asked Questions

Authentication & Authorization in GraphQL

What are the main authentication methods supported in GraphQL APIs?

GraphQL APIs commonly support HTTP authentication, custom authentication (such as OAuth), and JSON Web Token (JWT) authentication. HTTP authentication uses credentials sent with each request, custom authentication allows integration with third-party services for flexibility, and JWT authentication uses signed tokens to verify user identity. Each method has its own implementation and security considerations. Learn more.

How can I implement HTTP authentication in a GraphQL API?

HTTP authentication in GraphQL is typically implemented using the Authorization header, where credentials are sent with each request. While easy to build, it is less secure since credentials are sent in plaintext and can be hard to revoke. Example code and best practices are available in the Hygraph Academy guide. Read the guide.

What is JWT authentication and how does it work in GraphQL?

JWT authentication uses JSON Web Tokens to authenticate requests. When a user logs in, the API generates a JWT containing user claims. The client includes this token in subsequent requests, and the API verifies its validity before granting access. Example Node.js code and implementation details are provided in the Hygraph Academy. See examples.

How is authorization handled in GraphQL APIs?

Authorization in GraphQL is managed by granting access to resources based on user roles and permissions. This can be implemented using directives (such as @auth), role-based authorization, attribute-based authorization, or custom logic in resolvers. Libraries like graphql-shield help define and enforce these rules. Learn more.

What are best practices for securing a GraphQL API?

Recommended best practices include encrypting sensitive data, implementing rate limiting, validating input to prevent injection attacks, keeping the schema simple, and regularly auditing the API for vulnerabilities. Security should be an ongoing process. See best practices.

Security & Compliance

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant (achieved August 3rd, 2022), ISO 27001 certified for hosting infrastructure, and GDPR compliant. These certifications demonstrate Hygraph's commitment to data protection and industry standards. See details.

What security features does Hygraph offer?

Hygraph provides granular permissions, SSO integrations, audit logs, encryption at rest and in transit, regular backups, and enterprise-grade compliance features such as dedicated hosting and custom SLAs. Security issues can be reported and reviewed transparently. Learn more.

Features & Capabilities

What are the key features and benefits of Hygraph?

Hygraph offers a GraphQL-native Headless CMS with features like Smart Edge Cache for fast content delivery, content federation to integrate multiple data sources, rich text formatting, custom roles, project backups, and developer-friendly APIs. It enables operational efficiency, scalability, and improved workflows for global teams. See all features.

How does Hygraph perform in terms of speed and reliability?

Hygraph delivers exceptional performance with Smart Edge Cache for enhanced speed, high-performance endpoints, and measured GraphQL API performance. These features ensure fast, reliable content delivery for high-traffic and global audiences. Read more.

How easy is Hygraph to use for non-technical users?

Hygraph is praised for its intuitive user interface, making it accessible for both technical and non-technical users. Customers report that it's easy to set up and use, even without technical expertise. Hygraph was recognized for "Best Usability" in Summer 2023. Try Hygraph.

Pricing & Plans

What is Hygraph's pricing model?

Hygraph offers a Free Forever Developer Account, self-service plans (e.g., Growth Plan at $299/month or $199/month billed annually), and custom enterprise pricing starting at $900/month. Plans include 1,000 entries, with add-ons for additional entries, locales, API calls, asset traffic, and content stages. See pricing details.

Use Cases & Customer Success

Who can benefit from using Hygraph?

Hygraph is ideal for developers, product managers, and marketing teams in industries such as ecommerce, automotive, technology, food and beverage, manufacturing, transportation, staffing, and science. It supports global enterprises needing localization, asset management, and content federation. See case studies.

What business impact can customers expect from using Hygraph?

Customers can expect improved speed-to-market (e.g., Komax achieved 3x faster launches), enhanced customer engagement (Samsung saw a 15% increase), increased revenue (Stobag grew online share from 15% to 70%), cost efficiency, and scalability. Explore success stories.

Can you share specific case studies or success stories of customers using Hygraph?

Yes. Komax managed 20,000+ product variations across 40+ markets with 3x faster time to market. AutoWeb increased website monetization by 20%. Dr. Oetker adopted MACH architecture for global consistency. Samsung improved engagement by 15%. Stobag increased online revenue share from 15% to 70%. Burrow uses Hygraph for inventory management. See all case studies.

Pain Points & Solutions

What core problems does Hygraph solve?

Hygraph addresses operational inefficiencies (reducing developer dependency, modernizing legacy tech stacks), financial challenges (lowering costs, accelerating launches), and technical issues (simplifying schema evolution, robust integrations, cache and localization management). See solutions in action.

What are some case studies or use cases relevant to each of the pain points Hygraph solves?

Operational: HolidayCheck reduced developer bottlenecks; Dr. Oetker adopted MACH architecture; Si Vale streamlined content creation. Financial: Komax achieved faster launches and lower costs; Samsung scaled globally with reduced maintenance. Technical: Hygraph case studies highlight simplified development and robust integrations. Explore more.

Implementation & Onboarding

How long does it take to implement Hygraph and how easy is it to start?

Implementation time varies by project. For example, Top Villas launched in 2 months; Si Vale met aggressive deadlines. Hygraph offers a free API playground, free developer account, and structured onboarding (introduction call, account provisioning, business/technical/content kickoffs). Training resources and documentation are available. See onboarding details.

What training and technical support is available to help customers get started with Hygraph?

Hygraph provides structured onboarding, webinars, live streams, how-to videos, extensive documentation, 24/7 support via chat/email/phone, Intercom chat, a community Slack channel, and a dedicated Customer Success Manager for enterprise customers. Access resources.

How does Hygraph handle maintenance, upgrades, and troubleshooting?

Hygraph is cloud-based, handling all deployment, updates, and infrastructure maintenance. Upgrades are seamless, and troubleshooting is supported via 24/7 support, Intercom chat, documentation, and a Customer Success Manager for enterprise clients. Learn more.

Competition & Comparison

Why should a customer choose Hygraph over alternatives?

Hygraph offers unique features like Smart Edge Cache, content federation, rich text formatting, custom roles, and project backups. It delivers speed-to-market, lower total cost of ownership, scalability, and proven results (e.g., Komax 3x faster launches, Samsung 15% engagement increase). Hygraph is developer-friendly, secure, and provides dedicated support. See comparisons.

Technical Requirements

What technical requirements are needed to use Hygraph?

Hygraph is a cloud-based, API-first platform accessible via GraphQL endpoints. No specific infrastructure is required; users need internet access and can integrate with their existing tech stack using Hygraph's APIs and SDKs. See technical documentation.

See Hygraph MCP Server, AI Agents, and Editorial Experience Upgrades in Action

GraphQL

Authentication & Authorization

Implementing proper authentication and authorization is one of the most crucial aspects of securing your API. Let's take a look at how you can do it with GraphQL.

With great power comes great responsibility, and ensuring that your GraphQL API is secure is essential.

One of the most crucial aspects of securing your API is implementing proper authentication and authorization.

In this article, we will cover the basics of GraphQL authentication and authorization and provide best practices for securing your GraphQL API.

GraphQL Authentication

Authentication is the process of verifying the identity of a user. In the context of a GraphQL API, this typically involves verifying that the user has a valid token or credentials before allowing access to protected resources.

There are several common authentication methods used in GraphQL APIs, including:

  • HTTP Authentication
  • Custom Authentication
  • JSON Web Tokens (JWT) Authentication

HTTP authentication

For every request made to the API, HTTP authentication sends a username and password as part of the authentication process. After checking the credentials, the API requests the data and returns it if the credentials are genuine. Most GraphQL clients are capable of using this approach, which is reasonably easy to build.

However, HTTP authentication has some limitations. For example, it's not very secure because the credentials are sent with every request in plaintext. It can also be difficult to revoke or update credentials once they've been issued.

In GraphQL, HTTP authentication can be implemented using the Authorization header. The Authorization header is used to send authentication credentials with each request to the API. Here's an example of how to implement HTTP authentication in GraphQL using the Authorization header:

type Query {
me: User! @auth
}
directive @auth on FIELD_DEFINITION
type User {
id: ID!
name: String!
}
type AuthPayload {
token: String!
}
type Mutation {
login(email: String!, password: String!): AuthPayload!
}
schema {
query: Query
mutation: Mutation
}

In this example, we have a Query type with a single field, me, which returns a User object. We've added the @auth directive to the me field to indicate that this field requires authentication.

We've also defined a Mutation type with a login field, which takes an email and password as arguments and returns an AuthPayload object. The AuthPayload object contains a token field, a JWT that can be used for subsequent requests to the API.

The Client must include the Authorization header with the value Bearer <token> to authenticate a request, where <token> is the JWT returned by the login mutation. Let’s use the FetchAPI to include the Authorization header:

fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({ query: '{ me { id name } }' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))

In this code, we're using the fetch API to make a POST request to the GraphQL API. We've included the Authorization header with the value Bearer <token>. The token variable should be set to the JWT returned by the login mutation.

Try Hygraph, the GraphQL native headless CMS

Build limitless solutions rapidly with our GraphQL-native API-first approach

Custom authentication

Custom authentication involves using a third-party authentication service, such as OAuth. It allows for greater flexibility and control over the authentication process. For example, you can implement multi-factor authentication or require users to authenticate using a specific method, such as biometric authentication.

However, custom authentication can be more complex and require additional resources, such as a dedicated authentication server.

Here's an example of how you might implement custom authentication in a GraphQL API using Node.js and the graphql-yoga library:

const { GraphQLServer } = require('graphql-yoga')
// Define a simple schema with a single query
const typeDefs = `
type Query {
hello: String!
}
`
// Define a resolver function for the query
const resolvers = {
Query: {
hello: (_, { name }) => `Hello ${name || 'World'}!`,
},
}
// Define a function to authenticate requests
function authenticate(req) {
// Implement your custom authentication logic here
// For example, you might check if the user is logged in and has the necessary permissions to access the requested data
// If the user is not authenticated, throw an error
if (!req.user) {
throw new Error('You must be logged in to access this resource')
}
}
// Create a new GraphQL server with custom authentication middleware
const server = new GraphQLServer({
typeDefs,
resolvers,
context: (req) => {
// Call the authenticate function to verify that the request is authenticated
authenticate(req)
// Add the authenticated user to the context object, so it can be accessed by the resolver functions
return {
user: req.user,
}
},
})
// Start the server on port 4000
server.start(() => console.log('Server is running on http://localhost:4000'))

In this code, we define a simple GraphQL schema with a single query that returns a greeting. We then define a resolver function for the query that uses the name argument to personalize the greeting.

The custom authenticate function that accepts the req object as a parameter is then defined. This function carries out the unique authentication logic we've developed, including determining whether the user is currently signed in and has the appropriate access rights to the requested data.

We then create a new GraphQL server using the GraphQLServer constructor from the graphql-yoga library. We pass in the schema and resolver functions and a context function that calls the authenticate function to verify that the request is authenticated. We also add the authenticated user to the context object, so the resolver functions can access it. Finally, we start the server on port 4000 using the server.start() method.

JWT authentication

JWT authentication involves using JSON Web Tokens (JWTs) to authenticate requests to the API. JWTs are a type of token containing claims or statements about the user or client making the request. These claims can include information such as the user's ID or role.

When a user or client logs in to the API, the API generates a JWT and returns it to the client. The client then includes the JWT with each subsequent request to the API. The API verifies the JWT and returns the requested data if the JWT is valid.

Here's an example of how to implement JWT authentication in a GraphQL API using Node.js and the [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) library:

const jwt = require('jsonwebtoken');
// Secret key used to sign JWTs
const secretKey = 'mySecretKey';
// Function to generate a JWT
function generateToken(user) {
const token = jwt.sign({ id: user.id }, secretKey, { expiresIn: '1h' });
return token;
}
// Function to verify a JWT
function verifyToken(token) {
try {
const decoded = jwt.verify(token, secretKey);
return decoded;
} catch (err) {
throw new Error('Invalid token');
}
}
// Resolver for a protected query
function protectedQuery(_, args, context) {
// Verify the JWT in the request headers
const token = context.headers.authorization.split(' ')[1];
const decodedToken = verifyToken(token);
// Query the data using the user ID in the JWT
const userId = decodedToken.id;
const data = queryDatabase(userId);
return data;
}
// Resolver for a login mutation
function login(_, args) {
// Verify the user's credentials
const user = verifyUser(args.username, args.password);
// Generate a JWT for the user
const token = generateToken(user);
// Return the JWT to the client
return { token };
}

In this example, we define two functions for generating and verifying JWTs: generateToken() and verifyToken(). The generateToken() function takes a user object as input and returns a JWT signed with a secret key. The verifyToken() function takes a token as input and returns the decoded payload if the token is valid, or throws an error if the token is invalid.

We also define two resolvers: protectedQuery() and login(). The protectedQuery() resolver is used to query protected data that requires authentication. It first verifies the JWT in the request headers using the verifyToken() function, and then queries the data using the user ID in the JWT.

The login() resolver is used to authenticate users and generate a JWT for them. It first verifies the user's credentials using a hypothetical verifyUser() function, then generates a JWT using the generateToken() function and returns it to the client.

To use this example in your own GraphQL API, you would need to modify the resolvers to match your API's schema and data sources. You must also configure the GraphQL server to parse and validate JWTs in the request headers.

GraphQL Authorization

Authentication is the process of verifying a user's identity, while authorization is the process of granting access to resources based on the user's identity and the permissions they have. Once a user is authenticated, we need to ensure they have the necessary permissions to access the requested resources.

GraphQL provides a built-in way to implement authorization through directives. Directives are annotations that can be added to the schema definition to provide additional functionality. In this case, we'll use the @auth directive to restrict access to certain fields or types based on the user's permissions.

Let's look at how we can implement authorization in our GraphQL API.

Role-based authorization

A popular method for restricting access to resources in a GraphQL API is role-based authorisation. Each user is given a role under role-based authorisation, which establishes their level of access to resources.

A user with the role of "admin" might have access to all resources, whereas a user with the role of "guest" might only have access to a portion of the resources.

Here how to use the graphql-shield package to establish role-based authorization in a GraphQL API:

const { rule, shield, and, or, not } = require('graphql-shield');
// Define roles
const ADMIN = 'admin';
const USER = 'user';
const GUEST = 'guest';
// Define rules
const isAuthenticated = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => {
// Check if user is authenticated
return ctx.user !== null;
});
const isAdmin = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => {
// Check if user has admin role
return ctx.user.role === ADMIN;
});
const isUser = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => {
// Check if user has user role
return ctx.user.role === USER;
});
const isGuest = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => {
// Check if user has guest role
return ctx.user.role === GUEST;
});
// Define permissions
const permissions = shield({
Query: {
// Require authentication for all queries
'*': isAuthenticated,
// Allow all users to view public resources
publicResource: isGuest,
// Allow all authenticated users to view protected resources
protectedResource: isUser,
// Allow only admin users to view admin resources
adminResource: isAdmin
},
Mutation: {
// Require authentication for all mutations
'*': isAuthenticated,
// Allow all authenticated users to update their own profile
updateProfile: isUser,
// Allow only admin users to create new users
createUser: isAdmin
}
});
// Export permissions middleware
module.exports = permissions;

In this example, we define three roles: admin, user, and guest. We then define four rules using the rule function from graphql-shield. The isAuthenticated rule checks if the user is authenticated, while the isAdmin, isUser, and isGuest rules check if the user has the corresponding role.

We then define permissions using the shield function from graphql-shield. The permissions object specifies which rules apply to each query and mutation. For example, we require authentication for all queries and mutations, and only allow admin users to create new users.

Finally, we export the permissions middleware, which can be used to protect your GraphQL schema. You can apply the permissions middleware to your schema using a middleware library such as express-graphql.

Attribute-based authorization

Attribute-based authorization (ABA) is a type of authorization mechanism that involves making access decisions based on the attributes of the user or client making the request. In GraphQL, ABA can be used to control access to specific fields or types based on the attributes of the requesting user or client.

Here's an example of how ABA can be implemented in a GraphQL API using the graphql-shield library:

const { rule, shield } = require('graphql-shield')
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => {
return ctx.user !== null
},
)
const isAdmin = rule({ cache: 'contextual' })(
async (parent, args, ctx, info) => {
return ctx.user.role === 'admin'
},
)
const permissions = shield({
Query: {
// Only authenticated users can access the `me` query
me: isAuthenticated,
// Only admin users can access the `users` query
users: isAdmin,
},
Mutation: {
// Only authenticated users can access the `createPost` mutation
createPost: isAuthenticated,
// Only the author of a post can delete it
deletePost: rule({ cache: 'contextual' })(
async (parent, { id }, ctx, info) => {
const post = await getPostById(id)
return post.authorId === ctx.user.id
},
),
},
})

In this example, we're using graphql-shield to define rules that control access to specific queries and mutations in the GraphQL schema. We have two rules defined: isAuthenticated and isAdmin.

The isAuthenticated rule checks whether the user making the request is authenticated. If the user is authenticated, the rule returns true. Otherwise, it returns false. The isAdmin rule checks whether the user making the request has the admin role. If the user has the admin role, the rule returns true. Otherwise, it returns false.

We then use these rules to define the permissions for each query and mutation in the schema. For example, we use the isAuthenticated rule to restrict access to the query and the createPost mutation. We're using the isAdmin rule to restrict access to the users query. We're also using a custom rule to restrict access to the deletePost mutation. This rule checks whether the user making the request is the author of the post being deleted.

Custom authorization

Custom authorization in GraphQL involves implementing custom logic to determine whether a user or client can access a specific resource or perform a specific action. This can involve checking the user's role or permissions, validating input data, or implementing rate limiting to prevent abuse.

Here's an example of how custom authorization can be implemented in a GraphQL resolver:

const resolvers = {
Query: {
mySensitiveData: async (_, __, { user }) => {
if (!user || user.role !== 'admin') {
throw new Error('Unauthorized');
}
// Fetch and return sensitive data
const sensitiveData = await fetchSensitiveData();
return sensitiveData;
},
},
};

In this code, the resolver for the mySensitiveData field checks whether the user is authenticated and has the 'admin' role. If the user is not authenticated or doesn't have the correct role, the resolver throws an error indicating that the user is unauthorized.

Custom authorization can be implemented in a variety of ways, depending on the specific needs of your GraphQL API. For example, you might implement custom logic to check whether a user has permission to update a resource, or to limit the rate at which certain requests can be made.

You can check out this documentation on how to implement authorizations with Hygraph.

Best Practices for Securing a GraphQL API

There are various recommended practices you can adhere to so as to make sure your GraphQL API is secure, in addition to putting authentication and permission systems in place:

  • Encrypt sensitive data: Use encryption to protect sensitive data in transit and at rest.
  • Implement rate limiting: Limit the number of requests that can be made to the API in a given period to prevent abuse.
  • Validate input: Validate input to prevent injection attacks and other security vulnerabilities.
  • Keep the GraphQL schema simple: Limit introspection and expose what is necessary to clients.
  • Regularly audit the API: Perform security audits to identify and address vulnerabilities promptly.

Conclusion

Security is a continuous process; thus, it's crucial to routinely check your GraphQL API for potential flaws and patch them as soon as you find them.

In conclusion, building robust authentication and authorization mechanisms and adhering to security best practices are needed to secure a GraphQL API.

Now that you have a solid understanding of GraphQL authentication and authorization, you can apply these principles to your own API to ensure it's secure and protected.