I’m developing a web application with Angular for the frontend and Django for the backend. I’ve set up a Django REST API using Django REST framework to allow users to change their passwords. However, I’m encountering two main issues:
Forbidden (403) for /api/change_password/
: When trying to change the password via /api/change_password/
, I’m getting a Forbidden (403) error.
Backend Code:
views.py
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth import update_session_auth_hash
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from accounts.serializers import ChangePasswordSerializer
@method_decorator(login_required, name='dispatch')
class ChangePasswordView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
serializer = ChangePasswordSerializer(data=request.data)
if serializer.is_valid():
user = request.user
if not user.check_password(serializer.data.get('old_password')):
return Response({"old_password": "Wrong password."}, status=status.HTTP_400_BAD_REQUEST)
if serializer.data.get('new_password') != serializer.data.get('new_password_confirm'):
return Response({"new_password": "Password mismatch."}, status=status.HTTP_400_BAD_REQUEST)
user.set_password(serializer.data.get('new_password'))
user.save()
update_session_auth_hash(request, user)
return Response({"message": "Password changed successfully"}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls.py
from django.urls import path
from accounts import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/signup/', views.UserCreate.as_view(), name='signup'),
path('api/login/', views.login_view, name='login'),
path('api/logout/', views.logout_view, name='logout'),
path('api/csrf/', views.csrf, name='csrf'),
path('api/change_password/', views.ChangePasswordView.as_view(), name='change_password'),
]
Frontend Code:
accounts.service.ts (Angular)
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AccountsService {
private baseUrl = 'http://127.0.0.1:8000/api/';
private csrfToken: string | null = null;
constructor(private http: HttpClient) { }
private loadCsrfToken(): Observable<string> {
return this.http.get<any>(`${this.baseUrl}csrf/`).pipe(
switchMap((data: any) => {
this.csrfToken = data.csrfToken;
return [data.csrfToken];
}),
catchError((error: HttpErrorResponse) => {
console.error('Error loading CSRF token:', error.message);
return throwError(error);
})
);
}
private getHeaders(): HttpHeaders {
let headers = new HttpHeaders().set('Content-Type', 'application/json');
if (this.csrfToken) {
headers = headers.set('X-CSRFToken', this.csrfToken);
}
const token = this.getToken();
if (token) {
headers = headers.set('Authorization', `Bearer ${token}`);
}
return headers;
}
changePassword(oldPassword: string, newPassword: string, newPasswordConfirm: string): Observable<any> {
return this.loadCsrfToken().pipe(
switchMap(() => {
return this.http.post<any>(
`${this.baseUrl}change_password/`,
{ oldPassword, newPassword, newPasswordConfirm },
{ headers: this.getHeaders() }
);
}),
catchError((error: HttpErrorResponse) => {
console.error('Error changing password:', error);
return throwError(error);
})
);
}
}
Forum Question:
403 (Forbidden) errors for /api/change_password/
in my Django/Angular application. I’ve checked my views and URLs, and it seems like permissions and CSRF tokens are correctly configured. What could be causing these errors, and how can I resolve them?
user23298973 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.