GraphQL returns a "success" response when invalid credentials are provided
Summary
Our GraphQL API treats authentication issue the same way as authorization issue. That means when we provide incorrect credentials, instead of getting 401
error, the request is treated as if the credentials weren't provided at all.
In our GraphQL API documentation, we reference REST API documentation which says:
If authentication information is invalid or omitted, an error message will be returned with status code 401
And that is not happening.
Steps to reproduce
- Run
curl 'https://gitlab.com/api/graphql' --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/json" --request POST --data "{\"query\": \"query {currentUser {name}}\"}"
with an invalid token - observe
{"data":{"currentUser":null}}
as a response
What is the current bug behavior?
The GraphQL API returns null
resources. There is no distinction between the following three states:
- authentication failed (wrong credentials)
- authorization failed (user doesn't have access to the resource)
- resource doesn't exist
This becomes a critical issue when part of the project is public. Instead of telling user that they provided incorrect credentials (401
error), we return only the publicly available data. This makes "missing data" issue hard to spot and debug.
Example
The following query with an invalid token:
{
project(fullPath: "gitlab-org/gitter/webapp"){
snippets {
nodes {
title
}
}
},
}
curl 'https://gitlab.com/api/graphql' --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/json" --request POST --data-raw '{"query":"{ project(fullPath: \"gitlab-org/gitter/webapp\"){ snippets { nodes { title } } },}","variables":null,"operationName":null}' | jq
returns
{
"data": {
"project": {
"snippets": {
"nodes": [
{
"title": "Gitter weekly stats script"
},
{
"title": "Mongo query: Most populous active communites in date range"
},
{
"title": "Mongo query: Most active communites in date range"
},
{
"title": "generate-mongo-id-time-range"
},
{
"title": "find-sockets-in-multiple-rooms.lua"
}
]
}
}
}
}
Making the user believe everything went OK, but missing several snippets that are private.
What is the expected correct behavior?
The correct behaviour is the same as for our REST API, when we call
curl "https://gitlab.com/api/v4/user?access_token=$TOKEN"
with an invalid token, we should get 401
error back.