hasura / hasura/graphql-engine
Missing cookies between Hasura and auth hook?
- 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
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