Custom Auth Integration
Note: This is an advanced feature! We recommend sticking with the supported third-party authentication providers.
Convex can be integrated with any identity provider supporting the OpenID Connect protocol. At minimum this means that the provider can issue ID tokens and exposes the corresponding JWKS. The ID token is passed from the client to your Convex backend which ensures that the token is valid and enables you to query the user information embedded in the token, as described in Auth in Functions.
Server-side integration
Just like with Clerk and Auth0, the backend needs to be aware of the domain of the Issuer and your application's specific applicationID for a given identity provider.
Add these to your convex/auth.config.js
file:
export default {
providers: [
{
domain: "your.issuer.url.com",
applicationID: "your-application-id",
},
],
};
Client-side integration
Integrating a new identity provider
The ConvexProviderWithAuth
component provides a convenient abstraction for building an auth integration
similar to the ones Convex provides for Clerk and
Auth0.
In the following example we build an integration with an imaginary "ProviderX",
whose React integration includes AuthProviderXReactProvider
and
useProviderXAuth
hook.
First we replace ConvexProvider
with AuthProviderXReactProvider
wrapping
ConvexProviderWithAuth
at the root of our app:
import { AuthProviderXReactProvider } from "providerX";
import { ConvexProviderWithAuth } from "convex/react";
root.render(
<StrictMode>
<AuthProviderXReactProvider>
<ConvexProviderWithAuth client={convex} useAuth={useAuthFromProviderX}>
<App />
</ConvexProviderWithAuth>
</AuthProviderXReactProvider>
</StrictMode>,
);
All we really need is to implement the useAuthFromProviderX
hook which gets
passed to the ConvexProviderWithAuth
component.
This useAuthFromProviderX
hook provides a translation between the auth
provider API and the ConvexReactClient
API, which is ultimately responsible for making sure that the ID token is passed
down to your Convex backend.
function useAuthFromProviderX() {
const { isLoading, isAuthenticated, getToken } = useProviderXAuth();
const fetchAccessToken = useCallback(
async ({ forceRefreshToken }) => {
// Here you can do whatever transformation to get the ID Token
// or null
// Make sure to fetch a new token when `forceRefreshToken` is true
return await getToken({ ignoreCache: forceRefreshToken });
},
// If `getToken` isn't correctly memoized
// remove it from this dependency array
[getToken],
);
return useMemo(
() => ({
// Whether the auth provider is in a loading state
isLoading: isLoading,
// Whether the auth provider has the user signed in
isAuthenticated: isAuthenticated ?? false,
// The async function to fetch the ID token
fetchAccessToken,
}),
[isLoading, isAuthenticated, fetchAccessToken],
);
}
Using the new provider
If you successfully follow the steps above you can now use the standard Convex
utilities for checking the authentication state: the
useConvexAuth()
hook and the
Authenticated
,
Unauthenticated
and
AuthLoading
helper components.
See Logged-in and logged-out views for examples of using these.