http://en.wikipedia.org/wiki/One-time_password, thanks Madhukar R Pai
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 1.99.4 (2012-01-29 15:21:17) stable
|
||||
Version 1.99.4 (2012-01-29 15:22:07) stable
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import time
|
||||
from hashlib import md5
|
||||
from gluon.dal import DAL
|
||||
|
||||
def motp_auth(db=DAL('sqlite://storage.sqlite'),
|
||||
time_offset=60):
|
||||
|
||||
"""
|
||||
motp allows you to login with a one time password(OTP) generated on a motp client,
|
||||
motp clients are available for practically all platforms.
|
||||
to know more about OTP visit http://en.wikipedia.org/wiki/One-time_password
|
||||
to know more visit http://motp.sourceforge.net
|
||||
|
||||
|
||||
Written by Madhukar R Pai (madspai@gmail.com)
|
||||
License : MIT or GPL v2
|
||||
|
||||
thanks and credits to the web2py community
|
||||
|
||||
to use motp_auth:
|
||||
motp_auth.py has to be located in gluon/contrib/login_methods/ folder
|
||||
first auth_user has to have 2 extra fields - motp_secret and motp_pin
|
||||
for that define auth like shown below:
|
||||
|
||||
## after auth = Auth(db)
|
||||
db.define_table(
|
||||
auth.settings.table_user_name,
|
||||
Field('first_name', length=128, default=''),
|
||||
Field('last_name', length=128, default=''),
|
||||
Field('email', length=128, default='', unique=True), # required
|
||||
Field('password', 'password', length=512, # required
|
||||
readable=False, label='Password'),
|
||||
Field('motp_secret',length=512,default='',
|
||||
label='MOTP Seceret'),
|
||||
Field('motp_pin',length=128,default='',
|
||||
label='MOTP PIN'),
|
||||
Field('registration_key', length=512, # required
|
||||
writable=False, readable=False, default=''),
|
||||
Field('reset_password_key', length=512, # required
|
||||
writable=False, readable=False, default=''),
|
||||
Field('registration_id', length=512, # required
|
||||
writable=False, readable=False, default=''))
|
||||
|
||||
##validators
|
||||
custom_auth_table = db[auth.settings.table_user_name] # get the custom_auth_table
|
||||
custom_auth_table.first_name.requires = \
|
||||
IS_NOT_EMPTY(error_message=auth.messages.is_empty)
|
||||
custom_auth_table.last_name.requires = \
|
||||
IS_NOT_EMPTY(error_message=auth.messages.is_empty)
|
||||
custom_auth_table.password.requires = CRYPT()
|
||||
custom_auth_table.email.requires = [
|
||||
IS_EMAIL(error_message=auth.messages.invalid_email),
|
||||
IS_NOT_IN_DB(db, custom_auth_table.email)]
|
||||
|
||||
auth.settings.table_user = custom_auth_table # tell auth to use custom_auth_table
|
||||
## before auth.define_tables()
|
||||
|
||||
##after that:
|
||||
|
||||
from gluon.contrib.login_methods.motp_auth import motp_auth
|
||||
auth.settings.login_methods.append(motp_auth(db=db))
|
||||
|
||||
##Instructions for using MOTP
|
||||
- after configuring motp for web2py, Install a MOTP client on your phone (android,IOS, java, windows phone, etc)
|
||||
- initialize the motp client (to reset a motp secret type in #**#),
|
||||
During user creation enter the secret generated during initialization into the motp_secret field in auth_user and
|
||||
similarly enter a pre-decided pin into the motp_pin
|
||||
- done.. to login, just generate a fresh OTP by typing in the pin and use the OTP as password
|
||||
|
||||
###To Dos###
|
||||
- both motp_secret and pin are stored in plain text! need to have some way of encrypting
|
||||
- web2py stores the password in db on successful login (should not happen)
|
||||
- maybe some utility or page to check the otp would be useful
|
||||
- as of now user field is hardcoded to email. Some way of selecting user table and user field.
|
||||
"""
|
||||
|
||||
def verify_otp(otp,pin,secret,offset=60):
|
||||
epoch_time = int(time.time())
|
||||
time_start = int(str(epoch_time - offset)[:-1])
|
||||
time_end = int(str(epoch_time + offset)[:-1])
|
||||
for t in range(time_start-1,time_end+1):
|
||||
to_hash = str(t)+secret+pin
|
||||
hash = md5(to_hash).hexdigest()[:6]
|
||||
if otp == hash: return True
|
||||
return False
|
||||
|
||||
def motp_auth_aux(email,
|
||||
password,
|
||||
db=db,
|
||||
offset=time_offset):
|
||||
if db:
|
||||
user_data = db(db.auth_user.email == email ).select().first()
|
||||
if user_data:
|
||||
if user_data['motp_secret'] and user_data['motp_pin']:
|
||||
motp_secret = user_data['motp_secret']
|
||||
motp_pin = user_data['motp_pin']
|
||||
otp_check = verify_otp(password,motp_pin,motp_secret,offset=offset)
|
||||
if otp_check: return True
|
||||
else: return False
|
||||
else: return False
|
||||
return False
|
||||
return motp_auth_aux
|
||||
Reference in New Issue
Block a user