Heath
Heath•4mo ago

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
lee
lee•4mo ago
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 convex
Heath
HeathOP•4mo ago
I 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
lee
lee•4mo ago
You can validate JWTs with crypto or a library like jose
Heath
HeathOP•4mo ago
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.
sshader
sshader•4mo ago
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
Heath
HeathOP•4mo ago
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 runMigration runMutation that allows me to somehow influence the token used to run the migration mutation. BTW I did try overwriting request.headers.Authorization, hoping it would influence the auth used for runMigration runMutation, but it did not. I do feel that this functionality is useful beyond my beacon, for instance if an http action wants to authorize a user using some external source and then impersonate them for a runMigration() runMutation() or runQuery(). It feels tedious and messy to build a parallel set of internal methods
sshader
sshader•4mo ago
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)
Heath
HeathOP•4mo ago
er, yes, mutation!
cameronm
cameronm•4mo ago
@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?

Did you find this page helpful?