Search code examples
django-rest-frameworkdjoser

Stop djoser from adding API url to the frontend url set in PASSWORD_RESET_CONFIRM_URL


I have a DRF API using djoser to handle password reset. The password reset workflow is working well except for the PASSWORD_RESET_CONFIRM_URL

When I set my frontend page URL in that setting for Djoser it keeps concatenating the API URL to the frontend page URL. How can I stop that

for more context here are my Djoser settings showing the URL I set for PASSWORD_RESET_CONFIRM_URL

DJOSER = {
    'PASSWORD_RESET_CONFIRM_URL': 'http://localhost:3000/auth/confirm-password-reset/{uid}/{token}',
    'ACTIVATION_URL': '#/activate/{uid}/{token}',
    'SEND_ACTIVATION_EMAIL': True,
    'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': True,
    'PASSWORD_RESET_CONFIRM_RETYPE': True,
    'SERIALIZERS': {
        'password_reset': 'djoser.serializers.SendEmailResetSerializer',
        'password_reset_confirm': 'djoser.serializers.PasswordResetConfirmSerializer',
        'password_reset_confirm_retype': 'djoser.serializers.PasswordResetConfirmRetypeSerializer',
        'set_password': 'djoser.serializers.SetPasswordSerializer',
        'set_password_retype': 'djoser.serializers.SetPasswordRetypeSerializer',
        'current_user': 'djoser.serializers.UserSerializer',
    },
    'PERMISSIONS': {

    }
}


and here is the URL I receive in my email

email screenshot

as you can see http://127.0.0.1:8000 the API URL has been added to the frontend URL I set


Solution

  • There appear to be two ways to set a new DOMAIN name explicitly:

    1. Add a DOMAIN and SITE_NAME to the Django settings
    2. Use the Django Sites framework and set the domain name there

    Sites isn't often useful, so use #1 unless something else fails. The only other option is overriding all email templates so you can specify the full url.


    1. Djoser only supports paths/fragments, not full urls
    2. Links are created using {{ protocol }}://{{ domain }}/{{ url|safe }}
    3. A package called templated_mail is used to send these emails
    4. That package sets the protocol, domain and site_name

    The code for setting the variables for use in the email template is:

    site = get_current_site(self.request)
    domain = context.get('domain') or (
        getattr(settings, 'DOMAIN', '') or site.domain
    )
    protocol = context.get('protocol') or (
        'https' if self.request.is_secure() else 'http'
    )
    site_name = context.get('site_name') or (
        getattr(settings, 'SITE_NAME', '') or site.name
    )
    

    The http vs https decision is made for you, but since those are almost always the same its probably not an issue in practice.