def test_provisioning_uri(self): hotp = pyotp.HOTP('wrn3pqx5uqxqvnqr') url = urlparse( hotp.provisioning_uri('mark@percival')) self.assertEqual(url.scheme, 'otpauth') self.assertEqual(url.netloc, 'hotp') self.assertEqual(url.path, '/mark%40percival') self.assertEqual(dict(parse_qsl(url.query)), {'secret': 'wrn3pqx5uqxqvnqr', 'counter': '0'}) url = urlparse( hotp.provisioning_uri('mark@percival', initial_count=12)) self.assertEqual(url.scheme, 'otpauth') self.assertEqual(url.netloc, 'hotp') self.assertEqual(url.path, '/mark%40percival') self.assertEqual(dict(parse_qsl(url.query)), {'secret': 'wrn3pqx5uqxqvnqr', 'counter': '12'}) url = urlparse( hotp.provisioning_uri('mark@percival', issuer_name='FooCorp!')) self.assertEqual(url.scheme, 'otpauth') self.assertEqual(url.netloc, 'hotp') self.assertEqual(url.path, '/FooCorp%21:mark%40percival') self.assertEqual(dict(parse_qsl(url.query)), {'secret': 'wrn3pqx5uqxqvnqr', 'counter': '0', 'issuer': 'FooCorp!'}) key = 'c7uxuqhgflpw7oruedmglbrk7u6242vb' hotp = pyotp.HOTP(key, digits=8, digest=hashlib.sha256) url = urlparse( hotp.provisioning_uri('baco@peperina', issuer_name='FooCorp')) self.assertEqual(url.scheme, 'otpauth') self.assertEqual(url.netloc, 'hotp') self.assertEqual(url.path, '/FooCorp:baco%40peperina') self.assertEqual(dict(parse_qsl(url.query)), {'secret': 'c7uxuqhgflpw7oruedmglbrk7u6242vb', 'counter': '0', 'issuer': 'FooCorp', 'digits': '8', 'algorithm': 'SHA256'}) hotp = pyotp.HOTP(key, digits=8) url = urlparse( hotp.provisioning_uri('baco@peperina', issuer_name='Foo Corp', initial_count=10)) self.assertEqual(url.scheme, 'otpauth') self.assertEqual(url.netloc, 'hotp') self.assertEqual(url.path, '/Foo%20Corp:baco%40peperina') self.assertEqual(dict(parse_qsl(url.query)), {'secret': 'c7uxuqhgflpw7oruedmglbrk7u6242vb', 'counter': '10', 'issuer': 'Foo Corp', 'digits': '8'})
def get(request, phone): try: Mobile = phoneModel.objects.get( phone_number=phone ) # if Mobile already exists the take this else create New One except ObjectDoesNotExist: phoneModel.objects.create(phone_number=phone, ) Mobile = phoneModel.objects.get( phone_number=phone) # user Newly created Model Mobile.counter += 1 # Update Counter At every Call Mobile.save() # Save the data keygen = generateKey() key = base64.b32encode( keygen.returnValue(phone).encode()) # Key is generated OTP = pyotp.HOTP(key) # HOTP Model for OTP is created print(OTP.at(Mobile.counter)) custom_params = { "number": phone, "text": f"Your one time code is: {OTP.at(Mobile.counter)}", "sign": "SMS Aero" } r = requests.get( url=SMS_AERO_URL, params=custom_params, auth=HTTPBasicAuth(SMS_AERO_USERNAME, SMS_AERO_API_KEY)) #same as Http Basic auth # Using Multi-Threading send the OTP Using Messaging Services like Twilio or Fast2sms return Response({"otp": OTP.at(Mobile.counter)}, status=200) # Just for demonstration
def get(request, phone): try: try: Mobile = Phone.objects.get(Mobile=phone) # if Mobile already exists the take this else create New One except ObjectDoesNotExist: Phone.objects.create( Mobile=phone, ) Mobile = Phone.objects.get(Mobile=phone) # user Newly created Model Mobile.counter += 1 # Update Counter At every Call Mobile.save() # Save the data keygen = generateKey() key = base64.b32encode(keygen.returnValue(phone).encode()) # Key is generated OTP = pyotp.HOTP(key) # HOTP Model for OTP is created print(OTP.at(Mobile.counter)) # Your Account Sid and Auth Token from twilio.com/console client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN) message = client.messages \ .create( body='OTP for Parking Service is '+OTP.at(Mobile.counter), from_=SMS_FROM_NO, to='+91'+phone ) print(message.sid) # Using Multi-Threading send the OTP Using Messaging Services like Twilio or Fast2sms # return Response({"OTP": OTP.at(Mobile.counter)}, status=200) # Just for demonstration return Response({"message": "OTP Sent."}, status=status.HTTP_200_OK) except TwilioRestException: return Response({"message": "Trial Twilio accounts cannot send messages to unverified numbers.", "OTP": OTP.at(Mobile.counter)}, status=status.HTTP_200_OK) # Just for demonstration except Exception as e: return Response({"Error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def confirm_otp_token(login_manager, otp=None, tmp_id=None): '''Confirm otp matches.''' if not otp: otp = frappe.form_dict.get('otp') if not otp: if two_factor_is_enabled_for_(login_manager.user): return False return True if not tmp_id: tmp_id = frappe.form_dict.get('tmp_id') hotp_token = frappe.cache().get(tmp_id + '_token') otp_secret = frappe.cache().get(tmp_id + '_otp_secret') if not otp_secret: raise ExpiredLoginException(_('Login session expired, refresh page to retry')) hotp = pyotp.HOTP(otp_secret) if hotp_token: if hotp.verify(otp, int(hotp_token)): frappe.cache().delete(tmp_id + '_token') return True else: login_manager.fail(_('Incorrect Verification code'), login_manager.user) totp = pyotp.TOTP(otp_secret) if totp.verify(otp): # show qr code only once if not frappe.db.get_default(login_manager.user + '_otplogin'): frappe.db.set_default(login_manager.user + '_otplogin', 1) delete_qrimage(login_manager.user) return True else: login_manager.fail(_('Incorrect Verification code'), login_manager.user)
def send_user_otp(mobile=None, user=None): try: '''Authenticate using otp.''' from frappe.twofactor import (should_run_2fa, authenticate_for_2factor,get_otpsecret_for_, confirm_otp_token, send_token_via_sms, send_token_via_email) import pyotp, os if mobile: user = frappe.db.get_value('User', {"mobile_no":mobile},'name') recipients = [] recipients = recipients + mobile.split("\n") recipients = list(set(recipients)) otp_secret = get_otpsecret_for_(user) token = int(pyotp.TOTP(otp_secret).now()) hotp = pyotp.HOTP(otp_secret) otp = hotp.at(int(token)) frappe.log_error(otp, "userverification") # otp_issuer="INGC" message = 'Your verification code is {otp}'.format(otp=otp) status = send_sms(recipients, message) verification_obj = { 'token_delivery': status, 'prompt': status and 'Enter verification code sent to {}'.format(mobile[:4] + '******' + mobile[-3:]), "user": user, "tmp_id":token } return verification_obj except Exception as e: frappe.log_error(frappe.get_traceback(), "myjobpro.api.send_user_otp")
def send_token_via_sms(otpsecret, token=None, phone_no=None): '''Send token as sms to user.''' otp_issuer = frappe.db.get_value('System Settings', 'System Settings', 'otp_issuer_name') try: from frappe.core.doctype.sms_settings.sms_settings import send_request except: return False if not phone_no: return False ss = frappe.get_doc('SMS Settings', 'SMS Settings') if not ss.sms_gateway_url: return False hotp = pyotp.HOTP(otpsecret) args = { ss.message_parameter: 'Your verification code is {}'.format(hotp.at(int(token))) } for d in ss.get("parameters"): args[d.parameter] = d.value args[ss.receiver_parameter] = phone_no sms_args = { 'params': args, 'gateway_url': ss.sms_gateway_url } enqueue(method=send_request, queue='short', timeout=300, event=None, async=True, job_name=None, now=False, **sms_args) return True
def respond(self, request): rtime = time.time() jsonStr = request.payload #jsonStr = request dict = json.loads(jsonStr) hotp = pyotp.HOTP(self.groupNonce) timeCode = dict['timestamp'].replace(":", "") timeCode = timeCode.replace(" ", "") timeCode = timeCode.replace("-", "") timeCode = int(timeCode) groupKey = hotp.at(timeCode) m = hashlib.md5() m.update(groupKey.encode("UTF-8")) hashedKey = m.hexdigest()[:16] IV = binascii.unhexlify(dict['iv']) decipher = AES.new(hashedKey, AES.MODE_CBC, IV) unhexData = binascii.unhexlify(dict['data']) plainText = decipher.decrypt(unhexData) plainText = plainText[:-plainText[-1]] plainText = plainText.decode("utf-8") if plainText in self.database.keys(): #Value, encrypt, json, return payload = self._encrypt(self.database[plainText][:-1]) self._send(request.source[0], 'respond/', defines.Codes.POST.number, payload, rtime) return "OK"
def register(request): if request.method == 'POST': username, dominio = request.POST['email'].split('@') if dominio == 'inf.ufsm.br': try: User.objects.get(username=username) messages.warning(request, 'Esse email já está cadastrado') except ObjectDoesNotExist: hotp = pyotp.HOTP('base32secret3232') number = random.randrange(10000) # Save number of auth. token, created = Token.objects.get_or_create(username=username) token.token = number token.save() key = hotp.at(number) # Envia email com o token para a autenticação. subject = "[NCC Machine] Confirmação de email ." url = request.build_absolute_uri( reverse('accounts:cadastro', kwargs={ 'username': username, 'token': str(key) })) mensagem = "Olá, acesse a seguinte URL para continuar seu cadastro: " + url mfrom = settings.EMAIL_HOST_USER mto = [request.POST['email']] send_mail(subject, mensagem, mfrom, mto) messages.warning( request, 'Um link foi enviado para seu email para continuar o cadastro' ) else: messages.error(request, 'Insira um email @inf.ufsm.br') return render(request, 'accounts/register.html')
def send_token_via_email(user, token, otp_secret, otp_issuer, subject=None, message=None): '''Send token to user as email.''' user_email = frappe.db.get_value('User', user, 'email') if not user_email: return False hotp = pyotp.HOTP(otp_secret) otp = hotp.at(int(token)) template_args = {'otp': otp, 'otp_issuer': otp_issuer} if not subject: subject = get_email_subject_for_2fa(template_args) if not message: message = get_email_body_for_2fa(template_args) email_args = { 'recipients': user_email, 'sender': None, 'subject': subject, 'message': message, 'header': [_('Verfication Code'), 'blue'], 'delayed': False, 'retry':3 } enqueue(method=frappe.sendmail, queue='short', timeout=300, event=None, async=True, job_name=None, now=False, **email_args) return True
def check_otp(self, otp_code): res_user = self.env['res.users'].browse(self.env.uid) if res_user.aut_type2FA == 'Email' and res_user.require_2FA: if type(otp_code) is str and len(otp_code) == 16: tz_offset = self.env.user.tz_offset if self.env.user.tz_offset else False tz = int(tz_offset)/100 if tz_offset else 0 now = fields.Datetime.now() + datetime.timedelta(hours=tz) return res_user.twoFA_code == otp_code and now < res_user.twoFA_date elif res_user.aut_type2FA == 'QR Code' and res_user.require_2FA: self.require_2FA_flag = False if type(otp_code) is str and len(otp_code) != 6: return False if res_user.otp_type == 'time': totp = pyotp.TOTP(res_user.otp_secret) return totp.verify(otp_code) elif res_user.otp_type == 'count': hotp = pyotp.HOTP(res_user.otp_secret) for i in range(0,20): print(hotp.at(i), i) # Allow users to accidentally click 20 times more, but the code that has been used cannot be used again for count in range(res_user.otp_counter, res_user.otp_counter + 20): val = hotp.verify(otp_code, count) if count > 0 and val: self.require_2FA_flag = True res_user.otp_counter = count + 1 return True return False
def get(request, phone): try: Mobile = User.objects.get( phone=phone ) # if Mobile already exists the take this else create New One except ObjectDoesNotExist: message = { 'message': 'Phone Number does exist please enter registered phone number' } return Response(data=message, status=400) Mobile.counter += 1 Mobile.save() keygen = generateKey() key = base64.b32encode( keygen.returnValue(phone).encode()) # Key is generated OTP = pyotp.HOTP(key) message = client.messages \ .create( body=f'''' You have recived this otp on request for password reset Please click on the link below and enter the otp Your one time password is:{OTP.at(Mobile.counter)} http://52.201.220.252/api/otp/ ''', from_='+19388883481', to=f'+91{Mobile}' ) return Response({"OTP": OTP.at(Mobile.counter)}, status=200) # Just for demonstration
def OTPVerify(): error = None if request.method == "POST": req = request.form HTOP = pyotp.HOTP("JASWY3DPEHPK3PXP") i = 7 a = (HTOP.at(i)) b = (HTOP.at(i+1)) c = (HTOP.at(i+2)) d = (HTOP.at(i+3)) print(a) if req["otp"] == a: return render_template('home.html') if req["otp"] == b: return render_template('home.html') if req["otp"] == c: return render_template('home.html') if req["otp"] == d: return render_template('home.html') else: errorMsg = "Wrong OTP. Please enter again." print(error) return render_template('OTP.html', error=error, errorMsg=errorMsg)
def confirm_device_otp_token(): email = frappe.form_dict.get('email') tmp_id = frappe.form_dict.get('tmp_id') otp = frappe.form_dict.get('otp') if email and not frappe.db.exists('User', email): raise frappe.PermissionError("User does not exist") if not otp: raise frappe.PermissionError("OTP not found") if not tmp_id: raise frappe.PermissionError("ID not found") hotp_token = frappe.cache().get(tmp_id + '_token') otp_secret = frappe.cache().get(tmp_id + '_otp_secret') if not otp_secret: raise frappe.PermissionError("Login expired") hotp = pyotp.HOTP(otp_secret) if hotp_token: if hotp.verify(otp, int(hotp_token)): frappe.cache().delete(tmp_id + '_token') key = _generate_key(email) return key else: raise frappe.PermissionError("OTP does not match") totp = pyotp.TOTP(otp_secret) if totp.verify(otp): key = _generate_key(email) return key else: raise frappe.PermissionError("OTP does not match")
def _add_otp(self, name=None, otp_type=None, secret=None): if not name: self.q.put([Action.ask_input, _("Add OTP to which password?"), "", "add_otp"]) elif not otp_type: screenshot = pyscreenshot.grab(childprocess=False).convert('L') qr_codes = zbar.Scanner().scan(screenshot) autodetected = 0 for qr_code in qr_codes: qr_data = qr_code.data.decode() try: pyotp.parse_uri(qr_data) except ValueError: continue autodetected += 1 self._append_password(name, qr_data) if autodetected == 0: self.q.put([Action.add_error, _("Could not detect any valid OTP QR codes on your screen. Continuing with manual configuration...")]) self.q.put([Action.ask_choice, _("Use which OTP type?"), ["TOTP", "HOTP"], "add_otp {}".format(name)]) else: self.q.put([Action.add_message, _("Detected and added {} valid OTP QR code(s) on your screen.").format(str(autodetected))]) return elif not secret: self.q.put([Action.ask_input, _("What is the OTP secret?"), "", "add_otp {} {}".format(name, otp_type)]) else: if otp_type == "TOTP": otp_uri = pyotp.TOTP(secret).provisioning_uri() elif otp_type == "HOTP": otp_uri = pyotp.HOTP(secret).provisioning_uri() else: return self._append_password(name, otp_uri)
def post(request, phone): try: Mobile = phoneModel.objects.get(phone_number=phone) except ObjectDoesNotExist: return Response("User does not exist", status=404) # False Call keygen = generateKey() key = base64.b32encode( keygen.returnValue(phone).encode()) # Generating Key OTP = pyotp.HOTP(key) # HOTP Model if OTP.verify(request.data["otp"], Mobile.counter): # Verifying the OTP Mobile.isVerified = True Mobile.save() first_name = request.data["first_name"] last_name = request.data['last_name'] phone_number = request.data['phone_number'] password = request.data['password'] user = Account.objects.create_user(first_name=first_name, last_name=last_name, password=password, phone_number=phone_number) user.save() account = Profile.objects.create(account=user, visit_counter=0) account.save() return Response("You are authorised", status=200) return Response("OTP is wrong", status=400)
def cadastrar(request, token, username): hotp = pyotp.HOTP('base32secret3232') crip = Token.objects.get(username=username) if not hotp.verify(token, crip.token): messages.error( request, 'Token invalido, não foi possível fazer a confirmação de email. Tente novamente!' ) return redirect('index') else: form = UserAdminCreationForm() if request.method == 'POST': form = UserAdminCreationForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.username = username user.email = username + '@inf.ufsm.br' user.save() raw_password = form.cleaned_data.get('password1') user = authenticate(username=user.username, password=raw_password) login(request, user) messages.success(request, 'Usuario criado com sucesso') return redirect('accounts:index') else: messages.error(request, 'Dados invalidos') return render(request, 'accounts/cadastro.html', { 'form': form, 'token': token, 'username': username })
def verify_signup(self, request, format='json'): validator = SignUpVerificationValidator(data=request.query_params) if not validator.is_valid(): return Response(validator.errors, status=status.HTTP_400_BAD_REQUEST) if validator.is_valid(): validated_data = validator.validated_data code = validated_data['code'] user_id = int(validated_data['user_id']) confirm_token = ConfirmToken.objects.get(user__id=user_id, kind=SIGNUP_TOKEN) user = User.objects.get(id=int(user_id)) date_time = confirm_token.token_epires_at key = confirm_token.token_hash if (timezone.now() < date_time): counter = int(user.id) hotp = pyotp.HOTP(key) if int(code) == int(hotp.at(counter)): user.is_active = True user.save() confirm_token.delete() data = get_tokens_plus_user(user, request) data["message"] = "Account Activated Successfully" return Response(data, status=status.HTTP_200_OK) else: return Response({"message": "Invalid Code"}, status=status.HTTP_400_BAD_REQUEST) else: return Response({"message": "Code Expired"}, status=status.HTTP_400_BAD_REQUEST)
def check_token(token, secret, counter): hotp = pyotp.HOTP(secret) for i in range(1, 10): if hotp.verify(token, (counter + i)): return counter + i return 0
def _add_otp(self, name=None, otp_type=None, secret=None): if not hasattr(pyotp, "parse_uri"): self.q.put([ Action.critical_error, _("pyotp lib doesn't support this yet") ]) return if not name: self.q.put([ Action.ask_input, _("What password should OTP be added to?"), "", "add_otp" ]) elif not otp_type: screenshot = pyscreenshot.grab(childprocess=False).convert('L') qr_codes = zbar.Scanner().scan(screenshot) autodetected = 0 for qr_code in qr_codes: qr_data = qr_code.data.decode() try: pyotp.parse_uri(qr_data) except ValueError: continue autodetected += 1 self._append_password(name, qr_data) if autodetected == 0: self.q.put([ Action.add_error, _("No valid OTP QR codes detected on your screen. Configuring manually…" ) ]) self.q.put([ Action.ask_choice, _("Which OTP type should be used?"), ["TOTP", "HOTP"], "add_otp {}".format(name) ]) else: self.q.put([ Action.add_message, _("Detected and added {} valid OTP QR code(s) on your screen." ).format(str(autodetected)) ]) return elif not secret: self.q.put([ Action.ask_input, _("What is the OTP secret?"), "", "add_otp {} {}".format(name, otp_type) ]) else: if otp_type == "TOTP": otp_uri = pyotp.TOTP(secret).provisioning_uri() elif otp_type == "HOTP": otp_uri = pyotp.HOTP(secret).provisioning_uri() else: return self._append_password(name, otp_uri)
def check_token(self, user, token): if not (user and token): return False key = base64.b32encode(self._make_hash_value(user).encode()) OTP = pyotp.HOTP(key) # HOTP Model if OTP.verify(token, user.pk): # Verifying the OTP return True return False
def get(self, username): try: userinfo = db.get_user(username) hotp = pyotp.HOTP(userinfo.otp_secret) otp_key = hotp.at(userinfo.hotp_counter) self.write(str(otp_key)) except db.User.DoesNotExist: self.send_error(404)
def create(self, country_code: str, phone_number: int): secret = self._create_secret(secret=pyotp.random_base32(length=32)) counter = self._create_counter() hotp = pyotp.HOTP(secret, digits=self._digits) self._send_sms(sms_code=hotp.at(counter), country_code=country_code, phone_number=phone_number)
def _validate_passcode(passcode): passcode = int(passcode) if session.get('two_factor_counter'): hotp = pyotp.HOTP(app.config['OTP_SECRET']) return hotp.verify(passcode, session['two_factor_counter']) else: totp = pyotp.TOTP(app.config['OTP_SECRET']) return totp.verify(passcode)
def test_other_secret(self): hotp = pyotp.HOTP( 'N3OVNIBRERIO5OHGVCMDGS4V4RJ3AUZOUN34J6FRM4P6JIFCG3ZA') self.assertEqual(hotp.at(0), '737863') self.assertEqual(hotp.at(1), '390601') self.assertEqual(hotp.at(2), '363354') self.assertEqual(hotp.at(3), '936780') self.assertEqual(hotp.at(4), '654019')
def __init__(self, a, b, c, char, exp): self.a, self.b, self.c = a, b, c self.char, self.exp = char, exp print(self) f = open("otp_seed.txt", "r") seed = f.readline().strip() f.close() self.hotp = pyotp.HOTP(seed)
def testHOTPRateLimit(self): logger.debug('Running testHOTPRateLimit') backends = getBackends() # Save custom state for HOTP user, as some backends rely on it to trigger HOTP mode state = totpcgi.GAUserState() state.counter = 1 setCustomState(state, 'hotp') gau = totpcgi.GAUser('hotp', backends) secret = backends.secret_backend.get_user_secret(gau.user) hotp = pyotp.HOTP(secret.otp.secret) token = hotp.at(1) self.assertEqual(gau.verify_token(token), 'Valid HOTP token used') # counter is now at 2 token = '555555' # We now fail 4 times consecutively with self.assertRaisesRegex(totpcgi.VerifyFailed, 'HOTP token failed to verify'): gau.verify_token(token) with self.assertRaisesRegex(totpcgi.VerifyFailed, 'HOTP token failed to verify'): gau.verify_token(token) with self.assertRaisesRegex(totpcgi.VerifyFailed, 'HOTP token failed to verify'): gau.verify_token(token) with self.assertRaisesRegex(totpcgi.VerifyFailed, 'HOTP token failed to verify'): gau.verify_token(token) # We should now get a rate-limited error with self.assertRaisesRegex(totpcgi.VerifyFailed, 'Rate-limit'): gau.verify_token(token) # Same with a valid token with self.assertRaisesRegex(totpcgi.VerifyFailed, 'Rate-limit'): gau.verify_token(hotp.at(2)) # Make sure we recover from rate-limiting correctly old_timestamp = secret.timestamp - (31 + (secret.rate_limit[1] * 10)) state = totpcgi.GAUserState() state.fail_timestamps = [ old_timestamp, old_timestamp, old_timestamp, old_timestamp ] state.counter = 2 setCustomState(state, 'hotp') with self.assertRaisesRegex(totpcgi.VerifyFailed, 'HOTP token failed to verify'): gau.verify_token(token) # Valid token should work, too setCustomState(state, 'hotp') self.assertEqual(gau.verify_token(hotp.at(2)), 'Valid HOTP token used') cleanState('hotp')
def do_verify(): # handle username/password # TODO: CSRF protection username = request.forms.get('username') password = request.forms.get('password') if username and password: logging.info('Verifying username %s and password...', username) handler = OdooAuthHandler() data, session_id = handler.check_login(username, password) if session_id: hotp = pyotp.HOTP(HOTP_SECRET) counter, code = db.next_hotp_id(session_id) key = hotp.at(counter) if not send_mail(username, key): message = 'Mail with security code not sent.' logging.error(message) return template('login', dict(theme_params, error=message)) return template( 'hotp', dict(theme_params.items(), counter=counter, code=code)) else: # TODO: brute force protection # (block for X minutes after X attempts) message = 'Invalid username or password.' logging.info(message) return template('login', dict(theme_params, error=message)) # check HOTP counter = request.forms.get('counter') code = request.forms.get('code') hotp_code = request.forms.get('hotp_code') if code and counter and hotp_code: hotp = pyotp.HOTP(HOTP_SECRET) if not hotp.verify(hotp_code, int(counter)): message = 'Invalid security code.' return template('login', dict(theme_params, error=message)) session_id = db.verify_code_and_expiry(counter, code) if not session_id: message = 'Invalid security code (2).' return template('login', dict(theme_params, error=message)) db.save_session(session_id, EXPIRY_INTERVAL) logging.info('Setting session cookie: %s', session_id) response.set_cookie("session_id", session_id, path='/') return redirect('/') return redirect('/')
def counter_based_otp(): hotp = pyotp.HOTP('base32secret3232') hotp.at(0) # => '260182' hotp.at(1) # => '055283' hotp.at(1401) # => '316439' # OTP verified with a counter hotp.verify('316439', 1401) # => True hotp.verify('316439', 1402) # => False
def verify(self, sms_code: int, phone_number: int) -> str: secret = self._get_secret() count = self._get_counter() if count and secret: hotp = pyotp.HOTP(secret, digits=self._digits) if hotp.verify(sms_code, count): return self._create_token(phone_number=phone_number) return None
def testHOTPBasedComm(): hotp = pyotp.HOTP('base32secret3232') print(hotp.at(0)) # => '260182' print(hotp.at(1)) # => '055283' print(hotp.at(1401)) # => '316439' # OTP verified with a counter print(hotp.verify('316439', 1401)) # => True print(hotp.verify('316439', 1402)) # => False