how to use email instead of username for user authentication?

1,461 views
Skip to first unread message
Message has been deleted

Rama Vadakattu

unread,
Mar 31, 2009, 4:03:09 AM3/31/09
to Django users
The authentication model provided along with django is based on
username.

What to do to change the authentication based on email instead of
username?

To be more specific
~~~~~~~~~~~
With username authentication , to login user we do the following

user = authenticate(name,password)
.......
login(request,user)

what to write for the above statements if we are authenticating
using email?

For form
~~~~~
iam planning to write my own form which shows the fields
email,password and the validation.
Is this the correct approach?





















johan...@student.hpi.uni-potsdam.de

unread,
Apr 1, 2009, 6:37:02 AM4/1/09
to Django users
Best way is to write your own authentication backend I think.

Check the docs:
http://docs.djangoproject.com/en/dev/topics/auth/?from=olddocs#writing-an-authentication-backend

This article might also give you a good idea:
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

The actual authenticate function might look something like this:

def authenticate(self, username=None, password=None):
# authenticate with email
try:
user = self.user_class.objects.get(email=username)
if user.check_password(password):
return user
except self.user_class.DoesNotExist:
# authentication with username
try:
user = self.user_class.objects.get(username=username)
if user.check_password(password):
return user
except self.user_class.DoesNotExist:
# neither nor succesfull, so no user exists
return None

Beware: During registration I have forbidden usernames that might look
like mail adresses (just unallow character @). Other than that there
might be the rare possibility that people can not login with their
username/password credentials if it username is the e-mail-adress used
by another account.

Timboy

unread,
Apr 2, 2009, 10:04:50 PM4/2/09
to Django users
What's the best way to add users with an auto generating username? ie:
Taub.John, Smith.Tim, Smith.Tim2


On Apr 1, 3:37 am, johan.u...@student.hpi.uni-potsdam.de wrote:
> Best way is to write your own authentication backend I think.
>
> Check the docs:http://docs.djangoproject.com/en/dev/topics/auth/?from=olddocs#writin...
>
> This article might also give you a good idea:http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-mod...

Malcolm Tredinnick

unread,
Apr 2, 2009, 10:11:45 PM4/2/09
to django...@googlegroups.com
On Thu, 2009-04-02 at 19:04 -0700, Timboy wrote:
> What's the best way to add users with an auto generating username? ie:
> Taub.John, Smith.Tim, Smith.Tim2

You can do it however you like, since the user will never see it.
Something as simple as taking the email address, replacing "@" with "AT"
and "." with "DOT" might work.

One thing I did for a client was take the email address, trip off
everything after the "@" and then continue adding a number to the end of
the username until it was unique. So if t...@example.com registered
first, he would be username "tim" and t...@foo.bar.org would be username
"tim1", since "tim" was already in use. Since all registration is
normally done through one or two places, it only required setting up the
registration form handling view and writing a management command tool to
add a user manually. These days, I might also add some admin overrides,
but I didn't need that at the time.

Regards,
Malcolm


johan.uhIe

unread,
Apr 7, 2009, 4:38:47 AM4/7/09
to Django users
The slugify function may also provide you with valid usernames, if you
feed it with first and last name for example. But always be certain,
that the username is unique, just as malcolm described.

pkenjora

unread,
Apr 7, 2009, 1:16:21 PM4/7/09
to Django users
Hi,

Why not remove the '@' filter and allow the specific project
developer the freedom to use email as username? What was the
reasoning behind this?

I always like Django because it didn't try to force development down
a specific path. All developers have their own way and every project
is unique, for a long time Django accommodated that. I'm a bit
worried about where this is going...

I'm worried that the workarounds just introduce unnecessary
complexity. We are currently upgrading to Django 1.02 and will most
likely strip the limiting logic instead of working around it. I will
have a patch available for anyone interested later today.

- Paul

On Apr 2, 7:11 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:

pkenjora

unread,
Apr 7, 2009, 1:40:55 PM4/7/09
to Django users
Hi Again,

Here is what we used to get around the email restriction. It works
very well for authenticating through your application, Admin is a
different story. In our case the users who register online never need
to log into admin. If yours do, then you will have to strip logic
from several files.

In /django/contrib/auth/backends.py modify the following function....

def authenticate(self, **credentials):
try:
user = None
if 'username' in credentials:
user = User.objects.get(username=credentials
['username'])
else:
user = User.objects.get(email=credentials['email'])

if user.check_password(credentials['password']):
return user

except User.DoesNotExist:
return None

Then when authenticating all you have to do is use:

user = authenticate(email=email, password=password)

or you can fall back on...

user = authenticate(username=email, password=password)

Either way thats all it takes, works like a charm now. There was even
a patch for this many months back, too bad Django developers went the
exact opposite way...

http://code.djangoproject.com/ticket/7591

Should we re-open the ticket? Either way, if you want email
authentication leave feedback...

-Paul

felix

unread,
Apr 7, 2009, 8:06:10 PM4/7/09
to django...@googlegroups.com

I use an EmailBackend for auth, found on django snippets

(though the one pkenjora posted looks the same but slightly better.)

and a generate_username to create a clean unique username when creating accounts, 
also found on django snippets



I sure wish djangosnippets had a google search box attached. 

Malcolm Tredinnick

unread,
Apr 7, 2009, 8:10:35 PM4/7/09
to django...@googlegroups.com
On Tue, 2009-04-07 at 10:16 -0700, pkenjora wrote:
> Hi,
>
> Why not remove the '@' filter and allow the specific project
> developer the freedom to use email as username? What was the
> reasoning behind this?

One reason is that usernames can be made to be unique, since you're
selecting a new username and if the one you choose is already taken, you
can choose another one. You cannot, however, easily change your email
address and there are cases of different people sharing a single email
address or the same person needing/wanting to create multiple accounts.

Another reason is likely simply historical; usernames that *aren't*
email addresses are much more readable and traditional in social-based
sites and that was what was used in the initial implementation. The
uniqueness problem mentioned above is very real, however, so Django is
protecting people from doing dumb things here. If you want to work
around that, it's possible and fairly easy, but not heavily advisable.

> I always like Django because it didn't try to force development down
> a specific path. All developers have their own way and every project
> is unique, for a long time Django accommodated that. I'm a bit
> worried about where this is going...

It's not "going" anywhere. The username requirements have been the same
since the very first day you used Django. Don't frame this as something
slipping out of control, please.

>
> I'm worried that the workarounds just introduce unnecessary
> complexity.

Almost as if you shouldn't workaround a valid constraint, isn't it? :-)

Regards,
Malcolm

pkenjora

unread,
Apr 11, 2009, 10:52:38 AM4/11/09
to Django users
Malcom,

Google, FaceBook, and LinkedIn have been using email authentication
for how long now? With the default constraints you've put on Django a
developer would have to "work around" the out of the box code to make
the project behave like the big 3 names on the web. In this light it
sounds like the constraint is too tight and needs to be moved into an
optional module not a default one. Again these sound like project
specific requirements not general framework properties.

As far as your reasons go, I'm fairly sure its just as easy to
change the email as it is the username, I would even argue that my
username (display name) could change but my login credentials should
stay the same. I currently use the same email address for multiple
accounts on many Django projects using the code I pasted above, I
simply use what almost every email engine today supports email[+-._]
var...@domain.com. Looking at this objectively, I would argue the
case for email authentication is strongest. I think changing the
default auth module to allow both and making the current one optional
would leave in place the flexibility of DJango out of the box and
allow developers to constrain it on their own. Email authentication
is catching on, Django should not fight the tide.

You are correct, username authentication has always been around.
However, the explicit banning and obfuscating of email authentication
in the default module has not. That is the part that worries me, that
is where things are going wrong.

We're all professionals here, we all take the time to leave feedback
in the hopes of improving Django. I have a sneaking suspicion that
project specific requirements crept into the trunk because it was
easier than patching every time. Now there is a hesitation to modify
because it would affect the original project. That's not a good
reason to start justifying weak requirements to the community. I
would recommend re-opening the ticket and getting feedback on it from
the community.

-Paul




On Apr 7, 5:10 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:

Karen Tracey

unread,
Apr 11, 2009, 5:13:00 PM4/11/09
to django...@googlegroups.com
On Sat, Apr 11, 2009 at 10:52 AM, pkenjora <pken...@gmail.com> wrote:

 You are correct, username authentication has always been around.
However, the explicit banning and obfuscating of email authentication
in the default module has not.  That is the part that worries me, that
is where things are going wrong.

I can't figure out what you are talking about here.  You mention an '@' filter elsewhere, and all I can think you mean is the fact that '@' is not an allowed character in the auth's username field?  If so, near as I can tell that has been there since the earliest official Django release, you can see in the 0.90 source code that there's an isAlphaNumeric validator on that field:

http://code.djangoproject.com/browser/django/tags/releases/0.90/django/models/auth.py#L33

so as far back as 0.90, near as I can tell, you were not allowed to have '@' in a username. 

Yet you seem to be saying you need to work around the 'new' restriction as you upgrade to 1.0.2 -- so I'm confused.  Are you upgrading from some level (what one?) which allowed '@' in usernames?  Are you talking about some other restriction?

Karen

Malcolm Tredinnick

unread,
Apr 11, 2009, 7:13:28 PM4/11/09
to django...@googlegroups.com
On Sat, 2009-04-11 at 07:52 -0700, pkenjora wrote:
> Malcom,

Well, I'm not "Malcom" (sic), but I'll reply anyway.

> Google, FaceBook, and LinkedIn have been using email authentication
> for how long now? With the default constraints you've put on Django a
> developer would have to "work around" the out of the box code to make
> the project behave like the big 3 names on the web.

There's some assumption there that what they're doing is a good idea.
Their systems have the usability problems I've mentioned. It's also not
clear their authentication methods are the best around. In any case, as
I note below (and have written elsewhere), you're simply not restricted
from using this system and can do so without patching Django, if that's
the way you want to go. There's no restriction in place here!

The combined size of forums and social networking sites not pretending
that my "handle" is an email address is, I'll wager, larger than
Facebook or LinkedIn, certainly. Which has precisely the same small
weight as your examples. The point being that there are valid use-cases
in both directions and you'll notice that that's never been disputed.

[...]


> As far as your reasons go, I'm fairly sure its just as easy to
> change the email as it is the username,

I'm sorry you feel that way. It's patently false. The username is only
used on the site you are creating an account for. Your email address has
much wider usage and creating a new one isn't always possible or
desirable (signing up to one of the hosted services requires agreeing to
T&C that are often unpleasant). The username when creating a new account
on a site has much less currency.

> I would even argue that my
> username (display name) could change but my login credentials should
> stay the same.

You are assuming that the username is the display name. That might be a
secondary use for it and it sometimes works well for that. However, the
username is primarily the unique identifier for the user within the
system. It's the thing that won't change. Having a display name,
particularly one that can change is also quite common and it's for
extensions like that that user profile exist for.

Login credentials are not the same as identifier within the system. The
login credentials should definitely be permitted to change. Having an
account tied to an email address is tragic when that email address is no
longer accessible to you (for example, it was a company address and
you've since left the company). Allowing the email address to change --
and hence not making it the entity identifier -- is a good thing.

> You are correct, username authentication has always been around.
> However, the explicit banning and obfuscating of email authentication
> in the default module has not.

I'm sorry, but that's simply not correct. I pointed that out earlier in
the thread.

You have the version control history, please feel free to find the
released version of Django where this wasn't the case and correct me if
you really feel this is not the case.

> That is the part that worries me, that
> is where things are going wrong.
>
> We're all professionals here, we all take the time to leave feedback
> in the hopes of improving Django.

Which is a given. Not a partricularly relevant comment for this thread,
unless you're trying to imply something sinister, since there's no
indication that feedback isn't being listened to. In fact, in this case,
it's being answered with both technical and usability reasons for the
current behaviour.

> I have a sneaking suspicion that
> project specific requirements crept into the trunk because it was
> easier than patching every time.

Whereas, I have a sneaking suspicion that you've forgotten your history.
Now we both have sneaking suspicions. It's all very suspicous. :-)

Part of the problem with threads like this is the built-in assumptions
people are bringing to the table. The username field in the User model
is just the unique identifier in the system. If you want to use the
email address for login, it's fairly easy to do so: writing auth
backends is supported and encouraged. You never have to show the
username to users (so you could generate a more-or-less random
identifier when creating the account) and that's fairly standard
practice in a bunch of projects I've seen. It's also not uncommon to add
a user-editable display name in a user profile class, etc, etc.

You're argument is about a bit of a red herring because it's assigning
more import to the username field than it deserves. That field simply
isn't intrinsic to a user's experience on the site because you are in
complete control as to what information you show and what information
you authenticate against on your site. Before complaining that "oh, no,
now I have to write my own login method", yes, big deal! You have to
write half a dozen lines once, or use somebody else's. Just like you do
when supporting OpenID or Facebook Connect or other authentication
systems.

Django has a default auth system. It works well for a large class of
situations. It's also easy enough to use other systems, including an
email address as an authentication facilitator.

Regards,
Malcolm

pkenjora

unread,
Apr 13, 2009, 12:44:23 AM4/13/09
to Django users
Malcolm, <- Remembered the 'l' this time!

To keep things simple and avoid fragmenting this discussion into a
million different dead end tit for tats , I'll try to reign in the
main points.

1. The default authentication method in Django should have no inherent
restrictions. Such as blocking '@' in the username. This leaves the
default framework open and free of workarounds. This approach would
not preclude any project specific requirements.

2. Any authentication method having restrictions should be an opt in
method. The current method is a restrictive authentication method,
one that does not allow email, and should be made optional.

3. When you boil down the hundreds of specific use cases out there you
still end up with the above two points. In which case I would make
the argument that if you need to block emails as user names then it is
you who should write a new authentication handler. In your own words,
the framework allows this and its only a few lines of code.

Now for the dead end tit for tat... this is really project philosophy
not framework philosophy... hence I feel like it is circular
discussion that distracts from the main point...

Authenticating by email does not require me to check my email every
time I log in. So if my email is no longer accessible (left my job) I
can simply log in and change it to a new one. If changing the
username requires checking my email then I will have the same problem
if I use email as my username or not.

You yourself identify the username as mainly an authentication
mechanism not necessarily a display value. Thats all the more reason
to have a robust restriction free out of the box implementation of
authentication.

Thanks for reading the feedback, I still fail to see how you can
include project specific requirements in a framework? The
implementation you are advocating is a subset of the general
implementation I would like to see bundled out of the box. Why not
move it into an optional module?

-Paul


On Apr 11, 4:13 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:

Praveen

unread,
Apr 13, 2009, 2:22:05 AM4/13/09
to Django users
You please check the satchmo package there they are using email as
username in satchmo-registration using
user=generate_id(email,firstname)

bvemu

unread,
Jun 22, 2009, 1:02:37 PM6/22/09
to Praveen, django...@googlegroups.com
Hi

Further to the above discussion,
I did implement the code and it worked for me for the authentication
while using the email id as the username
(username=emailid ; valid_user = authenticate (username=username,
password=password )

# django-admin.py --version
1.1 beta 1 SVN-10957

1.) The problem is in the admin interface "@" is not accepted as
username while I can populate the same from the view.py
Is this an expected behaviour or should I raise a ticket ( if at all
it doesnt exists )

2.) Do we have a configuration file or so where we can define these
constraints like max_length of user name, accepted characters set in
the user name and others.
I can very well change the code in django-trunk of my web server, but
I dont want to do that since I want to avoid the overhead of re-doing
the svn tasks

Thanks
Vemu

Reply all
Reply to author
Forward
0 new messages