def new(self, id=None):
        """Set up a users new security TOTP credentials"""
        context = {
            'model': model, 'session': model.Session,
            'user': c.user, 'auth_user_obj': c.userobj
        }
        # pylons includes the rest of the url in the param, so we need to strip the /new suffix
        user_id = id.replace('/new', '')

        data_dict = {'id': user_id, 'user_obj': c.userobj}
        user_dict = self._fetch_user_or_fail(context, data_dict)
        SecurityTOTP.create_for_user(user_dict['name'])
        self._setup_totp_template_variables(context, data_dict)
        log.info("Rotated the 2fa secret for user {}".format(user_id))
        helpers.flash_success(_('Successfully updated two factor authentication secret. Make sure you add the new secret to your authenticator app.'))
        helpers.redirect_to('mfa_configure', id=user_id)
Beispiel #2
0
 def reset_totp(self, username):
     print('Resetting totp secret for user', username)
     from ckanext.security.model import SecurityTOTP
     SecurityTOTP.create_for_user(username)
     print('Success!')
Beispiel #3
0
    def login(self):
        """
        Ajax call to test username/password/mfa code
        """
        tk.response.headers.update({'Content-Type': 'application/json'})

        try:
            res = {}
            if request.method != 'POST':
                tk.response.status_int = 405
                return json.dumps(res)

            identity = request.params
            if not ('login' in identity and 'password' in identity):
                tk.response.status_int = 422
                return json.dumps(res)

            user_name = identity['login']
            user = model.User.by_name(user_name)

            login_throttle_key = get_login_throttle_key(request, user_name)
            if login_throttle_key is None:
                tk.response.status_int = 403
                return json.dumps(res)

            throttle = LoginThrottle(user, login_throttle_key)
            locked_out = throttle.is_locked()
            if locked_out:
                log.info(
                    'User {} attempted login while brute force lockout in place'
                    .format(user_name))

            invalid_login = user is None or not user.is_active(
            ) or not user.validate_password(identity['password'])
            if invalid_login:
                # Increment the throttle counter if the login failed.
                throttle.increment()

            if locked_out or invalid_login:
                log.info('login failed')
                tk.response.status_int = 403
                return json.dumps(res)

            # find or create 2 factor auth record
            totp_challenger = SecurityTOTP.get_for_user(user.name)
            if totp_challenger is None:
                totp_challenger = SecurityTOTP.create_for_user(user.name)

            mfaConfigured = totp_challenger.last_successful_challenge is not None
            if not mfaConfigured:
                res['totpSecret'] = totp_challenger.secret
                res['totpChallengerURI'] = totp_challenger.provisioning_uri

            res['mfaConfigured'] = mfaConfigured

            if identity['mfa']:
                res['mfaCodeValid'] = totp_challenger.check_code(
                    identity['mfa'], verify_only=True)

            return json.dumps(res)

        except Exception as err:
            log.error('Unhandled error during login: {}'.format(err))
            tk.response.status_int = 500
            return json.dumps({})
    def login(self):
        """
        Ajax call to test username/password/mfa code
        """

        def set_response(status):
            tk.response.status_int = status
            tk.response.headers.update({'Content-Type': 'application/json'})

        try:
            res = {}
            if request.method != 'POST':
                set_response(405)
                return json.dumps(res)

            identity = request.params
            if not ('login' in identity and 'password' in identity):
                set_response(422)
                return json.dumps(res)

            on_mfa_form = identity.get('mfa-form-active') == 'true'

            user_name = identity['login']
            user = model.User.by_name(user_name)

            login_throttle_key = get_login_throttle_key(request, user_name)
            if login_throttle_key is None:
                set_response(403)
                return json.dumps(res)

            throttle = LoginThrottle(user, login_throttle_key)
            locked_out = throttle.is_locked()
            if locked_out:
                log.info('User %s attempted login while brute force lockout in place', user_name)

            invalid_login = user is None or not user.is_active() or not user.validate_password(identity['password'])
            if invalid_login:
                # Increment the throttle counter if the login failed.
                throttle.increment()

            if invalid_login or (locked_out and not on_mfa_form):
                log.info('login failed for %s', user_name)
                set_response(403)
                return json.dumps(res)

            # find or create 2 factor auth record
            totp_challenger = SecurityTOTP.get_for_user(user.name)
            if totp_challenger is None:
                totp_challenger = SecurityTOTP.create_for_user(user.name)

            mfaConfigured = totp_challenger.last_successful_challenge is not None
            if not mfaConfigured:
                res['totpSecret'] = totp_challenger.secret
                res['totpChallengerURI'] = totp_challenger.provisioning_uri

            res['mfaConfigured'] = mfaConfigured
            set_response(200)

            if identity['mfa']:
                code_valid = totp_challenger.check_code(identity['mfa'], verify_only=True)
                res['mfaCodeValid'] = code_valid and not locked_out
                if code_valid:
                    log.info('Login succeeded for %s', user_name)
                else:
                    log.info('User %s supplied invalid 2fa code', user_name)
                    set_response(403)
                    throttle.increment()

            return json.dumps(res)

        except Exception as err:
            log.error('Unhandled error during login: %s', err)
            set_response(500)
            return json.dumps({})