#Calling a mutation after the second stage of OTP auth.

8 messages · Page 1 of 1 (latest)

sonic onyx
#

Is it possible to trigger a mutation after an email OTP code is verified without going to the client again and have it happen entirely in the one auth flow?

rancid sapphireBOT
#

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

#

Based on the knowledge sources, you can use the afterUserCreatedOrUpdated callback to trigger additional operations after a user is authenticated with OTP. This callback runs in a mutation context and allows you to perform additional database operations.

Here's how you can implement this:

import { convexAuth } from "@convex-dev/auth/server";
import { ResendOTP } from "./ResendOTP";
import { Password } from "@convex-dev/auth/providers/Password";

export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
  providers: [Password({ verify: ResendOTP })],
  callbacks: {
    async afterUserCreatedOrUpdated(ctx, { userId }) {
      // Perform additional database operations here
      await ctx.db.insert("someTable", { userId, data: "some data" });
      
      // Or schedule an action to run immediately after this transaction completes
      // if you need to perform side effects like API calls
      ctx.scheduler.runAfter(0, internal.yourNamespace.yourAction, { userId });
    },
  },
});

It's important to note that this callback runs in a mutation context, so you cannot directly call actions from it. If you need to perform side effects like API calls, you should schedule an action to run after the transaction completes using ctx.scheduler.runAfter() as shown above.

The callback will be triggered after the OTP verification is successful and the user is created or updated in the database, all within the same authentication flow.

Auth Advanced Details

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

#

@sonic onyx Kapa.ai is still learning and improving, please let me know how I did by reacting below.

sonic onyx
#

But it needs to happen ONLY after the verification step, won’t afterusercreatedorupdated run during both steps @rancid sapphire ?

rancid sapphireBOT
#

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

#

You're right to be concerned about when the callback runs. According to the documentation, the afterUserCreatedOrUpdated callback will only be triggered after the verification step is complete, not during both steps of the OTP flow.

From the API reference:

This callback is called during the sign-in process, after the user is created or updated, before account creation and token generation.

For OTP verification specifically, the callback will be called with args.type set to "verification" when it's triggered after an email or phone token verification:

args.type: "oauth" | "credentials" | "email" | "phone" | "verification"

Where "verification" indicates "this callback is called after an email or phone token verification" API Reference.

If you want to ensure your code only runs after the verification step, you can check the type parameter in your callback:

callbacks: {
  async afterUserCreatedOrUpdated(ctx, args) {
    // Only run after verification step
    if (args.type === "verification") {
      // Your code here
      await ctx.db.insert("someTable", { userId: args.userId, data: "verified user" });
      
      // Or schedule an action
      ctx.scheduler.runAfter(0, internal.yourNamespace.yourAction, { userId: args.userId });
    }
  },
}

This way, your code will only execute after the verification step is complete, not during the initial OTP sending step.

Note that if you're using a custom createOrUpdateUser callback, the afterUserCreatedOrUpdated callback won't be called at all, as mentioned in the documentation: "This callback is only called if createOrUpdateUser is not specified."

#

Would you like more information about handling the verification flow?

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