i am new in django, i require login with user and password or facebook, i am using rest framework for api endpoints. ¿How i can do it?
i try with:
django-rest-framework-social-oauth2 but don't work for my because i needs save additional info from user after first enter.
I expect have 2 endpoint one sending user and password and another sending facebook auth token
Here's sample code for user login for Django Rest Framework:
class Login(APIView):
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(Login, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'email' in request_data and 'password' in request_data:
try:
validate_email(request_data['email'])
except ValidationError:
return JsonResponse({'result': 'E-mail is invalid'}, status=400)
user = authenticate(email=request_data['email'], password=request_data['password'])
if user is not None:
if user.is_active:
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
return JsonResponse({'result': 'success', 'token': token.key, 'id': user.id}, status=200)
return JsonResponse({'result': 'E-mail or password is incorrect'}, status=400)
return JsonResponse({'result': 'E-mail or password is empty'}, status=400)
Here's sample for FB login code for Django Rest Framework (from my test project):
class FbLogin(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.AllowAny,)
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(FbLogin, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'access_token' in request_data:
response = requests.get(
url='https://graph.facebook.com/v2.5/me/',
params={
'access_token': request_data['access_token'],
'fields': 'email,first_name,last_name',
},
)
json_response = json.loads(response.text)
if 'error' not in json_response:
response_photo = requests.get(
url='https://graph.facebook.com/v2.5/%s/picture' % json_response['id'],
params={
'redirect': 'false',
'type': 'large',
},
)
response_photo_json = json.loads(response_photo.text)
response_friends = requests.get(
url='https://graph.facebook.com/v2.5/me/friends/',
params={
'access_token': request_data['access_token'],
'limit': 300,
},
)
generated_password = get_random_string(10, '0123456789abcdefghijklmnopqrstuvwxyz')
try:
json_response_email = json_response['email']
except:
first_name = json_response['first_name'].lower()
last_name = json_response['last_name'].lower()
id = json_response['id']
json_response_email = first_name + last_name + id + '#facebook.com'
try:
current_user = User.objects.get(email=json_response_email)
current_user.set_password(generated_password)
current_user.save()
except User.DoesNotExist:
new_user = User.objects.create_user(email=json_response_email,
password=generated_password)
new_user.provider_id = json_response['id']
new_user.provider_type = 'facebook'
if 'first_name' in json_response:
new_user.first_name = json_response['first_name']
if 'last_name' in json_response:
new_user.last_name = json_response['last_name']
new_user.save()
photo_name = urlparse(response_photo_json['data']['url']).path.split('/')[-1].split('?')[-1]
photo_content = urllib.request.urlretrieve(response_photo_json['data']['url'])
new_user.profile_photo.save(photo_name, File(open(photo_content[0], 'rb')), save=True)
user = authenticate(email=json_response_email, password=generated_password)
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
if user is not None:
if user.is_active:
fullname = json_response['first_name'] + ' ' + json_response['last_name']
return JsonResponse({'result': 'success', 'token': token.key, 'name': fullname}, status=200)
return JsonResponse({'result': 'User access token is incorrect'}, status=400)
Related
This was working just fine before I tried to add social authentication to the project, and now when I send the verification email with the token, the token verifier says that the token is not valid!
class ResendVerifyEmail(APIView):
serializer_class = RegisterSerialzer
def post(self, request):
data = request.data
# email = data.get('email')
email = data['email']
print(email)
try:
user = User.objects.get(email=email)
# print('hello')
if user.is_verified:
return Response({'msg':'User is already verified','status':'status.HTTP_400_BAD_REQUEST'})
print (user.username)
token = RefreshToken.for_user(user).access_token
current_site= get_current_site(request).domain
relativeLink = reverse('email-verify')
absurl = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body = 'Hi '+ user.username + ' this is the resent link to verify your email \n' + absurl
data = {'email_body':email_body,'to_email':user.email,
'email_subject':'Verify your email'}
Util.send_email(data)
return Response({'msg':'The verification email has been sent','status':'status.HTTP_201_CREATED'}, status=status.HTTP_201_CREATED)
except User.DoesNotExist:
return Response({'msg':'No such user, register first','status':'status.HTTP_400_BAD_REQUEST'})
class VerifyEmail(APIView):
serializer_class = EmailVerificationSerializer
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY)
# print('decoded')
user = User.objects.filter(id=payload['user_id']).first()
# print(user)
if user.is_verified:
return Response({'msg':'User already verified!'}, status=status.HTTP_400_BAD_REQUEST)
else:
user.is_verified = True
# user.is_authenticated = True
user.is_active = True
# if not user.is_verified:
user.save()
return Response({'email':'successfuly activated','status':'status.HTTP_200_OK'}, status=status.HTTP_200_OK)
# except jwt.ExpiredSignatureError as identifier:
except jwt.ExpiredSignatureError:
return Response({'error':'Activation Expired','status':'status.HTTP_400_BAD_REQUEST'}, status=status.HTTP_400_BAD_REQUEST)
# except jwt.exceptions.DecodeError as identifier:
except jwt.exceptions.DecodeError:
return Response({'error':'invalid token','status':'status.HTTP_400_BAD_REQUEST'}, status=status.HTTP_400_BAD_REQUEST)
also, I have added these in settings.py
AUTHENTICATION_BACKENDS = (
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
I get 'jwt.exceptions.DecodeError'
This did the job
payload = jwt.decode(token, settings.SECRET_KEY, algorithms='HS256')
User = get_user_model()
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','phone' , 'password',)
write_only_fields = ('password',)
def create(self, validated_data):
user = User.objects.create(validated_data['phone'])
user.set_password(validated_data['password'])
user.save()
return user
})
class Register(APIView):
def post(self, request, *args, **kwargs):
phone = request.data.get('phone', False)
password = request.data.get('password', False)
print(phone)
print(password)
if phone and password:
old = PhoneOTP.objects.filter(phone__iexact=phone)
if old.exists():
old = old.first()
validated = old.validate
if validated:
temp_data = {
'phone': phone,
'password': password
}
serializers = CreateUserSerializer(data=temp_data)
serializers.is_valid(raise_exception=True)
user = serializers.save()
old.delete()
return Response({
'status': True,
'detail': 'Account is created '
})
while saving user pasword feild is shows Invalid password format or unknown hashing algorithm.
user is created the password feild is Invalid password format or unknown hashing algorithm.
uable to find y
also tried user.set_unusable_password() in serializer but same result could not figure it out
I try a lot a method you are using. It didn't save the password in the right form.
I suggest you create another model such as Profile and serializers for it and then try this -:
views.py
class Register(APIView):
permission_classes = (AllowAny, )
serializer_class = UserRegistrationSerializer
def post(self, request, *args, **kwargs):
phone = request.data.get('phone' , False)
if phone:
old = PhoneOTP.objects.filter(phone__iexact = phone)
if old.exists():
old = old.last()
validated = old.validated
if validated:
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
response = {
'success' : 'True',
'status code' : status.HTTP_200_OK,
'message': 'User registered successfully',
}
status_code = status.HTTP_200_OK
return Response(response, status=status_code)
else:
return Response({
'status' : False,
'detail' : "OTP haven't verified. FIrst do that step."
})
else:
return Response({
'status' : False,
'detail' : 'Please verify phone number first.'
})
else:
return Response({
'status' : False,
'detail' : 'Phone password, address, Date_Of_Birth, are not sent.'
})
serializers.py
class UserRegistrationSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=False)
class Meta:
model = User
fields = ('phone', 'username', 'password', 'profile')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create_user(**validated_data)
users = Profile.objects.create(
user=user,
state=profile_data['state'],
city=profile_data['city'],
date_Of_Birth=profile_data['date_Of_Birth'],
address=profile_data['address']
)
users.save()
return users
Hope the answer is useful
hello i learning about Django rest api, I am learning through someone else's code, but I don't know how to make Login.
my code :
model:
class User(models.Model):
class Meta:
db_table = "users"
created_at = models.DateTimeField(default = timezone.now)
updated_ay = models.DateTimeField(auto_now= True)
email = models.CharField(max_length = 128, unique= True)
password = models.CharField(max_length = 255)
active = models.BooleanField(default=False)
token = models.CharField(max_length= 255, null = True)
nickname = models.CharField(max_length = 255, null = True)
serializer:
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField()
class Meta:
model = User
fields = '__all__'
def to_internal_value(self, data):
ret = super(UserSerializer, self).to_internal_value(data)
# cipher = AESSipher()
# ret['password'] = cipher.encrypt_str(ret['password'])
return ret
def to_representation(self, obj):
ret = super(UserSerializer, self).to_representation(obj)
print(ret)
return ret
def validate_email(self, value):
if User.objects.filter(email=value).exists():
raise serializers.ValidationError("Email already exists")
return value
def validate_password(self, value):
if len(value) < 8:
raise serializers.ValidationError("The password must be at least %s characters long. " % 8)
return value
def create(self, validate_data):
user = User.objects.create(
email = validate_data['email'],
password = validate_data['password'],
)
user.active = False
user.save()
message = render_to_string('user/account_activate_email.html', {
'user': user,
'domain' : 'localhost:8000',
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user)
})
mail_subject = 'sign up mail.'
to_email = 'mymail#gmail.com'
email = EmailMessage(mail_subject, message, to=[to_email])
email.send()
return validate_data
views:
class SignUp(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserActivate(APIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk = uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
try:
if user is not None and account_activation_token.check_token(user, token):
user.active = True
user.token = token
user.save()
return Response(user.email + 'email active', status=status.HTTP_200_OK)
else:
return Response('Expired Link', status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
print(traceback.format_exc())
Since I want to handle log-in status in the Mobile Client section,
I want to get only user model information when I log-in.
When Enter Email and Password in Client and I want to get user information.
How to make log-in? Do you know anyone?
Here is the link to the article: custom user authentication; it should help you
https://wsvincent.com/django-rest-framework-user-authentication-tutorial/
Hi you can use Django packages for this. for example you can use rest-auth package this package have all the things that you need for log in log out and reset password and all you need is that follow the rest auth documentation :
. https://pypi.org/project/django-rest-auth/
. https://django-rest-auth.readthedocs.io/en/latest/
Hi I am beginner in Django Here I want user email and name in response after user login using api. Thanks in advance for your help.
models.py
I want user email and user name in response only getting auth token in response
class UserManager(BaseUserManager):
def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
if not password:
raise ValueError('Users must have a password')
user = self.model(email=self.normalize_email(email), **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email,password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
serializers.py
I want user email and user name in response only getting auth token in response
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
class Meta:
model = get_user_model()
fields = ('email', 'password', 'name')
extra_kwargs = {'password': {'write_only': True, 'min_length': 6}}
def create(self, validated_data):
user = User.objects.create_user('name',validated_data['email'],
validated_data['password'],)
return user
class AuthTokenSerializer(serializers.Serializer):
email = serializers.CharField()
password = serializers.CharField(
style = {'input_type':'password'},
trim_whitespace = False
)
def validate(self, attrs):
email = attrs.get('email')
password = attrs.get('password')
user = authenticate(
request = self.context.get('request'),
username = email,
password = password
)
if not user:
msg = _('Unable to authenticate with provided crenditial')
raise serializers.ValidationError(msg, code = 'authorization')
attrs['user'] = user
return attrs
urls.py
I want user email and user name in response only getting auth token in response
path('api/login/',views.CreateTokenView.as_view(),name='token'),
View file for creating view and I dont now how to return user from Auth token. I want user email and user name in response only getting auth token in response
views.py
class UserCreate(APIView):
"""
Creates the user.
"""
def post(self, request, format='json'):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
token = Token.objects.create(user=user)
json = serializer.data
json['token'] = token.key
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CreateTokenView(ObtainAuthToken):
serializer_class = AuthTokenSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
def post(self, request, *args, **kwargs):
response = super(CreateTokenView, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
return Response({'token': token.key})
I guess what you can do is maybe once you recieve a valid token for the user, you could query for the user using the user's email from the request data.
def post(self, request, *args, **kwargs):
response = super(CreateTokenView, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
user_email = request.data.get('email', None)
user = User.objects.get(email=user_email)
return Response({'name': user.name, 'email': user.email, 'token': token.key})
Hope this helps!
I know this is an old post but I ended up searching for this.
For the new comers:
There's an example on Django REST Framework, available here
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
class CustomAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'email': user.email
})
using the tastypie API and implementing some functionality for the user resource (following this example code: How can I login to django using tastypie), I wonder how the authenticated user is deposited or how I can access it in the right way. While testing the login method:
curl -u "user:pw" -H "Content-Type: application/json" -X POST --data '{"username" : "user", "password": "pw"}' http://localhost:8000/api/user/login/?format=json
everything works fine; but the logout method sees the request.user as an anonymous user. How can I pass to the logout method the right authenticated user? Thanks a lot.
Snippet from api.py
class UserResource(ModelResource):
class Meta:
queryset = AppUser.objects.all()
resource_name = 'user'
fields = ['first_name', 'last_name', 'username', 'email', 'is_staff']
allowed_methods = ['get', 'post', 'patch']
always_return_data = True
authentication = BasicAuthentication()
authorization = Authorization()
def prepend_urls(self):
params = (self._meta.resource_name, trailing_slash())
return [
url(r"^(?P<resource_name>%s)/login%s$" % params, self.wrap_view('login'), name="api_login"),
url(r"^(?P<resource_name>%s)/logout%s$" % params, self.wrap_view('logout'), name="api_login")
]
def login(self, request, **kwargs):
"""
Authenticate a user, create a CSRF token for them, and return the user object as JSON.
"""
self.method_check(request, allowed=['post'])
data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
username = data.get('username', '')
password = data.get('password', '')
if username == '' or password == '':
return self.create_response(request, {
'success': False,
'error_message': 'Missing username or password'
})
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
response = self.create_response(request, {
'success': True,
'username': user.username
})
response.set_cookie("csrftoken", get_new_csrf_key())
return response
else:
return self.create_response(request, {
'success': False,
'reason': 'disabled',
}, HttpForbidden )
else:
return self.create_response(request, {
'success': False,
'error_message': 'Incorrect username or password'
})
def logout(self, request, **kwargs):
"""
Attempt to log a user out, and return success status.
"""
self.method_check(request, allowed=['get'])
if request.user and request.user.is_authenticated():
logout(request)
return self.create_response(request, { 'success': True })
else:
return self.create_response(request, { 'success': False, 'error_message': 'You are not authenticated, %s' % request.user.is_authenticated() })
If you're making your own custom tastypie URLs you need to call the tastypie authentication yourself before the request.user object is populated correctly.
def logout(self, request, **kwargs):
"""
Attempt to log a user out, and return success status.
"""
self.method_check(request, allowed=['get'])
# Run tastypie's BasicAuthentication
self.is_authenticated(request)
if request.user and request.user.is_authenticated():
logout(request)
return self.create_response(request, { 'success': True })
else:
return self.create_response(request, { 'success': False, 'error_message': 'You are not authenticated, %s' % request.user.is_authenticated() })