Odyssey

Authentication & Authorization

IntroductionAuthentication: Identifying usersAuthorization: Checking permissionsAuth in GraphOS Studio
4. Auth in GraphOS Studio
2m

Overview

Now that we've seen how Airlock handles both authentication and authorization, we can take a step back and check that everything is working.

In this lesson, we will:

  • Use GraphOS Studio to add headers to a GraphQL query and test our auth setup.

Testing a query in GraphOS Studio

Let's start by opening http://localhost:4000 in GraphOS Studio Sandbox.

We'll try out a query that requires an authenticated and authorized user: retrieving a host's listings. This query needs you to be logged in as a host.

Using Explorer, let's build a query to retrieve a host's listings. For each listing, we'll ask for the title, costPerNight, description, photoThumbnail, numOfBeds, and locationType.

Here's the complete query:

query GetHostListings {
hostListings {
title
costPerNight
description
photoThumbnail
numOfBeds
locationType
}
}

Let's run the operation, and... uh oh! We get back an AuthenticationError with no logged-in user 😱

{
"errors": [
{
"message": "*** you must be logged in ***",
"extensions": {
"code": "UNAUTHENTICATED",
"serviceName": "monolith",
"exception": {
"stacktrace": "AuthenticationError: *** you must be logged in ***" // plus a long stack trace with files and line numbers goes here",
"message": "*** you must be logged in ***",
"locations": [
{
"line": 1,
"column": 2
}
],
"path": ["hostListings"]
}
}
}
],
"data": null
}

After a brief moment of panic, let's think about what we're missing.

We've just set up the server-side handling of Authorization headers, but we haven't actually sent those headers with our request! So our server is trying to authenticate the user sending the request, but it can't find their user token, and it returns the appropriate error.

Adding headers in GraphOS Studio

Let's go ahead and add those missing headers.

  1. In the bottom panel of the Explorer, open the Headers tab.

  2. Click the New header button. Set the header key as Authorization, and set the value as Bearer user-1. (We know that user-1 is a host!)

A screenshot of the GraphOS Studio Explorer. In the Headers tab at the bottom of the screen, there's a header called 'Authorization' with a value of 'Bearer user-1'.
Authorization: Bearer user-1

Let's run the query again! Now that we have the correct header, we get the data we're asking for with all the fields we need.

{
"data": {
"hostListings": [
{
"title": "Cave campsite in snowy MoundiiX",
"costPerNight": 120,
"description": "Enjoy this amazing cave campsite in snow MoundiiX, where you'll be one with the nature and wildlife in this wintery planet. All space survival amenities are available. We have complementary dehydrated wine upon your arrival. Check in between 34:00 and 72:00. The nearest village is 3AU away, so please plan accordingly. Recommended for extreme outdoor adventurers.",
"photoThumbnail": "https://res.cloudinary.com/apollographql/image/upload/v1644350721/odyssey/federation-course2/illustrations/listings-01.png",
"numOfBeds": 2,
"locationType": "CAMPSITE"
},
{
"title": "Cozy yurt in Mraza",
"costPerNight": 592,
"description": "Thiz cozy yurt has an aerodyne hull and efficient sublight engines. It is equipped with an advanced sensor system and defensive force shield. Meteor showers are quite common, please rest assured that our Kevlar-level shields will keep you safe from any space debris. Mraza suns are known to have high levels of UV hyper radiation, which we counteract with the yurt's UV protection shield.",
"photoThumbnail": "https://res.cloudinary.com/apollographql/image/upload/v1644350839/odyssey/federation-course2/illustrations/listings-02.png",
"numOfBeds": 1,
"locationType": "ROOM"
},
]
}
}

For fun, let's check what happens if we ask for the exact same fields, but as a guest, like user-2. Change the value of the Authorization header to "Bearer user-2", then run the query.

{
"errors": [
{
"message": "Only hosts have access to listings.",
"extensions": {
"code": "FORBIDDEN",
"serviceName": "monolith",
"exception": {
"stacktrace": [
"ForbiddenError: Only hosts have access to listings." // plus a long stack trace with files and line numbers goes here",
],
"message": "Only hosts have access to listings.",
"locations": [
{
"line": 1,
"column": 2
}
],
"path": ["hostListings"]
}
}
}
],
"data": null
}

We get a ForbiddenError that says only hosts have access to listings. But we're logged in as a guest, so that's great! Our server is working as it's supposed to.

Task!

Key takeaways

  • You can add headers to requests in GraphOS Studio Explorer via the Headers tab.

Conclusion

And with that, we've seen our first example of implementing auth on a GraphQL server! We learned how to use HTTP headers to authenticate users, how to write field-level authorization in a GraphQL resolver, and how to add headers to a request in GraphOS Studio.

If you're interested in digging deeper into auth topics, check out the list of additional resources below.

As for what's next, you can check out the Intermediate Schema Design side quest, or dive into the Voyage series to learn how to modularize your graph using Apollo Federation.

Additional resources

  • Apollo Server docs: Authentication and authorization
  • Apollo Client docs: Authentication
  • Apollo GraphQL YouTube: How to Auth: Secure a GraphQL API with Confidence
Previous
              GraphOS Studio

              The web interface for GraphOS, which provides graph, variant, and organization management, metrics visualization, schema pipeline tools and more.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              GraphOS Studio Explorer

              A powerful web IDE for creating, running, and managing GraphQL operations. It's also available in a Sandbox mode that doesn't require an Apollo account.

              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              field

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              resolver

              A function that populates data for a particular field in a GraphQL schema. For example:

              const resolvers = {
              Query: {
              author(root, args, context, info) {
              return find(authors, { id: args.id });
              },
              },
              };
              GraphOS Studio

              The web interface for GraphOS, which provides graph, variant, and organization management, metrics visualization, schema pipeline tools and more.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              Apollo Federation

              Apollo’s implementation of GraphQL Federation—an architecture for orchestrating multiple APIs into a single GraphQL API.

              NEW COURSE ALERT

              Introducing Apollo Connectors

              Connectors are the new and easy way to get started with GraphQL, using existing REST APIs.

              Say goodbye to GraphQL servers and resolvers—now, everything happens in the schema!

              Take the course