Setting auth from within an HTTP action
I am using navigator.sendBeacon() to call an HTTP action on page unload, which in turn uses runMutation() to call one of my mutations. This generally works ok, but sendBeacon() cannot be configured to send headers like Authorization. I can pass the JWT via the POST body, but once I receive it within the HTTP action I am not sure how to then configure convex to use this JWT, to somehow call my runMutation with the JWT context, or to otherwise validate the JWT and extract my user information so that my mutation can work properly.
9 Replies
Can you pass the JWT as an arg to the mutation and validate it there? Or make it an
internalMutation
and pass in an argument like user id, which is fine since internal mutation cannot be called from outside convexI could pass the JWT to the mutation, but how can I validate the JWT in the mutation?
I also could pass userId to an internal mutation, but I need to first validate the JWT to know the authoritative userId
You can validate JWTs with
crypto
or a library like jose
hm, yes - but I know that Convex is handling all this stuff already, and was hoping for some method that would allow me to avoid reimplementing that kind of logic in my codebase.
Just to link for any future readers -- https://docs.convex.dev/auth/functions-auth#http-actions documents the usual approach of sending the JWT in a header (which you said isn't an option here).
Sounds like what you want is something like
auth.extractIdentity(jwt)
and then we could pass the JWT in as an argument.
As a hack, I guess you could have one HTTP action for sendBeacon, which contains the JWT as an argument, and then in that action just do a fetch to another one of your HTTP actions, but this time setting the Authorization
header?Auth in Functions | Convex Developer Hub
_If you're using Convex Auth, see the
As a hack, I guess you could have one HTTP action for sendBeacon, which contains the JWT as an argument, and then in that action just do a fetch to another one of your HTTP actions, but this time setting the Authorization header?@sshader haha yeah 😄 I actually did this already, I just didn't want to reveal I had a solution because it feels like such a hack btw I found this method
http.runRequest()
, but I cannot find any use of it or sample code, but the documented description sounds potentially relevant, allowing me to just loop a request back into the router. Do you have any details on this?
Given a JSON string representation of a Request object, return a Response by routing the request and running the appropriate endpoint or returning a 404 Response. Sounds like what you want is something like auth.extractIdentity(jwt) and then we could pass the JWT in as an argument.Yes, that would be great. Or one of these options would be even better, 1. something like
ctx.auth.setIdentityFromJwt(jwt)
which would then allow me to set the identity for the current request from a source other than the http header.
2. Additional arguments on Re:
runRequest
-- this is more or less an internal function that we call into when handling an HTTP action and isn't really meant to be used directly (it involves converting a special JSON representation of a Request
into a Request
)
And cool setIdentityFromJwt
makes sense. (also assuming by "migration" you mean "mutation" here)er, yes, mutation!
@sshader I am running into the same issue. I am using Hono to build a REST API, and I want to use Hono middleware to authenticate the user. You're article on this was very helpful btw so thanks for that!
Already can get the access token in through http only cookies as well as Bearer token to give the end user multiple options to send their credentials, but can't find a way to pass the token to convex auth to identify the user other than the hack you mentioned above making an additional fetch call with the Authorization header.
That hack feels kind of clunky especially since we're checking auth state on every request, and seems like it would result in additional function calls or action compute. Would this be the case with that workaround?