hasura / hasura/graphql-engine

Missing cookies between Hasura and auth hook?

Open
#3,855 5 comments 4 reactions 0 assignees View on GitHub
k/question
Dominant language
TypeScript
Stars
32.1k
Forks
3k
PR merge metrics
PR metrics pending

Description

I am currently struggling with authentication hook. I have some HTTP-only cookies containing my access token. As Hasura doesn't support token from cookies, but only `Authorization` header, I planned to set up an hook to read cookies and return data required by Hasura (user ID and role).

Testing my auth hook independently works:

``` sh
curl -X POST \
https://auth.acme.com/auth \
-H 'Cookie: access_token=XXX;'
```

```json
{
"X-Hasura-User-Id": "42",
"X-Hasura-Role": "user"
}
```

Yet, if I test with my Hasura endpoint, I can see in the logs:

```sh
curl -X POST \
https://graphql.acme.com/v1/graphql \
-H 'Cookie: access_token=XXX;' \
-d '{"operationName":"getFoos","variables":{},"query":"query getFoos {\n foos { id } }"}'
```

I got an error from webhook:

```json
{
"type": "webhook-log",
"timestamp": "2020-02-09T18:16:43.370+0000",
"level": "error",
"detail": {
"response": "{\"error\":\"Missing `access_token` cookie\"}",
"url": "https://auth.acme.com/auth",
"method": "POST",
"http_error": null,
"status_code": 401
}
}
```
It looks like the cookies are not transferred between GraphQL Engine and auth hook. My auth code is the following (running on AWS Lambda):

```js
require('source-map-support').install();

const jwt = require('jsonwebtoken');

export const getCookiesFromHeader = headers => {
if (headers === null || headers === undefined || headers.Cookie === undefined) {
return {};
}

// Split a cookie string in an array (Originally found http://stackoverflow.com/a/3409200/1427439)
var list = {},
rc = headers.Cookie;

rc && rc.split(';').forEach(function( cookie ) {
var parts = cookie.split('=');
var key = parts.shift().trim()

try {
var value = decodeURIComponent(parts.join('='));
if (key != '') {
list[key] = value
}
} catch (err) {
console.error(`Decoding error for ${key} (${value}): ${err.message}`)
}
});

return list;
};

export const handler = async (event) => {
const cookies = getCookiesFromHeader(event.headers);
const { access_token: accessToken } = cookies;
if (!accessToken) {
return {
statusCode: 401,
body: JSON.stringify({
"error": "Missing `access_token` cookie"
})
};
}

let decodedToken = null;

try {
decodedToken = jwt.verify(accessToken, process.env.AUTH0_PEM);
} catch (err) {
return {
statusCode: 401,
body: JSON.stringify({
error: err.message
})
};
}

const hasuraClaims = decodedToken['https://hasura.io/jwt/claims'];

return {
statusCode: 200,
body: JSON.stringify({
"X-Hasura-User-Id": hasuraClaims['x-hasura-user-id'],
"X-Hasura-Role": hasuraClaims['x-hasura-default-role']
})
}
}
```

It works locally, but not once deployed.

Is there any restrictions for passing cookies? How can I debug the request to the auth hook? I tried using the `debug` log level, in vain. And I never read any Haskell before, reducing a little bit my understanding of current code base. :)

Contributor guide

Open the contributing guide

Research direction

No repository file or test is named. Start by reproducing the Hasura-to-auth-hook request with the provided curl examples and inspect the webhook request and debug logs for forwarded headers. Done means determining whether cookie forwarding is restricted and documenting or correcting the observed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, graphql, javascript
Domain
api, authentication, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.