Custom auth
Hi everyone,
I am trying to understand how auth works in convex.
I want to implement custom oauth and not use clerk or auth0.
What I usually do is I have 2 endpoints per providers.
For example, /oauth/google that redirects users to the google login page, and another endpoint /oauth/google/callback that get the user profile and insert it into the database.
Then I create a custom JWT, redirect the user to https://frontend/?access_token=***, extract the access_token on the frontend (SPA), store it in local storage, then include it in every requests I make to my API.
I know I can create endpoints with http actions (for oauth redirect and callback), store users in the database and generare JWT but is there a way to setup the convex javascript client to send my own JWT on every requests?
I tried to use client.setAuth() but it says provider not recognized.
My goal is to be able to use convex built in ctx.auth in server functions so that I don't have to fetch the user manually at the beginning of every function.
10 Replies
Thanks for posting in <#1088161997662724167>.
Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets.
- Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.)
- Use search.convex.dev to search Docs, Stack, and Discord all at once.
- Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI.
- Avoid tagging staff unless specifically instructed.
Thank you!
You might want to check out https://labs.convex.dev/auth (either to use directly, or to use as a reference implementation).
Auth with Convex works with JWTs -- you generally provide the client (e.g. React client, JS client, but lmk if you're using a different client) with a
fetchToken
function that fetches a JWT client-side (e.g. reading from local storage, making a call to something like clerk / auth0). And then the Convex backend will validate that this token is valid according to the OIDC spec using your auth.config.ts
.
As long as your implementation of fetchToken
respects the forceRefresh
parameter (i.e. it returns a new JWT when forceRefresh
is true), the Convex client handles refetching the token and making sure the backend always has an up to date token.
If you're seeing errors like "no provider found" or that the token is not valid, I'd check that the token matches up with you auth.config.ts
(specifically the iss
field should match a domain in your auth.config.ts
) -- check out https://docs.convex.dev/auth/debug#step-3-check-that-backend-configuration-matches-frontend-configurationConvex Auth - Convex Auth
Authentication library for your Convex backend
Debugging Authentication | Convex Developer Hub
You have followed one of our authentication guides but something is not working.
Thank you for your help.
I looked at convex auth source code (which is for react only?) and it looks like that's what I am trying to achieve, but with svelte.
I am still confused about setAuth and auth.config.js.
It looks like setAuth requires an IdToken and not an access token. And it looks like convex backend will try to validate the IdToken based on the provider in the "iss" and will try to reach well-known/jkws.json?
Does that mean if I want to use my own token in setAuth() I need to implement my own oauth backend (with the well-known/jwks.json endpoint)?
Yes, sounds like you have the right understanding of this.
If it is your goal to implement auth without using Clerk or Auth0, then using Convex Auth directly seems like the way to go. It implements well-known/jkws.json etc. for you, as an OAuth OpenID Connect ID provider.
If you don't want to use the Convex Auth library, but you want to mint your own JWTs that can be used with setAuth with Convex, then yes that's exactly right, setAuth requires an identity token. So yes, if you want to use your own token in setAuth you need to implement your own OAuth backend. The Convex Auth library does this for you, so it's a good place to start.
(which is for react only?)Yeah, I count about 600 liners of React code in https://github.com/get-convex/convex-auth/tree/main/src/react so if you want to do this with Svelte, that's the part you'll need to reimplement.
GitHub
convex-auth/src/react at main · get-convex/convex-auth
Library for built-in auth. Contribute to get-convex/convex-auth development by creating an account on GitHub.
Thanks! I just realized I can still use convex-auth backend part and implement only the svelte front end part.
Hello @Tom and @sshader . I am doing almost the exact same thing with @Spioune . Here is my context. I have already setup a fully custom Oauth flow with google, fully barebones no library just nextjs and ironsession to save the session info. So to make convex aware of my currently signed in user I am using the below pattern
that almost works. I get a valid token in my own unique ways and return it. but i get the error message
Failed to authenticate: "No auth provider found matching the given token", check your server auth config
okay. now with my many searches online i think I am supposed to follow the link shared by @sshader that guides setting up with convex auth but in my following it seems convex is kind of tied to auth.js
especially the part of getting the Google provider.
Bro I cannot stress enough how much I want to avoid that library. I do not want to see it at all in my codebase. How can I avoid the error without having to install AuthJS.
Here is my current auth.config.ts
The Convex Auth library is built around sharing code with Auth.js. It sounds like you don't want to use the Convex Auth library (npm library
@convex-dev/auth
), but instead you want to use the built in auth support that is part of Convex (npm library convex
)
That allows you to use your own JWT if you add the right info to convex/auth.config.ts
. See https://docs.convex.dev/auth/advanced/custom-auth.Hi @AmohPrince
I came to the conclusion that no matter how "custom" you want to implement your auth, the only thing you cannot control is how convex backend validates the token you pass to setAuth().
It does this by looking at the "iss" field inside the token (it needs to be a JWT, so your iron session token won't work), looks at your auth.conf.ts to find the matching iss then calls the /.well-known/jwks.json endpoint to get the public keys to verify the token.
So if you want to be 100% custom auth, you will need to implement this (see OpenID spec).
I didn't go this far and I didn't use convex for a long time so my memory is a bit rusty.
But that's what I remember.
@Tom it would be nice if we could have our own token validator on the backend and setAuth would then just be a way to attach any session id to the requests. Then for DX, convex could provide an already made function that does the OICD validation like it is done today.
Thanks @Spioune . I found out a way here https://docs.convex.dev/auth/advanced/custom-auth it worked for me
Custom Auth Integration | Convex Developer Hub
Note: This is an advanced feature! We recommend sticking with the