Authentication, Authorization &
Error Handling with GraphQL
Nikolas Burk 👋
Developer at Graphcool
$ whoami
@nikolasburk
1. GraphQL Introduction
2. Authentication, Authorization &
Error Handling in GraphQL
3. Demo & Practical Examples
Agenda
@nikolasburk
GraphQL Introduction
@nikolasburk
What’s GraphQL?
• new API standard
• developed & open-sourced by Facebook
• declarative way of fetching & updating data
@nikolasburk
Schema
… defines the data model
@nikolasburk
type Link {
url: String!
description: String
postedBy: User!
}
type User {
name: String!
isAdmin: Boolean!
links: [Link!]!
}
Queries
… only read data
Link(id: “1”) {
url
postedBy {
name
}
}
{
“data”: {
“Link”: {
“url”: “https://graph.cool”,
“postedBy”: {
“name”: “Sarah”
}
}
}
}
@nikolasburk
Queries
… only read data
@nikolasburk
Link(id: “1”) {
url
postedBy {
name
}
}
{
“data”: {
“Link”: {
“url”: “https://graph.cool”,
“postedBy”: {
“name”: “Sarah”
}
}
}
}
Mutations
… write and read data
mutation {
createLink(url: “https://graph.cool”) {
id
}
}
{
“data”: {
“createLink”: {
“id”: “3”,
}
}
}
@nikolasburk
Mutations
… write and read data
mutation {
createLink(url: “https://graph.cool”) {
id
}
}
{
“data”: {
“createLink”: {
“id”: “3”,
}
}
}
@nikolasburk
How does it work?
Authentication, Authorization
& Error Handling in GraphQL
@nikolasburk
Authentication vs Authorization
@nikolasburk
• Authentication: Verifying a user’s identity
• Authorization: Specifying data access permissions
Error Handling with REST
@nikolasburk
• permissions are handled in API / business
logic layer or middleware
• no standardized approach
• HTTP status codes
• permissions expressed in terms of actions
Challenges with GraphQL
@nikolasburk
• fine-grained data access
• transport-layer agnostic - no status codes
• multiple queries in single request are possible
Error Handling with GraphQL
@nikolasburk
…described in official
GraphQL specification
Returning errors
@nikolasburk
{
"data": null,
"errors": [
...
]
}
Anatomy of an error
@nikolasburk
• message: information for the developer
• locations?: where in query or mutation (line+column)
• path?: which field in the query caused the issue
• custom information
Example: Required field not provided
@nikolasburk
mutation {
createLink(url: “https://graph.cool”) {
id
}
}
mutation {
createLink() {
id
}
}
Example: Required field not provided
@nikolasburk
required url argument is missing ❌
{
"data": null,
"errors": [
{
"message": "Field 'createLink' argument 'url' of type 'String!' is required but not provided.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [ "createLink" ]
}
]
}
Example: Required field not provided
@nikolasburk
required url argument is missing ❌
@nikolasburk
Link(id: “1”) {
id
description
}
Example: Not authorized for specific field (1/2)
@nikolasburk
Link(id: “1”) {
id
description # not authorized
}
Example: Not authorized for specific field (1/2)
@nikolasburk
{
"data": {
"Link": {
"id": "1",
"description": null
}
},
"errors": [
{
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [ "Link", "description" ],
"message": "Insufficient Permissions",
}
]
}
Example: Not authorized for specific field (1/2)
@nikolasburk
{
"data": {
"Link": {
"id": "1",
"description": null
}
},
"errors": [
{
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [ "Link", "description" ],
"message": "Insufficient Permissions",
}
]
}
Example: Not authorized for specific field (1/2)
@nikolasburk
{
"data": {
"Link": {
"id": "1",
"description": null
}
},
"errors": [
{
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [ "Link", "description" ],
"message": "Insufficient Permissions",
}
]
}
Example: Not authorized for specific field (1/2)
…but
@nikolasburk
… this only works for non-required fields like description.
type Link {
url: String!
description: String
postedBy: User!
}
@nikolasburk
Link(id: “1”) {
id
url
}
Example: Not authorized for specific field (2/2)
@nikolasburk
Link(id: “1”) {
id
url # not authorized
}
Example: Not authorized for specific field (2/2)
@nikolasburk
Example: Not authorized for specific field (2/2)
{
"data": {
"Link": null
},
"errors": [
{
"locations": [
{
"line": 4,
"column": 5
}
],
"path": [ "Link", "url" ],
"message": "Insufficient Permissions"
}
]
}
…so
@nikolasburk
… with required fields the error bubbles up.
Authorization with GraphQL:
Permission Queries
@nikolasburk
• new and powerful approach to access control
• based on familiar GraphQL queries
• express permission rules by accessing the entire
data graph and object relations
Permissions with Graphcool
@nikolasburk
Demo
&
Practical Examples
@nikolasburk
Example Schema
@nikolasburk
type Link {
url: String!
description: String
comments: [Comment!]! @relation(name: "CommentsOnLink")
postedBy: User! @relation(name: "UsersLinks")
}
type User {
name: String!
isAdmin: Boolean!
links: [Link!]! @relation(name: "UsersLinks")
comments: [Comment!]! @relation(name: "UsersComments")
}
type Comment {
text: String!
link: Link! @relation(name: "CommentsOnLink")
writtenBy: User! @relation(name: "UsersComments")
}
4 Requirements
@nikolasburk
READ: Only authenticated user can read links
CREATE: Only a user who wrote at least one comment
that contains “GraphQL” can create new links
UPDATE: Only a user who created a link can update it
DELETE: Only a user who created a link can delete it
OR the user is an admin
READ: Only authenticated user
can read links
@nikolasburk
CREATE: Only a user who wrote at least one
comment that contains “GraphQL” can
create new links
@nikolasburk
query ($user_id: ID!) {
SomeUserExists(
filter: {
id: $user_id,
comments_some: {
text_contains: "GraphQL"
}
}
)
}
UPDATE: Only a user who created a link
can update it
@nikolasburk
query ($node_id: ID!, $user_id: ID!) {
SomeLinkExists(
filter: {
id: $node_id,
postedBy: {
id: $user_id
}
}
)
}
DELETE: Only a user who created a link
can delete it OR the user is an admin
@nikolasburk
query ($node_id: ID!, $user_id: ID!) {
SomeUserExists(
filter: {
id: $user_id,
OR: [{
isAdmin:true
}, {
links_some: {
id: $node_id
}
}]
}
)
}
Resources 📚
@nikolasburk
• Reinventing Authorization: GraphQL Permission Queries (Article)
https://www.graph.cool/blog/2017-04-25-graphql-permission-queries-oolooch8oh/
• Error-Handling in GraphQL (Specification)
https://facebook.github.io/graphql/#sec-Errors
• Authorization in GraphQL (Discussion)
https://www.graph.cool/blog/2017-04-25-graphql-permission-queries-oolooch8oh/
• Authentication and Error Handling in GraphQL (Video)
https://www.youtube.com/watch?v=xaorvBjCE7A&t=223s
Community 🙌
• slack.graph.cool (> 2500 members)
• GraphQL Weekly Newsletter
• GraphQL Radio Podcast
@nikolasburk
We’re hiring!
www.graph.cool/jobs
@nikolasburk
Thank you! 🙇
… any questions?
@nikolasburk

Authentication, Authorization & Error Handling with GraphQL