Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Account Security for the Fashionable App Developer

Account Security for the Fashionable App Developer

In the same way that we feel safe giving our info to some app and nervous giving our info to other apps, your users have some feeling of safety or concern with the apps you develop. We’ll go over design patterns and Python libraries that will help you protect your user’s accounts.

Given at PyCascades 2019

Philip James

February 24, 2019
Tweet

More Decks by Philip James

Other Decks in Technology

Transcript

  1. #pycascades @asheeshlaroia @phildini 1. Make it costly to take over

    an account 2. Help users stay informed 3. Empower users to defend themselves
  2. #pycascades @asheeshlaroia @phildini hIps:/ /www.teamsid.com/100-worst-passwords-top-50/ #9 qwerty #8 sunshine #7

    1234567 #6 111111 #5 12345 #4 12345678 #3 123456789 #2 password #1 123456
  3. #pycascades @asheeshlaroia @phildini “We have had no reported or confirmed

    account takeovers since implemendng security keys at Google” hIps:/ /krebsonsecurity.com/2018/07/google-security-keys-neutralized-employee-phishing/
  4. #pycascades @asheeshlaroia @phildini MFA Summary • SMS (Twilio, etc.) •

    TOTP (Google Authendcator) (pyotp) • U2F (python-u2flib-server)
  5. #pycascades @asheeshlaroia @phildini Email Login Implementadon • hIps:/ /github.com/skorokithakis/django-tokenauth •

    store sha(token) in your database • big-ish index size • remember password resets
  6. #pycascades @asheeshlaroia @phildini from django.contrib.auth.signals import user_logged_in from django.dispatch import

    receiver from my_app.email import send_login_notification @receiver(user_logged_in) def check_for_suspicious_login(sender, request, user): if user.last_ip != request.ip: send_login_notification(user)
  7. #pycascades @asheeshlaroia @phildini from django.contrib import messages @receiver(user_logged_in) def check_for_suspicious_login(sender,

    request, user): if user.last_ip != request.ip: send_login_notification(user) messages.add_message( request, messages.INFO, 'Login from new IP address!', )
  8. #pycascades @asheeshlaroia @phildini class MyAppUser(User): __password_at_init = None ... def

    __init__(self, *args, **kwargs): super(MyAppUser, self).__init__(*args, **kwargs) self.__password_at_init = self.password … def save(self, *args, **kwargs): if self.password != self.__password_at_init: send_password_change_notification() super(MyAppUser, self).save(*args, **kwargs) self.__password_at_init = self.password
  9. #pycascades @asheeshlaroia @phildini Password: Confirm Password & Upgrade By confirming

    your password, you will enter “sudo mode”. We won’t ask for your password for some time after. /sudo?next=/account&reason=upgrade
  10. #pycascades @asheeshlaroia @phildini def require_sudo_mode(reason): FIVE_MINUTES_AGO = now() - timedelta(seconds=300)

    if request.session.last_authenticated > FIVE_MINUTES_AGO: return else: redirect_to = redirect_to( "/sudo", {"next": request.referer, "reason": reason}, ) hIps:/ /github.com/jusdnmayer/django-elevate
  11. #pycascades @asheeshlaroia @phildini Summary 1. Make it costly to take

    over an account 2. Help users stay informed 3. Empower users to defend themselves Asheesh Laroia - @asheeshlaroia
 Philip James - @phildini