Authentication system in the forum application #3: Generate token and Email configuration

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@duski.harahap·
0.000 HBD
Authentication system in the forum application #3: Generate token and Email configuration
#### Repository
https://github.com/python

#### What Will I Learn?
- Generate token when signing up
- Email configuration and email templates

#### Requirements
- Basic Python
- Install Python 3
- Install Django


#### Resources
- Python - https://www.python.org/
- Django- https://www.djangoproject.com/
- Bootstrap 4 - https://getbootstrap.com/docs/4.0/getting-started/introduction/
- http://ana-balica.github.io/2015/01/29/pagination-in-django/

#### Difficulty
Basic

### Tutorial Content

Hi all, this tutorial is still continuing the previous tutorial about authentication in our forum application. In this tutorial, I will make our authentication system safer. Because in this tutorial we will generate tokens when we have signed up. In the previous tutorial, we have created a new model, namely the ***profile*** that we will use to set up user accounts and associate them with the *authentication system* that is being created. Okay, we just start our tutorial this time.

### Generate token

The first part we will create is generated the token when the user is signing up. For that, we can create a file that we will use to store the generic system. I will create a file with the name **token.py** in the ***account*** folder. We can see the example below:

**account/token.py**

```
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six

class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
	def _make_hash_value(self, user, timestamp):
		return (
			six.text_type(user.pk) + six.text_type(timestamp) +
			six.text_type(user.username)
		)

account_activation_token = AccountActivationTokenGenerator()
```

- Django has *provided* a function to **generate tokens**. to use it we can import  ```django.contrib.auth.tokens``` module and can use the ```PasswordResetTokenGenerator()``` function to generate tokens ```from django.contrib.auth.tokens import PasswordResetTokenGenerator```.

- Then we can create a class to create a password generating system. In this class we will pass the *PasswordResetTokenGenerator* function as a parameter ```class AccountActivationTokenGenerator(PasswordResetTokenGenerator):```.

- To do hashing we can create a function ```def _make_hash_value(self, user, timestamp)``` in the ```class AccountActivationTokenGenerator()```. In this function ```_make_hash_value``` we have **3 parameters**. ***The first parameter*** is ```self``` that we will use to be able to access properties in this class. ***The second parameter*** is the user, the user is the user model and ***The third parameter*** is the timestamp that we will use for additional when generating tokens.

- The result of hashing is a combination of 3 elements:
```six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(user.profile.email_validated)```.
**user.pk** = *primary key* of the user model.
**timestamp** = This is time stamp.
**user.username** = This is username of user.
<br>
- **Displays the generated token**

We have created the *generate token system* that we have created in the **token.py** file. To test whether the system is successful or not, then we can print out the generated token, we will use the token in the ```SignUp()``` function, for more details we can see example below:

**account/views.py**

```
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.urls import reverse, reverse_lazy
from django.views import generic
from django.contrib import messages
from .forms import SignUpForm
from .token import account_activation_token

def SignUp(request):
	if request.method == 'POST':
		form = SignUpForm(request.POST)
		if form.is_valid():
			user  = form.save()
			user.is_active = False
			user.save()
			token = account_activation_token.make_token(user)
			return render(request, 'signup.html', {'signupForm' : form, 'token': token})
	else:
		formClass = SignUpForm
		return render(request, 'signup.html', {'signupForm' : formClass})
```

- to use the function that we have created on token.py we can import it as follows ```from .token import account_activation_token```. **account_activation_token** is the name of the variable that we created in token.py, for more details we can see the picture below:

![Screenshot_8.png](https://ipfs.busy.org/ipfs/Qmbhyybm6FKGiPGuu8ebddah68qZe6zpUo5js9Tv3A4RY6)

- If the user does the post method ```if request.method == 'POST':```, we will save the form ```user  = form.save()```. The first time we save the user we will ***make is_active is false*** ```user.is_active = False```.

- We can use the ```to_make (user)``` function to print out the token that we have generated. We need one parameter to generate. In this function, we will use the *user as parameters.*

- I will pass the token as a parameter that will be rendered by signup.html, we can pass the token parameters like this ```return render(request, 'signup.html', {'signupForm': formClass, 'token': token})```.

- We have passed the variable token in the signup.html template now we can render the variable in the template. for more details, we can see the code below:

**account/templates/signup.html**

```
{% extends "base.html" %}

{% block title %} Sign Up{% endblock %}

{% block content %}
<h2>Sign Up</h2>
<form method="post">
	{% csrf_token %}
	<p>Token : {{token}}</p>
	{{ signupForm.as_p }}
	<button type="submit" name="button">Register</button>
</form>

{% endblock%}
```
- We can render the variable as follows ```<p> Token: {{token}} </ p>```. If it's finished we can see the results like the following:

![ezgif.com-video-to-gif.gif](https://cdn.steemitimages.com/DQmNi56v8MfogGaKPyEHm8r5pkN9t8KkPGtfsirCMvKeyKd/ezgif.com-video-to-gif.gif)

### Email configuration

In the previous section, we have successfully generated the token after signing up and then displaying the token on the signup page. but that is not our real goal, displaying tokens just to see if we have successfully generated it. Our main task is to send a ***verification email*** to the user that contains the token. But before making it there are several *configurations* and *preparations* that we must do first.

- **Use ```email_user()``` function**

As I discussed in the previous tutorial, we will use the ```email_user ()``` function to send an email to the user. In this function we need ***2 parameters***. **The first** is the *subject* and **the second** is the *message.*

```
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib.auth import update_session_auth_hash
from django.urls import reverse, reverse_lazy
from django.views import generic
from django.contrib import messages
from .forms import SignUpForm
from .token import account_activation_token
//import new function
from django.utils.http import urlsafe_base64_encode
from django.contrib.sites.shortcuts import get_current_site

def SignUp(request):
	if request.method == 'POST':
		form = SignUpForm(request.POST)
		if form.is_valid():
			user  = form.save()
			user.is_active = False
			user.save()
			token = account_activation_token.make_token(user)
			# Send email
			subject = "Activate your account from email"
			message = render_to_string('activation_email.html',
				'user' : user,
				'domain' : get_current_site(request).domain,
				'uid' : urlsafe_base64_encode(force_byte(user.pk)),
				'token' : token
			)
			user.email_user(subject, message)
	else:
		formClass = SignUpForm()
		return render(request, 'signup.html', {'signupForm' : formClass})
```

- The *first* we will make a **subject**. the subject here is the subject of the email we will send. We make a subject with our wishes, here I will make the subject as follows ```subject = "Activate your account from email"```.

- The *second* is **message**. The message here is the *content* of the email we will send. In the message I will pass a template and variable to use in the template, for that I will use the ```render_to_string ()``` function.

- In ```render_to_string ()```  function. In the ```render_to_string ()``` function, we will pass ***two parameters***. ***The first parameter** is the template we will use in the email content and **The second parameter*** *is the variable we will render in the template*.

**The first parameter** is ```activation_email.html```. This is the template we will render. we will create this template in another section.

**The second parameter** is the **variable** that we will render on template ```activation_email.html```. The variable that we oper is a form of the object containing the ***key*** and ***value***.

```'user'``` is the *key* and the ```user``` is the *value* we get when we store user data ```user.save()```.

```'domain'``` is the *key* and its *value* is a **domain name**. To get our domain name, we can use the Django function. That is ```get_current_site()```. to use this function we must import it first like this ```from django.contrib.sites.shortcuts import get_current_site```.  For more details we can see in the picture below below

![Screenshot_9.png](https://cdn.steemitimages.com/DQmaAKNq17XSGD2qkjxrCvkcTHLnnNH1nnPtv71WDbnaccG/Screenshot_9.png)

```'uid'``` is the *key* and the *value* is an encryption of the primary key ```user.pk```. So the idea is that I will *pass* a **unique ID(uid)** in that email. to encrypt we can use the Django function, namely the base64 method ```urlsafe_base64_encode()```, to use it we must import it first like the following ```from django.utils.http import urlsafe_base64_encode```. 

```'token'``` is the *key* and the value we can get from the variable ```token``` that we have made in the previous section ```token = account_activation_token.make_token(user)```.

And finally, I will send the email using ```email_user ()``` and pass the parameters we have created ```user.email_user(subject, message)```. For now, I think we have enough for the preparation and configuration of the email, in the next section, we will see the results of the email sent.



### Curriculum

- **Forum app**

[django#1](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-1-init-projects-and-dependencies-and-database-schema-1551711163679), [django#2](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-2-template-system-and-class-based-view-implementation-1552057536737), [django#3](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-3-base-template-login-and-register-system-1552311993977), [django#4](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-4-admin-dashboard-ang-setting-redirect), [django#5](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-5-slug-concept-and-generated-slug-and-use-forms-generic-view), [django#6](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-6-crud-system-and-url-protection-redirect-system), [django#7](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-7-unique-slug-and-manage-modules-in-admin-dashboard-1553268749861), [django#8](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-8-display-forum-data-and-create-and-implement-list-view-1553525769014),  [django#8](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-8-display-forum-data-and-create-and-implement-list-view-1553525769014),  [django#9](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-9-single-page-for-forums-passing-params-in-routing-and-make-time-humanize-1553788983186),  [django#10](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-10-detail-page-for-forums-use-slug-as-the-parameter-url-and-implement-getcontextdata),  [django#11](https://steemit.com/utopian-io/@duski.harahap/create-a-forum-application-using-django-11-url-behavior-and-update-view-and-edit-menu-1554268753908)


#### Proof of work done

https://github.com/milleaduski/forums-django
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,