Here's an example of how an existing POP-mail account can be used to provide authentication to a python application.
The user doesn't have to remember yet another password, and the administrator doesn't have to handle users who forgot... Instead, we associate all our users to some external POP-mail account. When they want to log in to our system, we ask them for the password to their email account.
If we can log in to the pop server using their password, and just get a status from their mailbox (we don't peek of course) we decide that the user has authenticated himself.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | # popauth.py Authenticate user through POP server.
# Copyright (c) 2002, Thinkware AB, SWEDEN
# 2002-02-27 magnus@thinkware.se
def popauth(popHost, user, passwd):
"""
Log in and log out, only to verify user identity.
Raise exception in case of failure.
"""
import poplib
try:
pop = poplib.POP3(popHost)
except:
raise StandardError, "Could not establish connection "+\
"to %s for password check" % popHost
try:
# Log in and perform a small sanity check
pop.user(user)
pop.pass_(passwd)
length, size = pop.stat()
assert type(length) == type(size) == type(0)
pop.quit()
except:
raise StandardError, "Could not verify identity. \n"+\
"User name %s or password incorrect." % user
pop.quit()
del pop
users = {
'Winston C': ('winstonc', 'pop.somedomain.xx'),
'Benny G': ('bgoodman', 'mail.anotherdomain.yy'),
'John L': ('lennon', 'pop.music-co.uk'),
}
# The main routine is for testing purposes.
def main():
usernames = users.keys()
usernames.sort()
reply = ""
while reply == "" or reply[0] not in 'Qq':
print
for i, name in zip(range(len(usernames)), usernames):
print i, name
print
print 'Select the number before your name followed by [ENTER], '
reply = raw_input("or type Q[ENTER] to quit: ")
username = ''
try:
i = int(reply)
username = usernames[i]
except:
# Continue in the loop
pass
if username:
# User successfully selected identity.
popAccount, popServer = users[username]
print
print "Hello %s. Let's see if you know the password for the " % \
username
print "email-account '%s' at the server '%s'." % \
(popAccount, popServer)
print
import getpass
passwd = getpass.getpass(
'Enter e-mail password, followed by [ENTER]: ')
print
try:
popauth(popServer, popAccount, passwd)
print "Congratulations! You have been authenticated!"
except StandardError, msg:
print msg
if __name__ == '__main__':
main()
|
This solution has some weaknesses: * The user must trust that this system doesn't abuse his email account. * Passwords are sent in plain text over the internet. * We have to trust that the POP server security isn't compromised. * Logging in might take a few seconds if the POP server is slow. * Logging in won't work if the POP server is down.
The main advantage is that the application that uses this scheme doesn't have to store any passwords, or administer password changes etc. It's also fairly simple.
I wouldn't use this for a bank system...but perhaps to give users right to edit web pages at a somewhat restricted WikiWiki etc.
In this example, user data (name, pop-account, pop-server) are stored in the code in a dictionary. In a real system they would probably be stored in a separate file or a database table.
Used it in a intranet groupware. It is quite a nice idea. I used it for a intranet groupware in a Linux box. This allowed the users to have the same username and password for the Linux box, email and the groupware. Since in this case the pop server is the same for all users, we could ask just the username and password.
Ashish Shrestha
http://www.shrestha.net.np