3
votes

Am using Djoser for authentication in my project. Have been struggling to add email activation for over 4 days now but seems have failed to grab it fine as the documentation is a little hard for me to understand.

This is my code settings.py

#change auth model to custom model
AUTH_USER_MODEL = 'userauth.User'

#setting up email server
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'codemanuzmaster'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = '[email protected]'

#djoser login settings
DJOSER = {
    'DOMAIN': 'localhost:8000',
    'SITE_NAME': 'net',
    'LOGIN_FIELD':'email',
    'USER_CREATE_PASSWORD_RETYPE':True,
    'ACTIVATION_URL': '#/users/activate/{uid}/{token}',
    'SEND_ACTIVATION_EMAIL': True,
    'SERIALIZERS':{
        'user_create':'userauth.serializers.UserCreateSerializer',
        'user':'userauth.serializers.UserCreateSerializer',
        'activation': 'djoser.email.ActivationEmail',
    }
}

here is the email i receive after creating user

http://example.com/auth/users/activate/MQ/5c9-26bcab9e85e8a967731d

It shows example.com but i want it to change the web url to localhost:8000 instead

You're receiving this email because you need to finish activation process on example.com.

Please go to the following page to activate account:

http://example.com/auth/users/activate/MQ/5c9-26bcab9e85e8a967731d

And if i change the web url manually to

http://127.0.0.1:8000/users/activate/MQ/5c9-26bcab9e85e8a967731d

it keeps returning

{
    "detail": "Authentication credentials were not provided."
}

I really request you people to help me.

2
What is your DRF settings?JPG
Did you get it workin, I am also getting "Authentication credentials were not provided." currently, not knowing why. But I will look into it and can probably share a solution soon.Rik Schoonbeek

2 Answers

2
votes

To answer your original question (How to use a different domain for the activation url), you need to remove DOMAIN and SITE_NAME from the Djoser settings. Example:

DOMAIN = config('DOMAIN') #localhost:8000
SITE_NAME = config('SITE_NAME') #net

DJOSER = {
    'LOGIN_FIELD':'email',
    'USER_CREATE_PASSWORD_RETYPE':True,
    'ACTIVATION_URL': '#/users/activate/{uid}/{token}',
    'SEND_ACTIVATION_EMAIL': True,
    'SERIALIZERS':{
        'user_create':'userauth.serializers.UserCreateSerializer',
        'user':'userauth.serializers.UserCreateSerializer',
        'activation': 'djoser.email.ActivationEmail',
}

Then you should get the next link in your email:

http://localhost:8000/auth/users/activate/MQ/5c9-26bcab9e85e8a967731d
0
votes

I've got it working using this SO answer: https://stackoverflow.com/a/47159919/8110396

I may be explaining things you already understand, but it may help others see the flow of how this goes.

Looking at the Djoser docs on User Activation, it says that "this endpoint is not a URL which will be directly exposed to your users",

This means that the link that is used is not given to the person registering, the link you get in the email needs to activate some code that will perform the call to the Django view that will activate the user's email.

I guess you can do this both from the Frontend, where some JavaScript, using fetch/axios, will call the email activation view. But it can also be done by having a Django view contain code that will call the email activation view.

So basically, the email link will trigger code (JS/Python) that will send a http post request to a Django view.

I don't know what the best choice is, but this solution will all go through Django.

The basic flow is this:

1 User registers

2 The user is send an email with a URL, this has two important pieces of info we need, the uid and token.

How this URL in the email is formed can be changed by the ACTIVATION_URL setting: "ACTIVATION_URL": "auth/request_activate/{uid}/{token}", in my case.

/{uid}/{token} means that we can use the uid and token in the view that the link leads to.

3 This link leads to a Django view that does the user activation

views.py:

from rest_framework import permissions
from rest_framework.decorators import (
    api_view,
    permission_classes,
)
from rest_framework.response import Response
from rest_framework.views import APIView

import requests


@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def request_user_activation(request, uid, token):
    """ 
    Intermediate view to activate a user's email. 
    """
    post_url = "http://127.0.0.1:8000/djoser_auth/users/activation/"
    post_data = {"uid": uid, "token": token}
    result = requests.post(post_url, data=post_data)
    content = result.text
    return Response(content)

As you can see the view function receives uid and token as arguments, which are then send in a POST request to the actual (Djoser) view, using the requests library.

post_url created here is the one mentioned in the Djoser docs as the Default URL for email activation: /users/activation/ (you may find older urls /users/activate/, don't use that, won't work ;)).

Mind that I have djoser_auth in my url, where the default is just auth, not going to dive into why that is, but here's my main urls.py:

from django.urls import include, path


urlpatterns = [
    ...
    path("auth/", include("authentication.urls")),
    ...
    path("djoser_auth/", include("djoser.urls")),
    path("djoser_auth/", include("djoser.urls.jwt")),
]

And my settings.py:

DJOSER = {
    "ACTIVATION_URL": "auth/request_activate/{uid}/{token}",
    "SEND_ACTIVATION_EMAIL": True,
    "SERIALIZERS": {},
    "USER_CREATE_PASSWORD_RETYPE": True,
}

So, using this you should be able to click the link in the email, and that your user has the is activated checkbox checked in the admin.

enter image description here