getUserIdentity() resulting none
So I am calling http action from a 3rd party service in my case LinkedIn and following there 3 steps legged oauth. But while calling
Identity is returning null, how can I authenticate in this scenario?
Sharing my full code for more ref :
https://github.com/imaxisXD/AIvy-Post/blob/main/convex/oauth.ts
GitHub
AIvy-Post/convex/oauth.ts at main · imaxisXD/AIvy-Post
Contribute to imaxisXD/AIvy-Post development by creating an account on GitHub.
15 Replies
Have you tried this yet? https://docs.convex.dev/functions/http-actions#authentication
HTTP Actions | Convex Developer Hub
HTTP actions allow you to build an HTTP API right in Convex!
As in, passing the bearer token from the third party? If they’re calling directly, like a webhook, then there won’t be any auth there. You’ll have to pass user identifiers through in state (but make sure you do so securely - Google for strategies for oauth “state”). This is one reason to redirect back to the website instead of directly to convex- the website knows which user is logged in and can make an authenticated call.
@ian quick doubt if a third party calls my http action then ctx auth will not be present in ctx right? And if I call some function from this http action then again these functions will not have auth right?
So if I understood correctly, first redirect back to my nextjs route there I can check to auth with convex and then make an authenticated call. right ?
That's right
If the third party isn't specifying the
Authorization
header then you'll have to get the user from any data they send you. For example, once you swap the oauth code for tokens, you can decode those tokens and look at the data. Or use the token to fetch user data from the LinkedIn api. If you also want to know what logged-in-via-clerk user started the request, you need to channel the request back through the user's browser (vs. directly linkedin server -> convex server). make sense?after reading it multiple times, it makes some sense. Will it be alright to keep this chat open on more similar doubts related to this?
If you also want to know what logged-in-via-clerk user started the request, you need to channel the request back through the user's browser (vs. directly linkedin server -> convex server). make sense?
@ian so to do this, to know the user that started the request . Will it be possible to achieve this via nextjs route handlers?yes - if it's redirecting the user, the next nextjs route will be serving a request from the users's browser. This means it'll have access to the browser cookies to do server-side auth. You could alternatively handle this on the client-side on the page it redirected to - taking the query params from the page's location and passing them as arguments to convex when convex has the user logged in.
So in conclusion @ian this is how it will be done :
User clicks the btn -> goto linkedin server -> linkedin server calls your nextjs route (here we do user authentication ) -> then call linked in server to get access token through the code we received from previous call -> and store the user data through a convex function
That works. Alternatively you can do
call linked in server to get access token through the code we received from previous call -> and store the user data through a convex functionAs "call convex function with the code and get access token from linkedin from the convex function, get user data, and store it". If you need the token on the client to do other things, your approach makes sense. If you only need the token server-side, you can do the code exchange from Convex which will have a faster connection to LinkedIn. I'm assuming here that your user is "authenticated" with something other than LinkedIn. If here you're hoping to use LinkedIn as the primary login mechanism, let me know.
So right now I'm not using LinkedIn as the primary login mechanism.
But what I want to achieve is to store the access token with the user data(ie coming from the clerk) .
In this case what approach will be good ?
User clicks the btn -> goto linkedin server -> linkedin server calls your nextjs route (here we do user authentication ) -> call a convex action with the code we received from previous call -> from action, call linkedIn server to get access token from the code -> from the action, call an internalMutation via ctx.runMutation to store the access token. the internalMutation can call
ctx.auth.getUserIdentity()
.@ian I tried this approach but still in action
ctx.auth.getUserIdentity()
is still returning a null
If you could review the code, it would mean a lot to me.
The Flow is -> UI (Calling through server action) -> Nextjs route -> Action
UI: https://github.com/imaxisXD/AIvy-Post/blob/main/components/social-media-linkers/linkedin-connect-btn.tsx#L5
Route: https://github.com/imaxisXD/AIvy-Post/blob/main/app/api/linkedIn/oauth/route.ts
Action: https://github.com/imaxisXD/AIvy-Post/blob/main/convex/oauth.ts#L63
Internal Mutation: https://github.com/imaxisXD/AIvy-Post/blob/main/convex/users.ts#L104
Thank youAh, sorry I should have specified you need to call the convex action from the client where you're logged in, or pass a third argument to
fetchAction
with the token, if you can access the clerk auth state in that route
the websocket client (useMutation) has the token set by the convex provider (but you should make sure it has fully authenticated first ) but from the nextjs server you need to manually specify it for each request@ian this got me So confused xD
When you call fetchAction it doesn’t have any logged in state. You need to pass it as the third parameter. It’s on your api endpoint, server side. Clerk has nextjs middleware to make the token available there but you’ll have to look that up
I think these are the docs for what you're tryinging to do.
for example, here's a snippet for an nextjs api route where I used the auth token from clerk to call a mutation that requires a logged in user:
I can't remember if you also need a
middleware.ts
file for clerk, but heres the one I used for reference:
Next.js Server Rendering | Convex Developer Hub
Next.js automatically renders both Client and Server Components on the server