I'm building a basic app with login, register, etc. now i try finish the login using Django like backend and fronted with Angular, but i can't end my login because this error, when i try login with the correct credentials and redirect to new page or url show this error.
TypeError at /doctor
'list' object is not callable"in network panel"
service .ts
constructor(private http: Http, private httpClient: HttpClient) { }
private headers = new Headers({ 'Content-Type': 'application/json' });
getDoctores(): Promise<Doctor[]> {
return this.http.get(this.baseurl + '/doctor?format=json', { headers: this.headers })
.toPromise()
.then(response => response.json() as Doctor[])
}
component .ts
constructor(private dataService: dataService, public dialog: MatDialog,
private router: Router) {
this.getDoctores();
this.selectedDoctor = {
id: -1, nombreDoc: '', apellidoDoc: '', rutDoc: '', direccionDoc: ''
, telefonoDoc: '', release_date: ''
}
}
getDoctores(): void {
this.dataService
.getDoctores()
.then(doctores => this.doctores = doctores);
}
url.py
path('auth/login/', obtain_jwt_token),
path('auth/refresh-token/', refresh_jwt_token),
url(r'^doctor$', views.DoctorList.as_view()),
url(r'^doctor/(?P<pk>[0-9]+)$', views.DoctorDetail.as_view()),
view.py
class DoctorList(generics.ListCreateAPIView):
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
class DoctorDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
Related
I am authenticating user with http only cookies which contains jwt tokens.
Heres all my settigns require to use cookies.
settings.py
CORS_EXPOSE_HEADERS = ["Content-Type", "X-CSRFToken"]
CORS_ALLOW_CREDENTIALS = True
# CORS_ALLOW_HEADERS = ["Set-Cookie",]
SESSION_COOKIE_SAMESITE = "Lax"
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = "None"
CSRF_COOKIE_SECURE = True
CSRF_TRUSTED_ORIGINS = ["http://localhost:3000", "http://127.0.0.1:3000"]
'ACCESS_TOKEN_LIFETIME': timedelta(days=2),
'REFRESH_TOKEN_LIFETIME': timedelta(days=10),
# HTTPOnly Cookies
"AUTH_COOKIE": "access_token",
"AUTH_COOKIE_REFRESH": "refresh_token",
"AUTH_COOKIE_SAMESITE": "None",
"AUTH_COOKIE_SECURE": True,
"AUTH_COOKIE_HTTP_ONLY": True,
"AUTH_COOKIE_PATH": "/",
"AUTH_COOKIE_DOMAIN": None,
axios.js
import axios from "axios";
import { BASE_URL_BACK_SERVER } from "./_variables";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.withCredentials = true;
export const axiosInstanceBack = axios.create({
baseURL: BASE_URL_BACK_SERVER,
timeout: 5000,
headers: {
"Content-Type": "application/json",
},
});
Authenticating user working fine but the problem is when logging out user.
when it makes request for LogoutView it return 200 response.
But after redirecting in frontend again fetches current user which should be available if only user is logged in. When checked to network tab i found that request header for current user's details contain same cookies. Why is that happening? am i missing something here?
LogoutView
class LogoutView(APIView):
def post(self, request):
response = Response()
response.delete_cookie(settings.SIMPLE_JWT['AUTH_COOKIE'])
response.delete_cookie(settings.SIMPLE_JWT['AUTH_COOKIE_REFRESH'])
response.data = {
"status": "success",
"msg": "User logout successfully"
}
return response
logout Request
const logoutUser = () => {
axiosInstanceBack
.post("user/logout/", {}, { headers: { "X-CSRFToken": csrfToken } })
.then((response) => {
mutateCsrf();
setShouldFetch(false);
mutate("user/current/", null, { revalidate: false });
router.push("/login");
})
.catch((error) => console.log(error));
};
views.py
class DeviceView(viewsets.ModelViewSet):
serializer_class = DevicesSerializer
queryset = Devices.objects.all()
permission_classes = [permissions.IsAuthenticated]
Axios Request
axios.delete(`api/devices/${data.id}/`, {}, {
headers: {'X-CSRFToken': csrftoken }
})
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
When I carry out this request on my front-end, I get a response of :"DELETE http://localhost:3000/api/devices/4/ 403 (Forbidden)". Where 4 is the ID belonging to the record I would like to delete.
I am currently using Session Authentication in Django and I have passed in my CSRF Token value into the header of my request.
When I use other methods like PUT and POST on forms, they work fine. But, not DELETE
What am I doing wrong to receive this error?
Turns out I just needed to remove the empty body in the Axios request.
axios.delete(`api/devices/${data.id}/`, {
headers: {'X-CSRFToken': csrftoken }
})
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
I have my backend in Django and front in Vue.
A user performes login in Vue and via a POST request the creds are sent to a Django JWT login endpoint. This endpoint returns a token which is set in localStorage.
Then I want to check in Vue that the user is logged in. For that another endpoint in Django exists. However, it always returns "AnonymUser". I cannot get how to set this check.
Django:
My settings.py
JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
My urls.py
path('check-auth', views.check_if_logged_in, name="check-auth"), # check auth
path('auth/obtain_token', obtain_jwt_token), # obtain token
path('auth/refresh_token', refresh_jwt_token),
My views.py
# Login Check
#csrf_exempt
def check_if_logged_in(request):
authentication_class = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
print(request.user) # returns AnonymUser
check = None
if request.user.is_authenticated:
check = True
else:
check = False
print(check) # returns False
return HttpResponse(f"<html><body>{check}</body></html>")
Vue
obtainToken function
obtainToken(){
var that = this;
fetch(this.endpoints.obtainJWT, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: that.django.username,
password: that.django.password
})
}).then(response => response.json()
).then(function(response) {
console.log('auth', response); # get token
that.updateToken(response.token); # update localStorage
that.checkAuthData(); #check auth
});
},
checkAuth function
checkAuthData: function() {
var that = this;
fetch('http://localhost:8000/check-auth', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: this.jwt # send token
})
}).then(response => response.json()
).then(function(response) {
console.log('check', response);
});
},
You should include token not in the body, but in the header instead:
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.jwt
},
Also, please make sure that in your Django settings in REST_FRAMEWORK DEFAULT_AUTHENTICATION_CLASSES contains JWT authentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
]
}
I've read the duplicates and nothing seems to be working. I can do the put request directly from the form in the url but I can't seem to get the axios request working.
I tried:
CSRF with Django, React+Redux using Axios
https://gist.github.com/paltman/490049a64fa4115a2cea
my view.py:
class FrequencyList(generics.ListCreateAPIView):
queryset = Frequency.objects.all()
serializer_class = FrequencySerializer
class FrequencyDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Frequency.objects.all()
serializer_class = FrequencySerializer
My axios request:
axios({
method: 'put',
url: '/f/'+id,
data: {
item: item,
},
}).then(function (response) {
this.setState({needReceipt: true});
})
.catch(function (error) {
console.log(error);
});
In my settings.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
}
in my webpack.config.dev.js:
const axios = require('axios');
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.xsrfCookieName = "csrftoken";
try this
axios.put('/f/'+id, { item: item })
.then(function(response){
this.setState({needReceipt: true});
});
Reference
I've been looking all around for session based authentication with Angular 2.
I'm building an application that has Django on backend and Angular 2 on the frontend. To keep the process simple I'm trying to implement Django session authentication.
// Angular 2 authentication service
import { Injectable } from "#angular/core";
import { Headers, Http, Response } from "#angular/http";
import "rxjs/add/operator/toPromise";
import 'rxjs/add/operator/map'
import { AppSettings } from "../../app.settings";
#Injectable()
export class UserAuthService {
private headers = new Headers({'Content-Type': 'application/json'});
private loginUrl = `${AppSettings.BACKEND_URL}` + '/api/v1/users/login/';
constructor(
private http: Http
) { }
login(username, password) {
let data = {
username: username,
password: password
};
return this.http.post(this.loginUrl, data, this.headers)
.map((response: Response) => response.json());
}
}
# Django Login view
def login(self, request):
username = request.data['username']
password = request.data['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
serializer = self.serializer_class(user)
return Response(serializer.data, status=status.HTTP_200_OK)
raise AuthenticationFailed
I'm successfully calling backend API and my login view returns the successful response.
Also request.user gets updated after the login but when I try to call the other APIs using Angular or directly browse Django rest API user is not logged in.
The answer to this question is to append CSRF token to the X-CSRF header, because django uses X-CSRF token header to verify the sessions.
I don't exactly remember where I saw this but Iachieved this by using angular2-cookie and writing a custom request options service like this
// Custom request options service
import { CookieService } from "angular2-cookie/services/cookies.service";
import { Headers, RequestOptions } from "#angular/http";
import { Injectable } from "#angular/core";
#Injectable()
export class CustomRequestOptionsService {
constructor(
private cookieService: CookieService
) { }
defaultRequestOptions() {
return new RequestOptions({
headers: new Headers({
'Content-Type': 'application/json',
}),
withCredentials: true
});
}
authorizationRequestOptions() {
return new RequestOptions({
headers: new Headers({
'Content-Type': 'application/json',
'X-CSRFToken': this.cookieService.get('csrftoken')
}),
withCredentials: true
});
}
}
and then in your service where you hit secure APIs use it like this
// Officer service
import { Http, Response} from "#angular/http";
import { Injectable } from "#angular/core";
import "rxjs/add/operator/map";
// Services
import { CustomRequestOptionsService } from "../shared/custom-request-options.service";
#Injectable()
export class OfficerService {
private officerDashboardUrl = `http://${process.env.API_URL}` + '/api/v1/officers/detail';
constructor(
private http: Http,
private customRequestOptionService: CustomRequestOptionsService
) { }
getOfficer(officerId: number) {
return this.http.get(`${this.officerDashboardUrl}/${officerId}/`,
this.customRequestOptionService.authorizationRequestOptions())
.toPromise()
.then((response: Response) => {
return response.json();
})
.catch((error: any) => {
return Promise.reject(error.message || error)
});
}
}