Authorization
Now that you have set up and configured authentication with Convex Auth, learn how to use the authentication state in your frontend and backend.
Sign in
See each authentication method's Configuration page for how to build a sign-in UI.
Sign out
You can sign the user out via the signOut
function:
import { useAuthActions } from "@convex-dev/auth/react";
export function SignOut() {
const { signOut } = useAuthActions();
return <button onClick={() => void signOut()}>Sign out</button>;
}
Determine what UI to show based on signed-in state
You can control which content signed-in and signed-out users can see with the
components from convex/react
. You can combine them with your custom sign-in
and sign-out components:
import { Authenticated, Unauthenticated, AuthLoading } from "convex/react";
import { SignIn } from "./SignIn";
import { SignOut } from "./SignOut";
export function App() {
return (
<>
<AuthLoading>{/* consider showing a loading indicator */}</AuthLoading>
<Unauthenticated>
<SignIn />
</Unauthenticated>
<Authenticated>
<SignOut />
<Content />
</Authenticated>
</>
);
}
function Content() {
/* render signed-in content */
}
Authenticate HTTP actions
Sometimes your React frontend might need to call your Convex backend via HTTP, usually to stream data, such as when uploading files or when loading a slowly generated AI response.
To authenticate HTTP actions calls you will need to access the JWT token the
client uses for authenticating with the backend, which you get from the
useAuthToken
hook:
import { useAuthToken } from "@convex-dev/auth/react";
function SomeComponent() {
const token = useAuthToken();
const onClick = async () => {
// You might need to set up `VITE_CONVEX_SITE_URL`
const response = await fetch(
`${process.env.VITE_CONVEX_SITE_URL!}/someEndpoint`,
{ headers: { Authorization: `Bearer ${token}` } },
);
// ...
};
// ...
}
Use authentication state in backend functions
Within a Convex function (opens in a new tab), you can access
information about the currently logged-in user and session via helper functions
exported from @convex-dev/auth/server
file.
The getAuthUserId
and getAuthSessionId
methods use the Convex-built-in
ctx.auth.getUserIdentity()
under the hood and provide a typed API.
Data model
Convex Auth defines users
and
authSessions
tables for you.
When a user first signs up, a document is created in the users
table.
When a user signs in (including after initial sign-up), a document is created in
the authSessions
table. The session document exists until the session expires
or the user signs out. See
session document lifecycle.
One user can have many active sessions simultaneously. For web apps the same session is shared by all browser tabs by default, but this can be configured.
Get currently signed-in user ID
To get the currently signed-in user's ID, call getAuthUserId
and pass it a
query, mutation or action ctx
:
import { getAuthUserId } from "@convex-dev/auth/server";
import { query } from "./_generated/server";
export const currentUser = query({
args: {},
handler: async (ctx) => {
const userId = await getAuthUserId(ctx);
if (userId === null) {
return null;
}
return await ctx.db.get(userId);
},
});
The function returns Id<"users">
(or null
when the client isn't
authenticated).
Get current session ID
To get the current session ID, call getAuthSessionId
and pass it a query,
mutation or action ctx
:
import { getAuthSessionId } from "@convex-dev/auth/server";
import { query } from "./_generated/server";
export const currentSession = query({
args: {},
handler: async (ctx) => {
const sessionId = await getAuthSessionId(ctx);
if (sessionId === null) {
return null;
}
return await ctx.db.get(sessionId);
},
});
The function returns Id<"authSessions">
(or null
when the client isn't
authenticated).
Loading users and sessions
You can retrieve the user or session document via ctx.db.get()
in queries and
mutations.
See Customizing Schema for guidance on attaching additional information to users and sessions.
Detecting anonymous users
If you enabled anonymous sign-in, the user ID returned by
getAuthUserId
might belong to an anonymous user. You might want to restrict
what anonymous users can do compared to authenticated users. To do this, load
the current user and check the isAnonymous
field:
import { mutation } from "./_generated/server";
import { auth } from "./auth";
export const doSomethingAfterProperSignIn = mutation({
args: {
/* ... */
},
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (userId === null) {
throw new Error("Client is not authenticated!");
}
const user = await ctx.db.get(userId);
if (user.isAnonymous) {
throw new Error("User must sign in with an authentication method!");
}
// ...
},
});
Server-side authentication in Next.js
You can set up your Next.js App Router app to have access to the authentication state on the server.
See the dedicated Next.js page.