#using convex auth need to create users as an admin

13 messages · Page 1 of 1 (latest)

finite meadow
#

i'm using convex auth with vite and i dont' want users to signup or reset passwords rather i as an admin want to do it creating new users or resetting existing users passwords. guide

manic inletBOT
#

Hi @finite meadow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To create and manage users as an admin using Convex Auth, you would need to create a dashboard and implement the necessary functionality. This isn't built into Convex Auth, but you can build it yourself. Here's a general guide on how you can achieve this:

  1. Create User: You can create a user without a password. When the user logs on without a password (because they don't have one), they receive a magic link. The user will continue to log in this way until they create a password through their 'Manage account' functionality. This is similar to how Clerk does it.

  2. Update User: You can create functionality to change a user's email or any of their profile (user) details.

  3. Delete User: You can create functionality to completely delete the user from the system, user, authTable records, etc.

  4. Disable/Enable User: You can create functionality to stop the user from logging into the system.

To build this, you'd have an admin role for users and create a route in your application that requires the current user to be an admin, and create this dashboard UI. The functionality in Convex looks like normal mutations, with the user authenticated to check it's themselves or an admin[^1^].

For resetting passwords, you can use the Password provider included in Convex Auth which supports password reset flow via the reset option[^5^]. You can control the sign-in process on the backend by using the ConvexCredentials provider config[^6^].

Here's an example of how you can create a user:

async createOrUpdateUser(ctx: GenericMutationCtx<DataModel>, args) {
  if (args.existingUserId) {
    return args.existingUserId;
  }
  const existingUser = await ctx.db
    .query("users")
    .withIndex("email", (q) => q.eq("email", args.profile.email))
    .first();
#

if (existingUser) {
return existingUser._id;
}
return ctx.db.insert("users", {
email: args.profile.email,
});
}

[^2^]

And here's an example of how you can reset a password:

```javascript
const sendResetPasswordEmail = async (formValues: z.infer<typeof forgotPasswordSchema>) => {
  await signIn("password", {
    flow: "reset",
    email: formValues.email,
  })
    .then(() =>
      toast({
        title: "Success",
        description: `An email has been sent to ${formValues.email} with a password reset link`,
      }),
    )
    .catch(() =>
      toast({
        title: "Failure",
        variant: "destructive",
        description:
          "Failed to send password reset link. Make sure account is associated with the given email",
      }),
    );
};

[^2^]

Please note that Convex Auth is currently in beta, so some features may not be available or may change in the future[^9^].

^1^]: [Discord Support Thread (https://discord.com/channels/1019350475847499849/1279376450688122880)
^2^]: [Discord Support Thread (https://discord.com/channels/1019350475847499849/1273690158792970340)
^5^]: [Email reset setup (https://labs.convex.dev/auth/config/passwords#provider-configuration-1)
^6^]: [Completely customize the sign-in process (https://labs.convex.dev/auth/config/passwords#completely-customize-the-sign-in-process)
^9^]: [Convex Auth (https://labs.convex.dev/auth)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@finite meadow kapa.ai is still learning and improving, please let us know how it did by reacting below

finite meadow
#

@manic inlet what if i just use convexcredentials and don't encrypt user passwords at all. i don't need all that just a simple flow to login

manic inletBOT
#

Let me check the knowledge base for you. One moment! :books:

#

While it's technically possible to use ConvexCredentials and not encrypt user passwords, it's highly discouraged due to security reasons. Storing passwords in plain text is a major security risk. If an attacker gains access to your database, they would have access to all user passwords. This could lead to unauthorized access to user accounts, data breaches, and other serious issues.

Here's an example of how you can use ConvexCredentials for a custom authentication implementation[^2^]:

import ConvexCredentials from "@convex-dev/auth/providers/ConvexCredentials";
import { convexAuth } from "@convex-dev/auth/server";
 
export const { auth, signIn, signOut, store } = convexAuth({
  providers: [
    ConvexCredentials({
      authorize: async (credentials, ctx) => {
        // Your custom logic here...
      },
    }),
  ],
});

In the authorize function, you would typically check the provided credentials against your user database. If the credentials are valid, you would return the user's data. If not, you would throw an error.

However, again, it's crucial to store passwords securely. This typically involves hashing the password before storing it and then comparing the hashed password when the user tries to log in. If you're not familiar with these concepts, it might be best to use a pre-built solution like the Password provider in Convex Auth[^4^], which handles these security considerations for you.

^2^]: [ConvexCredentials (https://labs.convex.dev/auth/api_reference/providers/ConvexCredentials)
^4^]: [Password Provider (https://labs.convex.dev/auth/config/passwords)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@finite meadow kapa.ai is still learning and improving, please let us know how it did by reacting below

finite meadow
#

@manic inlet yes i don't want to encrypt password and let admin role create users with passwords so other user can login that's it. but i need sessions etc provide an example for that

manic inletBOT
#

Let me check the knowledge base for you. One moment! :books:

#

While it's strongly recommended to encrypt passwords for security reasons, if you still want to proceed with plain text passwords, you can use the ConvexCredentials provider for a custom authentication implementation. Here's a basic example:

import ConvexCredentials from "@convex-dev/auth/providers/ConvexCredentials";
import { convexAuth } from "@convex-dev/auth/server";
 
export const { auth, signIn, signOut, store } = convexAuth({
  providers: [
    ConvexCredentials({
      authorize: async (credentials, ctx) => {
        // Fetch user from your database
        const user = await ctx.db.query("users").withIndex("email", (q) => q.eq("email", credentials.email)).first();

        // Check if user exists and password matches
        if (user && user.password === credentials.password) {
          return { id: user._id, email: user.email, role: user.role };
        } else {
          throw new Error("Invalid credentials");
        }
      },
    }),
  ],
});

In this example, when a user tries to sign in, the authorize function is called with the provided credentials. It fetches the user from the database based on the email, then checks if the user exists and if the provided password matches the one stored in the database. If the credentials are valid, it returns the user's data. If not, it throws an error.

For session management, Convex provides a session middleware that you can use. Here's an example of how you can use it to persist user data:

#
export const set = mutationWithSession({
  args: { name: v.string() },
  handler: async (ctx, { name }) => {
    if (ctx.user) {
      await ctx.db.patch(ctx.user._id, { name });
    } else {
      await ctx.db.insert("users", { name, sessionId: ctx.sessionId });
    }
  },
});

In this example, when a user sets their name, it checks if the user already exists in the session. If they do, it updates the user's name. If not, it creates a new user with the provided name and the current session ID[^3^].

Please note that this approach has serious security implications and is not recommended for production applications.

^2^]: [ConvexCredentials (https://labs.convex.dev/auth/api_reference/providers/ConvexCredentials)
^3^]: [Anonymous Users via Sessions (https://stack.convex.dev/anonymous-users-via-sessions#storing-anonymous-users-in-the-users-table)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: