Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 74 lines
 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.

1 comment

Bill Worker 18 years, 5 months ago  # | flag

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

Created by Magnus Lyckå on Tue, 3 Jun 2003 (PSF)
Python recipes (4591)
Magnus Lyckå's recipes (3)

Required Modules

  • (none specified)

Other Information and Tasks