Open siddhatiwari opened 3 years ago
What do you mean by unsigned tokens? Do you mean the algo is none
?
I have this issue also with the emulator. It keeps getting back with Could not verify JWT: JWSError JWSNoSignatures
I'm using 1.3.2. This is an issue for me as I want to test my cloud functions with actions as I'm working but I would have to make use of live authentication instead.
Edit: Thinking about it, I can make do with live auth for now.
I'm limited by live auth as it happens... in firebase I can run all via its emulator but as I have to use a key or jwk_url it just breaks. This is less than ideal as I have to extract the JWT data with 3rd party software. I would prefer to be able to use firebaseAdmin.auth().verifyIdToken(idToken)
for example.
@tirumaraiselvan Yes, it appears the algorithm is none, which doesn't appear to be specified in the JWT standard, but it'd be super handy if Hasura could support. This would allow for completely local development - without touching a remote auth server at all.
Here's a dump of one of the tokens produced by the mentioned auth emulator:
Headers:
{
"alg": "none",
"typ": "JWT"
}
Full payload:
{
"aud": "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
"iat": 1609857856,
"exp": 1609861456,
"iss": "firebase-auth-emulator@example.com",
"sub": "firebase-auth-emulator@example.com",
"uid": "yRdKtVuhWFShAUm43oT9HhpGMNid",
"claims": {
"https://hasura.io/jwt/claims": {
"...": "..."
}
}
}
Given that the token has an issuer and audience, it may be possible to allow a "type" of "none" only when one (or both) of these are specified.
I would add an environment variable for that circumstance too so it can only be used in testing and development
@marksyzm I think it should be enough for the existing HASURA_GRAPHQL_JWT_SECRET
environment variable to support a none
type
Yeah probably; save us having user error issues
Is there any solution around this?
@tirumaraiselvan the firebase doc section: https://firebase.google.com/docs/emulator-suite/connect_auth#id_tokens
I also just ran into this issue. I would agree in having the none
option on Hasura's JWT secret for local testing and development. Does anyone know a work around for this in the meanwhile?
Update Here is my current work around. I'm using Apollo with NextJS and I just added some middleware to handle the checking of environments. If the environment is local(where I'm using firebase emulator), it signs the token on request.
// Generate a signed token for the request
// since firebase auth emulator tokens are unsigned
const getLocallySignedToken = token => {
return jwt.sign(jwt.decode(token), "secret");
};
// condition for signing the token
const isLocalEnvironment = () => {
return location.hostname === "localhost";
};
//middleware to apply signed token on request
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
const token = getAuthToken();
operation.setContext(() => ({
headers: token
? {
Authorization: `Bearer ${
isLocalEnvironment() ? getLocallySignedToken(token) : token
}`
}
: { "X-Hasura-Role": `anonymous` }
}));
return forward(operation);
});
Remember to set the secret to use a key instead of the firebase JWK
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256", "key": "secret"}'
I would still LOVE a type of none
on the HASURA_GRAPHQL_JWT_SECRET
though :).
That will help for now, thanks... It isn't great having such a public work around in the code of course but hey, it'll be enough for the time being
Remember to set the secret to use a key instead of the firebase JWK
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256", "key": "secret"}'
This causes errors and I can't run the docker-compose. Normal Firebase JWT secret does work though. Odd!
Update: Nevermind, my "secret"
was exactly "secret"
which is not long enough! From the docs:
``key``
^^^^^^^
- In case of symmetric key (i.e. HMAC based key), the key as it is. (e.g. -
"abcdef..."). The key must be long enough for the algorithm chosen,
(e.g. for HS256 it must be at least 32 characters long).
- In case of asymmetric keys (RSA, EdDSA etc.), only the public key, in a PEM encoded
string or as a X509 certificate.
In case anyone is using flutter/dart, here is some code that uses the jwt_decoder and jaguar_jwt packages to sign tokens returned by the firebase emulator and have them be trusted by the local instance of Hasura:
String _calcJwtForHasura(String token) {
if (kDebugMode) {
try {
var decoded = JwtDecoder.decode(token);
var claims = JwtClaim.fromMap(decoded, defaultIatExp: false);
return issueJwtHS256(
claims, 'somerandompasswordthatmatcheswhatisinHASURA_GRAPHQL_JWT_SECRET');
} catch (e) {
print("Got unexpected exception (will return unmodified token): $e");
return token;
}
} else {
return token;
}
}
Future<String> calcJwtForHasura(String token) async {
return await compute(_calcJwtForHasura, token);
}
love you @klondikedragon, if I was a woman, I would have had your kids.
I also just ran into this issue. I would agree in having the
none
option on Hasura's JWT secret for local testing and development. Does anyone know a work around for this in the meanwhile?Update Here is my current work around. I'm using Apollo with NextJS and I just added some middleware to handle the checking of environments. If the environment is local(where I'm using firebase emulator), it signs the token on request.
// Generate a signed token for the request // since firebase auth emulator tokens are unsigned const getLocallySignedToken = token => { return jwt.sign(jwt.decode(token), "secret"); }; // condition for signing the token const isLocalEnvironment = () => { return location.hostname === "localhost"; }; //middleware to apply signed token on request const authMiddleware = new ApolloLink((operation, forward) => { // add the authorization to the headers const token = getAuthToken(); operation.setContext(() => ({ headers: token ? { Authorization: `Bearer ${ isLocalEnvironment() ? getLocallySignedToken(token) : token }` } : { "X-Hasura-Role": `anonymous` } })); return forward(operation); });
Remember to set the secret to use a key instead of the firebase JWK
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256", "key": "secret"}'
I would still LOVE a type of
none
on theHASURA_GRAPHQL_JWT_SECRET
though :).
Yeah, have been using similar workaround. One thing to note is that jsonwebtoken
library is not intended for browsers. Latest version does not work and old versions add about 150kb nodejs polyfills https://github.com/auth0/node-jsonwebtoken/issues/885#issuecomment-1423983985
I also just ran into this issue. I would agree in having the
none
option on Hasura's JWT secret for local testing and development. Does anyone know a work around for this in the meanwhile?Update Here is my current work around. I'm using Apollo with NextJS and I just added some middleware to handle the checking of environments. If the environment is local(where I'm using firebase emulator), it signs the token on request.
// Generate a signed token for the request // since firebase auth emulator tokens are unsigned const getLocallySignedToken = token => { return jwt.sign(jwt.decode(token), "secret"); }; // condition for signing the token const isLocalEnvironment = () => { return location.hostname === "localhost"; }; //middleware to apply signed token on request const authMiddleware = new ApolloLink((operation, forward) => { // add the authorization to the headers const token = getAuthToken(); operation.setContext(() => ({ headers: token ? { Authorization: `Bearer ${ isLocalEnvironment() ? getLocallySignedToken(token) : token }` } : { "X-Hasura-Role": `anonymous` } })); return forward(operation); });
Remember to set the secret to use a key instead of the firebase JWK
HASURA_GRAPHQL_JWT_SECRET='{"type":"HS256", "key": "secret"}'
I would still LOVE a type of
none
on theHASURA_GRAPHQL_JWT_SECRET
though :).
Great info thanks! @Rykuno
i have done similar and got it to work although had to create an endpoint to sign the JWT's as couldnt find a web front end token signer that would do the job and my code for token refreshing is client side.
I'm using the firebase auth emulator for local development which produces unsigned tokens. I'm running the firebase auth emulator and hasura (v1.3.3) locally using docker. It seems that hasura views the unsigned tokens using the recommended
HASURA_GRAPHQL_JWT_SECRET
for firebase as invalid. When I remove theHASURA_GRAPHQL_JWT_SECRET
, all requests are defaulted to theanonymous
role, which doesn't represent the actual role of the user from the unsigned token.Is there a flag to allow using unsigned JWT tokens for development purposes? Or am I missing something with my configuration?
Hasura has been a major productivity boost for me! Just having this small issue setting up my local environment