Beispiel #1
0
 def test_user_auth_success_otp(self):
     """The authentication should be succeeded with OTP."""
     from pyotp.totp import TOTP
     provider = TOTP(self.secret.secret)
     user = self.backend.authenticate(username=self.users[0].username,
                                      password="******",
                                      otp_auth=provider.now())
     self.assertEqual(user, self.users[0])
Beispiel #2
0
 def test_user_auth_failure_otp(self):
     """The authentication should be failed with OTP."""
     from pyotp.totp import TOTP
     provider = TOTP(self.secret.secret)
     user = self.backend.authenticate(
         username=self.users[0].username,
         password="******",
         otp_auth=str(
             (int(provider.now()) + 1) % 1000000).zfill(provider.digits))
     self.assertIsNone(user)
Beispiel #3
0
def totp_verify(request):
    """
    View method for path '/sso/totp/verify'
    """
    #authenticate the request
    if not _auth_bearer(request):
        #not authenticated
        return FORBIDDEN_RESPONSE

    #get the useremail, idp and totpcode
    data = json.loads(request.body.decode())
    logger.debug("verify totp code.{}".format(data))
    user_email = data.get("email")
    if not user_email:
        return HttpResponse(content="Email is missint", status=400)

    idp = data.get("idp")
    if not idp:
        return HttpResponse(content="Idp is missint", status=400)

    totpcode = data.get("totpCode")
    if not totpcode:
        return HttpResponse(content="Totp code is missint", status=400)

    user_totp = models.UserTOTP.objects.filter(email=user_email,
                                               idp=idp).first()
    if not user_totp:
        #can't find user totp object
        return HttpResponse(
            content="User({1}:{0})'s totp secret is missing".format(
                user_email, idp),
            status=400)

    if settings.TOTP_CHECK_LAST_CODE and totpcode == user_totp.last_verified_code:
        #totpcode is the last checked totp code,
        return CONFLICT_RESPONSE

    totp = TOTP(user_totp.secret_key,
                digits=user_totp.digits,
                digest=utils.get_digest_function(user_totp.algorithm)[1],
                name=user_totp.name,
                issuer=user_totp.issuer,
                interval=user_totp.timestep)
    if totp.verify(totpcode, valid_window=settings.TOTP_VALIDWINDOW):
        #verified
        user_totp.last_verified_code = totpcode
        user_totp.last_verified = timezone.now()
        user_totp.save(update_fields=["last_verified", "last_verified_code"])
        logger.debug("Succeed to verify totp code.{}".format(data))
        return SUCCEED_RESPONSE
    else:
        #verify failed.
        logger.debug("Failed to verify totp code.{}".format(data))
        return CONFLICT_RESPONSE
Beispiel #4
0
 def enter_totp(self, otp_secret):
     self.save_screen_shot("ENTER_ONE_TIME_PASS_CODE")
     if otp_secret is None:
         raise Exception("REQUIRED_TOTP_SECRET_IS_EMPTY")
     code = TOTP(otp_secret).now()
     WebDriverWait(self.driver, self.config.timeout_seconds)\
         .until(expected_conditions.element_to_be_clickable((By.ID, GoogleTokenPageElements.TOTPPIN)))
     self.driver.find_element_by_id(GoogleTokenPageElements.TOTPPIN).send_keys(code)
     self.driver.find_element_by_id(GoogleTokenPageElements.SUBMIT).click()
     return True
Beispiel #5
0
    def generatereq(self):
        """
        Generate strings for authentication.

        Message format:
            (
                req_num_connection_number (HEX, 2 bytes) +
                    used_remote_listening_port (HEX, 4 bytes) +
                    sha1(cert_pub),
                pyotp.TOTP(pri_sha1 + ip_in_hex_form + salt),
                main_pw,    # must send in encrypted form to avoid MITM
                ip_in_hex_form,
                salt,
                [cert1,
                cert2   (only when ptproxy is enabled)]
            )
        """
        msg = [""]
        number_in_hex = "%02X" % min((self.req_num), 255)
        msg[0] += number_in_hex
        msg[0] += "%04X" % self.remote_port
        msg[0] += self.clientpub_sha1
        # print(self.clientpub_sha1)
        # print("======================")
        if self.ipv6 == "":
            myip = int2base(self.ip)
        else:
            myip = int2base(
                int(
                    binascii.hexlify(
                        socket.inet_pton(socket.AF_INET6, self.ipv6)),
                    16)) + "G"
        salt = binascii.hexlify(os.urandom(16)).decode("ASCII")
        h = hashlib.sha256()
        h.update((self.clientpri_sha1 + myip + salt +
                  number_in_hex).encode('utf-8'))
        msg.append(TOTP(bytes(h.hexdigest(), "UTF-8")).now())
        msg.append(binascii.hexlify(self.main_pw).decode("ASCII"))
        # print(self.main_pw)
        # print("======================")
        msg.append(myip)
        msg.append(salt)
        if 1 <= self.obfs_level <= 2:
            certs_byte = urlsafe_b64_short_encode(self.certs_send)
            msg.extend([certs_byte[:50], certs_byte[50:]])
        elif self.obfs_level == 3:
            msg.append(''.join(
                [random.choice(ascii_letters) for _ in range(5)]))
        if Mode == "VPS":
            req_type = "00"
        elif Mode == "GAE":
            req_type = "01"
        msg.append(req_type + PROTO_VERSION)
        return '.'.join(msg)
Beispiel #6
0
def create_new_user(user_id):

    user = DATABASE.save_new_user(user_id)

    qr_code = TOTP(user['secret']).provisioning_uri(user['user_id'],
                                                    issuer_name=APP_NAME)

    qr_code_url = f'https://api.qrserver.com/v1/create-qr-code/?size=150x150&data={qr_code}'

    return {
        'user': user['user_id'],
        'qr_code': qr_code,
        'qr_code_url': qr_code_url,
    }
def two_factor_input():
    if current_user.is_authenticated or 'id' not in session:
        return redirect(url_for('proute.index'))
    contributor = Contributor.query.get(session['id'])
    if contributor is None:
        return redirect(url_for('proute.index'))
    form = GetTotp()
    if form.validate_on_submit():
        if TOTP(contributor.totp_key).verify(int(form.totp_code.data), valid_window=5):
            login_user(contributor, remember=session['remember_me'])
            flash("Congratulations, you are now logged in!")
            return redirect(url_for('proute.index'))
        else:
            flash("Oops, the pin was wrong")
            form.totp_code.data = None
            return render_template('two_factor_input.html', form=form, inst="Code was wrong, try again?")
    return render_template('two_factor_input.html', form=form, inst="Enter Auth Code")
Beispiel #8
0
 def get_current_totp_code(totp_key):
     return TOTP(totp_key).now()
Beispiel #9
0
 def verify_totp_code(totp_key, totp_code):
     return TOTP(totp_key).verify(totp_code)
Beispiel #10
0
def verify_user_code(user_id, code):
    user = DATABASE.get_user(user_id)
    return TOTP(user['secret']).verify(code)
Beispiel #11
0
def parse_uri(uri):
    """
    Parses the provisioning URI for the OTP; works for either TOTP or HOTP.

    See also:
        https://github.com/google/google-authenticator/wiki/Key-Uri-Format

    :param uri: the hotp/totp URI to parse
    :type uri: str
    :returns: OTP object
    :rtype: OTP
    """

    # Secret (to be filled in later)
    secret = None

    # Data we'll parse to the correct constructor
    otp_data = {}

    # Parse with URLlib
    parsed_uri = urlparse(unquote(uri))

    if parsed_uri.scheme != 'otpauth':
        raise ValueError('Not an otpauth URI')

    # Parse issuer/accountname info
    accountinfo_parts = split(':|%3A', parsed_uri.path[1:], maxsplit=1)
    if len(accountinfo_parts) == 1:
        otp_data['name'] = accountinfo_parts[0]
    else:
        otp_data['issuer'] = accountinfo_parts[0]
        otp_data['name'] = accountinfo_parts[1]

    # Parse values
    for key, value in parse_qsl(parsed_uri.query):
        if key == 'secret':
            secret = value
        elif key == 'issuer':
            if 'issuer' in otp_data and otp_data[
                    'issuer'] is not None and otp_data['issuer'] != value:
                raise ValueError(
                    'If issuer is specified in both label and parameters, it should be equal.'
                )
            otp_data['issuer'] = value
        elif key == 'algorithm':
            if value == 'SHA1':
                otp_data['digest'] = hashlib.sha1
            elif value == 'SHA256':
                otp_data['digest'] = hashlib.sha256
            elif value == 'SHA512':
                otp_data['digest'] = hashlib.sha512
            else:
                raise ValueError(
                    'Invalid value for algorithm, must be SHA1, SHA256 or SHA512'
                )
        elif key == 'digits':
            digits = int(value)
            if digits not in [6, 8]:
                raise ValueError('Digits may only be 6 or 8')
            otp_data['digits'] = digits
        elif key == 'period':
            otp_data['interval'] = value
        elif key == 'counter':
            otp_data['initial_count'] = value
        else:
            raise ValueError('{} is not a valid parameter'.format(key))

    if not secret:
        raise ValueError('No secret found in URI')

    # Create objects
    if parsed_uri.netloc == 'totp':
        return TOTP(secret, **otp_data)
    elif parsed_uri.netloc == 'hotp':
        return HOTP(secret, **otp_data)

    raise ValueError('Not a supported OTP type')