I have read that when you open a Django rendered page, Django automatically sends the “csrftoken” in client’s cookies and that if you are rendering a form via Django templates then just use the “{% csrftoken %}” tag to include in the request. But since i am going to be developing the front-end separately, i was just trying out the email authentication views before front-end development begins. But on sending the OTP i am getting this error:
Forbidden (CSRF cookie not set.): /register/
Forbidden (CSRF cookie not set.): /register/
[30/Jan/2025 12:49:34] "POST /register/ HTTP/1.1" 403 16353
On checking cookies in the browser, “csrftoken”, “sessionId” are not there. Why is cookie not being set ? Is it mandatory for the form to be django rendered ?
views.py (URL 127.0.0.1:8000):
def register(request):
if request.method == "POST":
# email = request.POST.get("email")
try:
# Parse the JSON body
data = json.loads(request.body)
email = data.get("email")
except json.JSONDecodeError:
return JsonResponse({"success": False, "message": "Invalid JSON format."})
try:
validate_email(email)
except ValidationError:
return JsonResponse({"success": False, "message": "Invalid email format."})
email_otp = generate_otp()
redis_key = f"otp:{email}"
cache.set(redis_key, email_otp)
try:
message = BaseEmailMessage(
template_name="emails/otp_template.html",
context={"email_otp": email_otp},
)
message.send([email])
except (BadHeaderError, SMTPException) as e:
return JsonResponse(
{"success": False, "message": f"Failed to send OTP. Error: {str(e)}"}
)
return JsonResponse(
{
"success": True,
"message": "OTP sent successfully. Please check your email.",
}
)
def verify_otp(request):
if request.method == "POST":
try:
# Parse the JSON body
data = json.loads(request.body)
email = data.get("email")
user_otp = data.get("otp")
except json.JSONDecodeError:
return JsonResponse({"success": False, "message": "Invalid JSON format."})
if not email or not user_otp:
return JsonResponse(
{"success": False, "message": "Email and OTP are required."}
)
redis_key = f"otp:{email}"
stored_otp = cache.get(redis_key)
if stored_otp is None:
return JsonResponse(
{"success": False, "message": "OTP expired or not found."}
)
if validate_otp(stored_otp, user_otp):
cache.delete(redis_key)
return JsonResponse(
{"success": True, "message": "OTP verified successfully."}
)
else:
return JsonResponse({"success": False, "message": "Invalid OTP."})
return JsonResponse({"success": False, "message": "Invalid request method."})
urls.py:
from django.urls import path
from django.views.generic import TemplateView
from . import views
urlpatterns = [
path("", TemplateView.as_view(template_name="core/index.html")),
path("register/", views.register, name="register"),
path("verify_otp/", views.verify_otp, name="verify_otp"),
]
settings.py:
CSRF_TRUSTED_ORIGINS = [
"http://127.0.0.1:8001",
"http://localhost:8001",
]
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = ["http://127.0.0.1:8001", "http://localhost:8001"]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
h.html (URL: 127.0.0.1:8001/h.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register and Verify OTP</title>
</head>
<body>
<h1>Register</h1>
<!-- Email Form -->
<form id="registerForm">
<label for="email">Email: </label>
<input type="email" id="email" name="email" required>
<button type="submit">Send OTP</button>
</form>
<!-- OTP Verification Form (Initially hidden) -->
<div id="otpForm" style="display: none;">
<h2>Enter OTP</h2>
<form id="verifyOtpForm">
<label for="otp">OTP: </label>
<input type="text" id="otp" name="otp" required>
<button type="submit">Verify OTP</button>
</form>
<div id="otpMessage"></div>
</div>
<div id="errorMessage" style="color: red;"></div>
<script>
// Function to get CSRF token from cookies
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== "") {
const cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie("csrftoken");
console.log(csrftoken);
// Handle email registration form submission
document.getElementById("registerForm").addEventListener("submit", function(event) {
event.preventDefault(); // Prevent form submission
let email = document.getElementById("email").value;
fetch("http://127.0.0.1:8000/register/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrftoken, // Include CSRF token in the headers
},
credentials: "include",
body: JSON.stringify({ email: email }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Show OTP form on successful OTP sent
document.getElementById("otpForm").style.display = "block";
document.getElementById("errorMessage").textContent = ""; // Clear any previous error messages
} else {
// Show error message if OTP wasn't sent successfully
document.getElementById("errorMessage").textContent = data.message;
}
})
.catch(error => {
console.log(error);
document.getElementById("errorMessage").textContent = "An error occurred while sending OTP.";
});
});
// Handle OTP verification form submission
document.getElementById("verifyOtpForm").addEventListener("submit", function(event) {
event.preventDefault(); // Prevent form submission
let email = document.getElementById("email").value;
let otp = document.getElementById("otp").value;
fetch("http://127.0.0.1:8000/verify_otp/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrftoken, // Include CSRF token in the headers
},
credentials: "include",
body: JSON.stringify({ email: email, otp: otp }),
})
.then(response => response.json())
.then(data => {
const otpMessageDiv = document.getElementById("otpMessage");
if (data.success) {
otpMessageDiv.style.color = "green";
otpMessageDiv.textContent = data.message;
} else {
otpMessageDiv.style.color = "red";
otpMessageDiv.textContent = data.message;
}
})
.catch(error => {
document.getElementById("otpMessage").textContent = "An error occurred during OTP verification.";
});
});
</script>
</body>
</html>