Passing clerk generated token to python client?
I generated a token from clerk in react and passed it to a Python service
These are errors I got
I am using dev env and I am pretty sure the url I used in both frontend and backend is consistent. And what's more interesting is, when I removed
convex.set_auth(token)
, the code ran through. I am really confused right now, what are we doing with the token if this is not required? Why providing a token will instead lead to the auth failure?25 Replies
What does your "chats.get" query look like? Note that
await auth.getUserIdentity();
evaluates to null
when the user is not authenticated, at which point your function needs to throw an error an error if auth is bad. But if the auth token is expired (which happens every 60 seconds by default with Clerk!) auth.getUserIdentity()
will throw. This could result in the behavior you see here; null is returned for "user is not authenticated," while an error is thrown for "user appears to have attempted to authenticate, but their token is expired."
For Python a manually implemented API token is often a better fit, unless the Python code always runs within a few seconds of being handed an updated Clerk auth token.I generated a new clerk token and passed it to the python client so I don't think expiration is a problem? (I've also extended its time)
What does your chat.get function look like?
When you say "generated a new clerk token" what kind of token is this, an OpenID token from a browser login flow?
there you go
1. When I commented out the
await auth.getUserIdentity()
part, the function can run without auth, is that expected?
2. When await auth.getUserIdentity()
is uncommented, with the token generated from clerk, I got the error 401 Client Error: Unauthorized for url: ...
(I don't understand why, can I directly take the freshly generated token from clerk with (const { getToken } = useAuth()
) and pass it to Python client?)1. Yep, endpoints don't require auth so you can provide a signed-out experience. If you want to enforce auth, you need the four lines you have commented out.
2. Yeah you should be able to. I'll try to repro this.
thanks Tom
so technically, I can encode the token of my own in Python and pass it to convex? I thought convex would have a place for keep my secret for verifying the token I sent to it
No, the auth token needs to be an OpenID identity token, but you can add an extra argument that you could check, say an API token you managed yourself in another table
@whoami I'm seeing what I think is the same thing, so it's not just you, I think this is some kind of issue on our end.
The JavaScript HTTP client works for me, but Python isn't — looking into it
thanks
@whoami I take it back, as long as I'm quick enough to paste in my Clerk token it's working for me.
I don't get a 401 unless it takes longer than 60 seconds for me to refresh the page to get a new token, copy the token out of my browser and call client.set_auth() (Python) and client.setAuth() (JS)
If I do take too long, I get a "TokenExpired" 401 in Python and JavaScript
Your "Unauthorized for URL" sounds different, maybe you're using a dev deployment for your browser and a production deployment for Python, and you haven't added this auth provider to both deployments?
I think I am using dev url for both, what does
Unauthorized for URL
really mean? What was going on behind the scene?ah I think these JWT tokens are specific to a deployment, so even if you'd added the same auth provider to both deployments, you can't use a token for one for the other
so react / python are considered as different deployments?
no
just dev vs prod
you meant dev/pro
ic
you can see double-check in https://jwt.io/ that you have the right "azp" field, but it sounds like you're not confusing these two
oh right, that's where you got it — I don't believe that's enforced
I believe "Unauthorized for URL" is the default message that Requests (a dependency of the Convex Python client) prints when no message is specified for a 401
Is that because convex checks for where the request is sent from based on the azp field? in my case my react is running on
3000
port while my python server is running on 8000
, causing the latter being rejected because the azp doesn't matchI think that was a misdirect by me, I believe the azp field is not checked. It shouldn't matter from Python, when the request is made (even if you make it in a Flask handler or whatever) the port the python server is listening on isn't send to Convex in the
convex.mutation("sendMessage", {})
HTTP request.
Have you tried authenticated requests in the browser, do those work?const token = await getToken({ template: 'convex' })
ah I think the problem is I wasn't using the right template
now it is working normallygood to hear, I'll think about better errors here; if it's a token from Clerk maybe we can guess that this is the problem and put that in an error message
yea I think once convex has validated the token is from clerk, direct the user to check their token, especially if they have used the right template for generating it could be helpful
thank you Tom for your time and patience