Spioune
Spioune2mo ago

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
Convex Bot
Convex Bot2mo ago
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!
sshader
sshader2mo ago
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-configuration
Convex 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.
Spioune
SpiouneOP2mo ago
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)?
ballingt
ballingt2mo ago
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.
ballingt
ballingt2mo ago
(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.
Spioune
SpiouneOP2mo ago
Thanks! I just realized I can still use convex-auth backend part and implement only the svelte front end part.
AmohPrince
AmohPrince2w ago
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
useEffect(() => {
const fetchToken: AuthTokenFetcher = async (args) => {
console.log("args", args);
const { data } = await axios.get<{ token: string | null }>(
`/api/session/token?force=${args.forceRefreshToken}`
);

console.log("data", data);
return data.token;
};

convex.setAuth(fetchToken, (isAuthenticated) => {
console.log("Auth status changed:", isAuthenticated);
});
}, []);
useEffect(() => {
const fetchToken: AuthTokenFetcher = async (args) => {
console.log("args", args);
const { data } = await axios.get<{ token: string | null }>(
`/api/session/token?force=${args.forceRefreshToken}`
);

console.log("data", data);
return data.token;
};

convex.setAuth(fetchToken, (isAuthenticated) => {
console.log("Auth status changed:", isAuthenticated);
});
}, []);
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
import Google from "@auth/core/providers/google";

// eslint-disable-next-line import/no-anonymous-default-export
export default {
providers: [Google],
};
import Google from "@auth/core/providers/google";

// eslint-disable-next-line import/no-anonymous-default-export
export default {
providers: [Google],
};
ballingt
ballingt2w ago
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.
Spioune
SpiouneOP2w ago
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.
AmohPrince
AmohPrince2w ago
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

Did you find this page helpful?