#convex auth with password using next
10 messages · Page 1 of 1 (latest)
A 404 error on POST to /api/auth when using Convex Auth with password authentication in a Next.js app is a common issue, and several causes and solutions are documented:
Common Causes & Solutions
-
Middleware Location in Next.js with
srcDirectory- If you are using a
srcdirectory (e.g.,src/app,src/components), yourmiddleware.tsfile must also be inside thesrcdirectory. If it's at the project root, Next.js won't register it, and/api/authrequests won't be proxied to Convex, resulting in a 404 error. - Solution: Move your
middleware.tsinto thesrcdirectory if your app structure uses it. This has resolved the issue for others in the same situation Discord: Convex auth failing when adding src directory.
- If you are using a
-
Missing or Incorrect Middleware
- Convex Auth for Next.js relies on middleware to proxy
/api/authrequests to Convex. If the middleware is missing, misconfigured, or not in the correct location, you'll get a 404. - Solution: Ensure you have the correct middleware set up as described in the Convex Auth docs. Here’s a typical example:
import { convexAuthNextjsMiddleware, createRouteMatcher, nextjsMiddlewareRedirect, } from "@convex-dev/auth/nextjs/server"; const isSignInPage = createRouteMatcher(["/signin"]); const isProtectedRoute = createRouteMatcher(["/", "/server"]); export default convexAuthNextjsMiddleware(async (request, { convexAuth }) => { if (isSignInPage(request) && (await convexAuth.isAuthenticated())) { return nextjsMiddlewareRedirect(request, "/"); } if (isProtectedRoute(request) && !(await convexAuth.isAuthenticated())) { return nextjsMiddlewareRedirect(request, "/signin"); } });
- Convex Auth for Next.js relies on middleware to proxy
export const config = {
matcher: ["/((?!.\..|_next).)", "/", "/(api|trpc)(.)"],
};
```
- Make sure this file is in the correct directory for your project structure Discord: Convex auth failing when adding src directory.
-
Monorepo or Custom Directory Structure
- In monorepos or custom setups, ensure that the middleware and all Convex-related files are correctly referenced and deployed. If routes aren’t registered in
convex/http.tsor the code isn’t deployed,/api/authwill 404. - Solution: Double-check your deployment and that your routes are registered Discord: POST /api/auth 404 for next js app using convex + convex auth in monorepo.
- In monorepos or custom setups, ensure that the middleware and all Convex-related files are correctly referenced and deployed. If routes aren’t registered in
-
General Debugging
- If you’re still stuck, add verbose logging to your middleware to see what’s happening, and ensure you’re not missing any required steps from the Convex Auth setup guide Discord: Self Hosted Auth.
Summary
- Move your
middleware.tsinto thesrcdirectory if you’re using one. - Ensure your middleware is set up and configured correctly.
- Check that your routes are registered and your deployment is up to date.
If you follow these steps, the 404 on /api/auth should be resolved. If not, please share your project structure and middleware file for more targeted help.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@junior flint Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Let me check the knowledge base for you again. One moment! :books:
Great to hear you solved the middleware issue!
For Convex Auth with password authentication, your users table schema can be customized to include any fields you want to collect during sign-up. At a minimum, you’ll want to store the user’s email. You can add more fields (like name, roles, etc.) as needed.
Here’s a typical example for a users table schema for password authentication:
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";
export default defineSchema({
...authTables,
users: defineTable({
email: v.string(),
name: v.optional(v.string()),
// Add any additional fields you want:
// role: v.optional(v.string()),
// avatarUrl: v.optional(v.string()),
}).index("email", ["email"]),
// Your other tables...
});
- If you want to add required fields, make sure your sign-up form and the
profilecallback in your Password provider return those fields, otherwise you’ll get schema validation errors. - If you want to add optional fields, use
v.optional().
Important:
You can only make a field required if it is always provided during sign-up. If you make a field required but don’t provide it, you’ll get an error during user creation. Many developers start with fields as optional and make them required once their sign-up flow is finalized and always provides those fields Customizing Schema.
If you want to store additional fields from your sign-up form, you should also customize the profile method in your Password provider to return those fields. For example:
import { Password } from "@convex-dev/auth/providers/Password";
import { DataModel } from "./_generated/dataModel";
export default Password<DataModel>({
profile(params, ctx) {
return {
email: params.email as string,
name: params.name as string,
// Add other fields here
};
},
});
[Customize user information](<https://labs.convex.dev/auth/config/passwords#customize-user-information>)
**Summary:**
- Start with `email: v.string()` in your users table.
- Add more fields as needed, using `v.optional()` for optional fields.
- Make sure your sign-up form and `profile` callback provide all required fields.
Let me know if you want an example with specific fields!
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@junior flint Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Let me check the knowledge base for you again. One moment! :books:
In Convex Auth, the user's password is not stored directly in your users table. Instead, password handling (including hashing and verification) is managed internally by the Convex Auth system when you use the Password provider.
When a user signs up or signs in, the password is processed by the Password provider, which by default uses Scrypt (from Lucia) to hash the password securely. You do not need to add a password field to your users table—Convex Auth manages password storage and verification in its own internal tables and logic. Your users table is for user profile data (like email, name, etc.), not for storing password hashes or secrets.
If you want to customize how passwords are hashed or verified, you can provide a crypto option in the Password provider config, but this is advanced usage. By default, Convex Auth handles this securely for you Password provider docs PasswordConfig options.
Summary:
- You do not need a
passwordfield in youruserstable. - Passwords are handled, hashed, and verified internally by Convex Auth.
- Your schema should focus on user profile fields (email, name, etc.).