How to configure email confirmation redirection URL dynamically?

Hi,
I’m trying to setup the email confirmation workflow to work well across multiple environments. (production, staging and locally)

When the confirmation email is sent it uses the URL environment variable to compose the confirmation URL, which upon being “GETed” confirms the User and redirects with 302 to the “redirection URL”.

The redirection URL can be configured in Admin Panel > Settings > Users & Permissions plugin > Advanced settings > Redirection url.

However it seems that it can only be hard-coded and since I’m running Strapi in multiple environments which each has its own frontend URL I need to set this redirection URL dynamically per environment.

Some solutions I considered:

  1. Setting the redirection URL once per enviornment manually from within the Admin Panel is not an option for me as I’m tracking the Strapi config in git with the config-sync plugin and the URL would get overwritten with every sync.
  2. The Redirection url can be set as relative. Then it will use the domain from the URL variable. The problem is that I’m running the backend and frontend on separate domains. I.e. the Strapi backend runs on api.domain.com and the website where I actually want to redirect to run on domain.com.

Is there any way to template the redirection URL with environment variables? Or maybe intercept the confirmation URL response and override the redirection URL myself?

PS: this analogically applies to the password reset workflow.
PS2: I already asked this on Discord but got no answers.

Thanks and all the best!

2 Likes

Hi @goodhoko

I’ve looked into it and I think there’s a solution, although it involves a lot more work that it should be needed.

TLDR;

Re-doing the register method with almost a copy-paste to be able to call your own sendConfirmationEmail method that can be (again) almost a copy-paste but getting the URL from the environment.

I uploaded an example here.

  • env.example :arrow_right: has the CALLBACK_URL value. If you are using env file you can place it there. For dev purposes I also uploaded the VS Code’s launch.json file where the environment variables can also be placed.

  • src/api/utils/services/email.js :arrow_right: a new sendConfirmationService has been created. It’s almost the same as the original one but uses process.env.CALLBACK_URL for the URL.

  • src/extensions/user-permissions/strapi.server.js :arrow_right: a new register method overriding the original one. It’s almost the same as the original one but calls await strapi.service(‘api::utils.email’).sendConfirmationEmail(sanitizedUser);.

:point_down:t2: Here some insights as to why I solved it that way

First, the method responsible for sending the email is the sendConfirmationEmail inside @strapi/plugin-users-permissions/server/services/user.
Inside that method you can (at least currently in Strapi version 4.4.3) find this code where you can see the URL being almost hardcoded:

const apiPrefix = strapi.config.get('api.rest.prefix');
    settings.message = await userPermissionService.template(settings.message, {
      URL: urlJoin(getAbsoluteServerUrl(strapi.config), apiPrefix, '/auth/email-confirmation'),
      SERVER_URL: getAbsoluteServerUrl(strapi.config),
      ADMIN_URL: getAbsoluteAdminUrl(strapi.config),
      USER: sanitizedUserInfo,
      CODE: confirmationToken,
    });

So, my first thought would’ve been to override the whole sendConfirmationEmail method following the Plugins Extensions documentation, but I’ve taken a look at what register method does in @strapi/plugin-users-permissions/server/controllers/auth and it gets the sendConfirmationEmail function on the fly, so even if overridden it will still call the original function:

 if (settings.email_confirmation) {
      try {
        await getService('user').sendConfirmationEmail(sanitizedUser);
      } catch (err) {
        throw new ApplicationError(err.message);
      }

      return ctx.send({ user: sanitizedUser });
    }
4 Likes

Thanks so much for this, you’ve made my day!

1 Like

I’m following the same approach , unfortunately it is not working
in addition i need to add user’s role to the link in the confirmation email

Hello, I am the same problem, really is posible, did you can do it?

You saved my life you good captain. @mancku

1 Like

I can assure you the method still works. I’m using it in a project in Strapi 4.24

1 Like