I have a bit unusual app.
I am trying to approach this by utilizing the actions feature. That gives me a custom mutation that accepts collected info and the handler should run some queries/mutations back at Hasura to create all necessary structures.
Since the user is anonymous at that point, I don't have any auth for communicating with Hasura. I was thinking about using webhook auth, but it feels too much back & forth especially in this actions scenario. Another obvious option is using admin secret key, but that solves only part of the problem.
I've decided to use Firebase Auth here. I followed the blog post but that doesn't work here. I need to call auth.signInWithCustomToken on the client-side with a token obtained from the action run.
And that's where it gets problematic. A token created with Firebase Admin SDK and function createCustomToken looks like this.
const token = await app.auth().createCustomToken(user.uid, {
hasura: {
'x-hasura-default-role': 'rocket',
'x-hasura-allowed-roles': ['rocket'],
},
})

Obviously, that does work (error JWSInvalidSignature). You may notice the nested claims/hasura key. Unfortunately, that's done by createCustomToken and for some reason, it completely ignores claims stored on the user with setCustomUserClaims(). It's a weird inconsistency, but whatever.
So I did change claims_namespace_path in jwt_secret.
{
"type":"RS256",
"jwk_url":"https://www.googleapis.com/service_accounts/v1/jwk/[email protected]",
"audience": "projectId",
"issuer": "https://securetoken.google.com/projectId",
"claims_namespace_path": "$.claims.hasura"
}
Unfortunately, that's not a root of a problem and error is the same. It seems that Hasura has a problem validating a signature of that token. It looks like that createCustomToken user a different signature than the token that's created on the client-side. But I am kinda lost in the whole JWK mechanics and how to find out what's actually used.
Alright, turns out I was using it all wrong thanks to @leoalves from Discord. Apologize for all the rumble here.
The createCustomToken is meant only for consumption on the client and signInWithCustomToken method. That creates a correct JWT token for connecting back to Hasura. No other scenario is possible.
As for connecting from the action handlers server-side, there doesn't seem to be a way to utilize Firebase here. It would be kinda nice if similar JWT could be created server-side to carry the information about Hasura role, but I haven't found any specification for that, especially regarding the key used to sign.
Instead the admin secret has to be used. It's not great to have such important value spread all over the place, but it's bearable I guess. And if I want to limit permissions (ie. to prevent code injection attacks), it's as easy as passing X-Hasura-Role header which will be respected.
Most helpful comment
Alright, turns out I was using it all wrong thanks to
@leoalvesfrom Discord. Apologize for all the rumble here.The
createCustomTokenis meant only for consumption on the client andsignInWithCustomTokenmethod. That creates a correct JWT token for connecting back to Hasura. No other scenario is possible.As for connecting from the action handlers server-side, there doesn't seem to be a way to utilize Firebase here. It would be kinda nice if similar JWT could be created server-side to carry the information about Hasura role, but I haven't found any specification for that, especially regarding the key used to sign.
Instead the admin secret has to be used. It's not great to have such important value spread all over the place, but it's bearable I guess. And if I want to limit permissions (ie. to prevent code injection attacks), it's as easy as passing
X-Hasura-Roleheader which will be respected.