I have a question about django-registration (https://bitbucket.org/ubernostrum/django-registration), but I can't find their issue tracker or a mailing list for it, so I'll try my luck here.
My application enables login via OpenID and login/password.
Some users "forget their password" on FS on try to reset it (here), but then they get the message:
The user account associated with this e-mail address cannot reset the password.
With no further explanations.
(You can try and reset my password - just type my email (tonylampada at gmail dot com) there to see the error message.
I want to customize that message. A better message would be:
The user account associated with this e-mail address cannot reset the password.
This happens because the user account was created with an OpenID or OAuth provider (tipically Google, Facebook, MyOpenID, etc).
To see the login provider(s) associated with this account, take a look at the user profile.
What is the easiest way to tell django-registration that?
Thanks!
PS: This issue on Github: https://github.com/freedomsponsors/www.freedomsponsors.org/issues/191 (just in case you're feeling like making a pull request today :-))
django-registration uses views from django.contrib.auth.
In this case: reset_password() github
Since this is no class based view, you can't override/inherit from it, but you can pass in a PasswordResetForm from django.contrib.auth.forms
from django.contrib.auth.forms import PasswordResetForm
class CustomResetForm(PasswordResetForm):
def validate(self, value):
#pseudocode
if user.cant_reset_pw:
raise ValidationError("The user account associated with this e-mail address cannot reset the password. and so forth..")
super(CustomResetForm, self).validate(value)
You'll have to wire things together by overriding the url r'^password/change/$' to point to a custom function that calls django.contrib.auth.passwort_reset() with your CustomResetForm.
Related
I have a reactjs app that already has a user logged in. I attached a link to the web app that make the user able to access Django admin page, but for now it still requires the user to login.
I'd like to bypass the login as the user is already authenticated when logging into the react app.
How do I bypass the log in page and tell django that this user is already authenticated? What if I still want to get the email from request? where can I access the request object?
EDIT:
I should specify that I would like to check for auth token which I already have in my localStorage, then authenticate the external user directly. If the auth token is not present, I should still hit the django admin login page
EDIT2:
Created a custom page just to deal with Auth0 authentication. But I'm not sure what to do next. The request.user at this point is AnonymousUser which I can't really operate on. There is no way to identify who this is (but I can successfully check if this user has permission)
I plan to create a user and give it superuser permission? Is that the right approach?
EDIT3:
login(request, request.user, backend='django.contrib.auth.backends.RemoteUserBackend')
return HttpResponseRedirect("/my/url")
and i got
'AnonymousUser' object has no attribute '_meta'
Is it part of the auth problem?
You should not "bypass the login" you need to use authorized tokens... to identify that client whos is consuming the API is really you and not the anyone else
The process is really simple, once you send username and password to your backend (django) you will retorn one autorization token to your frontend (react) and every request from your frontend you will add it to header
Use django_rest_framework or something like that (as tastypie)
http://www.django-rest-framework.org/api-guide/authentication/
So i'm piggybacking on this post here:
Python Social Auth duplicating e-mails for different users
Here's my issue:
I provide a user with ability to signup either via regular email sign up, facebook auth or twitter auth.
I'm also using same package Social Django Auth App for the user login pages.
I realized that a user might try sign up with a Facebook account (associated to one email) and then try again later to register with Twitter (which could have the same email address). Based on the aforementioned post, I added a function to check for duplicate emails like so:
def check_email_exists(request, backend, details, uid, user=None, *args, **kwargs):
email = details.get('email', '')
provider = backend.name
# check if social user exists to allow logging in (not sure if this is necessary)
social = backend.strategy.storage.user.get_social_auth(provider, uid)
# check if given email is in use
count = User.objects.filter(username=email).count()
success_message = messages.success(request, 'Sorry User With That Email Already Exists')
# user is not logged in, social profile with given uid doesn't exist
# and email is in use
if not user and not social and count:
return HttpResponseRedirect(reverse('accounts:sign_up', success_message))
and my pipeline with the function:
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'dealmazing.utils.check_email_exists',
'social_core.pipeline.social_auth.associate_by_email', # <--- enable this one
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)
UPON Testing--if i go to sign up with Twitter account of an already registered email address--it works. YAY!
BUT the main issue comes when i go to try to login via using either Facebook or Twitter. The function is checking on those logins as well and spitting me back the 'Email Allready Exists..' error.
So I somehow need to decipher between a login and a registration, but I'm having trouble finding how i actually do this with the social auth package.
Any ideas?
The difference between login and register is up to your project, it looks like in your scenario, a user landing in your pipeline function that matches an email in your DB should be considered like a login attempt and not a new singup. That's basically the functionality of associate_by_email method.
You might see the potential risk in this when a user uses a service that doesn't validate the email addresses, they can take control over somebody else account. You can mitigate this by doing validation on your end after any new social account is added, or by trusting services that are known to validate emails on their ends.
I would say, that you have to remove from the pipeline
'social_core.pipeline.social_auth.associate_by_email'
Reason: your application is not supporting unique user emails in User data model, and you are getting yourself into trouble. If you are not verifying user emails, then the trouble might be even bigger.
I have Django 2.0.2 with custom User model. One of feature is give anonymous users way to create order without "register-first" on site.
Main idea is:
Anonymous user fill order form, enter e-mail address and click Create Order;
Django create User with entered e-mail and random generated password;
Next, Django (or Celery) send to e-mail link for reset password (like from standard reset form);
User check e-mail and click to reset link, re-enter his own password.
This was killed two functions by one: user register and create first order.
And question: how can I send reset password mail from my custom views? I understand, link will generate and send on PasswordResetView view, but how to call to them on custom view?
To send the password reset link from a view you can fill out a PasswordResetForm which is what is used by the PasswordResetView
https://docs.djangoproject.com/en/2.0/topics/auth/default/#django.contrib.auth.forms.PasswordResetForm
As described in another stackoverflow answer here https://stackoverflow.com/a/30068895/9394660 the form can be filled like this:
from django.contrib.auth.forms import PasswordResetForm
form = PasswordResetForm({'email': user.email})
if form.is_valid():
request = HttpRequest()
request.META['SERVER_NAME'] = 'www.mydomain.com'
request.META['SERVER_PORT'] = '443'
form.save(
request= request,
use_https=True,
from_email="username#gmail.com",
email_template_name='registration/password_reset_email.html')
Note: if you are not using https replace the port with 80 and dont include use_https=True
Also depending on the situation you may already have a request and wouldn't need to create one
I'm using Django-Allauth to successfully log in with my Facebook account on my webserver. The problem is, when I use the default SignUpView to do so, the username stored in the DB is the username Facebook returns from the social login. Something like this:
<firstname>.<lastname>.<integer>
I've figured out how to connect my Facebook account with an already created standard user account ( not social ) at a later time using the view at:
/accounts/social/connections/
And how to change emails with
/accounts/email/
Can someone please show me how I can force a user to pick a non-facebook username when they log in with Facebook on my site without first creating a standard user?
Thanks!
============ EDIT =======================
So adding this to settings.py prompts for username and password to associate with facebook login, but does not prompty for a password:
SOCIALACCOUNT_AUTO_SIGNUP = False
I still need to figure out how to prompt for a password in this state.
This fixes it - inherit from SignupForm for social auth signup form.
class SignupForm(SignupForm):
I have implemented User account management into my application using Django all-auth. I have enabled login using username and password as well as with facebook connect.
The problem goes like this:
1) User visits a page http://example.com/page1/ and clicks login
2) He's taken to http://example.com/accounts/login?next=/page1/
3) When the user logs in using username and password, the user is redirected back to http://example.com/page1. But if the user logs in with facebook, he's taken to homepage.
How can I get desired behavior with Facebook login too?
You need to override the get_login_redirect_url method of django-allauth.
For this inherit the DefaultAccountAdapter class as
from allauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
# get the next parameter from request object and return the url
And make changes on settings.py
ADAPTER = "APPNAME.FILENAME.MyAccountAdapter"
ACCOUNT_ADAPTER = "APPNAME.FILENAME.MyAccountAdapter"
This should work !
How are you generating the Facebook login link? Most likely you are not indicating the next parameter there. The allauth documentation gives this example:
Google
To get the proper next parameter you can access request.GET.next.