Example #1
0
 def test_fail_uri_verification_if_invalid_insecure(self):
     bad_bitid_uri = bitid.build_uri(SEC_CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
     bad_bitid_uri = bitid.build_uri(CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, SEC_CALLBACK_URI)
     self.assertFalse(is_valid)
Example #2
0
 def test_fail_uri_verification_if_invalid_insecure(self):
     bad_bitid_uri = bitid.build_uri(SEC_CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
     bad_bitid_uri = bitid.build_uri(CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, SEC_CALLBACK_URI)
     self.assertFalse(is_valid)
def check_signature(callback_uri):
    # Extracts data from the posted request (from form of from json data according to the method used by the client)
    container = request.get_json(False, True, False) if request.mimetype == "application/json" else request.form
    bitid_uri = container["uri"]
    signature = container["signature"]
    address   = container["address"]
    # Checks the address
    if not bitid.address_valid(address, USE_TESTNET):
        return (False, None, address, "Address is invalid or not legal")
    # Checks the bitid uri
    if not bitid.uri_valid(bitid_uri, callback_uri):
        return (False, None, address, "BitID URI is invalid or not legal")
    # Checks the signature
    if not bitid.signature_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
        return (False, None, address, "Signature is incorrect")
    
    # Note that the previous 3 steps could also be done in 1 step with following code:
    # if not bitid.challenge_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
    #    return (False, "Sorry but something does not match")
    
    # Checks the nonce
    nid = bitid.extract_nonce(bitid_uri)
    # Tries to retrieve the nonce from db
    nonce = nonce_db_service.get_nonce_by_nid(nid)
    if nonce is None:
        return (False, None, address, "NONCE is illegal")
    elif nonce.has_expired():
        nonce_db_service.delete_nonce(nonce)
        return (False, None, address, "NONCE has expired")
    # Everything is  ok
    return (True, nonce, address, "")
def check_signature(callback_uri):
    # Extracts data from the posted request (from form of from json data according to the method used by the client)
    container = request.get_json(
        False, True,
        False) if request.mimetype == "application/json" else request.form
    bitid_uri = container["uri"]
    signature = container["signature"]
    address = container["address"]
    # Checks the address
    if not bitid.address_valid(address, USE_TESTNET):
        return (False, None, address, "Address is invalid or not legal")
    # Checks the bitid uri
    if not bitid.uri_valid(bitid_uri, callback_uri):
        return (False, None, address, "BitID URI is invalid or not legal")
    # Checks the signature
    if not bitid.signature_valid(address, signature, bitid_uri, callback_uri,
                                 USE_TESTNET):
        return (False, None, address, "Signature is incorrect")

    # Note that the previous 3 steps could also be done in 1 step with following code:
    # if not bitid.challenge_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
    #    return (False, "Sorry but something does not match")

    # Checks the nonce
    nid = bitid.extract_nonce(bitid_uri)
    # Tries to retrieve the nonce from db
    nonce = nonce_db_service.get_nonce_by_nid(nid)
    if nonce is None:
        return (False, None, address, "NONCE is illegal")
    elif nonce.has_expired():
        nonce_db_service.delete_nonce(nonce)
        return (False, None, address, "NONCE has expired")
    # Everything is  ok
    return (True, nonce, address, "")
Example #5
0
 def test_fail_uri_verification_if_missing_nonce(self):
     bad_bitid_uri = "%s%s" % (NETLOC, PATH)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #6
0
 def test_fail_uri_verification_if_invalid_callback_url(self):
     bad_bitid_uri = "%s%s?x=%s" % (NETLOC, PATH, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #7
0
 def test_fail_uri_verification_if_bad_scheme(self):
     bad_bitid_uri = "%s?x=%s" % (CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #8
0
 def test_fail_uri_verification_if_bad_uri(self):
     is_valid = bitid.uri_valid("garbage", CALLBACK_URI)
     self.assertFalse(is_valid)
Example #9
0
 def test_verify_uri(self):
     bitid_uri = bitid.build_uri(CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bitid_uri, CALLBACK_URI)
     self.assertTrue(is_valid)
Example #10
0
def callback():
    '''
    This function validates the response sent by the client about the challenge
    This is the route called by the bitcoin wallet when the challenge has been signed
    '''
    # Retrieves the callback uri
    callback_uri = get_callback_uri()
    # Extracts data from the posted request (from form of from json data according to the method used by the client)
    container = request.get_json(
        False, True,
        False) if request.mimetype == "application/json" else request.form
    bitid_uri = container["uri"]
    signature = container["signature"]
    address = container["address"]

    #
    # Let's start by a bunch of validations
    #

    # Checks the address
    if not bitid.address_valid(address, USE_TESTNET):
        return jsonify(message="Address is invalid or not legal"), 401
    # Checks the bitid uri
    if not bitid.uri_valid(bitid_uri, callback_uri):
        return jsonify(message="BitID URI is invalid or not legal"), 401
    # Checks the signature
    if not bitid.signature_valid(address, signature, bitid_uri, callback_uri,
                                 USE_TESTNET):
        return jsonify(message="Signature is incorrect"), 401

    # Note that the previous 3 steps could also be done in 1 step with following code:
    # if not bitid.challenge_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
    #    return jsonify(message = "Sorry but something does not match"), 401

    # Checks the nonce
    nid = bitid.extract_nonce(bitid_uri)
    # Tries to retrieve the nonce from db
    nonce = nonce_db_service.get_nonce_by_nid(nid)
    if nonce is None:
        return jsonify(message="NONCE is illegal"), 401
    elif nonce.has_expired():
        nonce_db_service.delete_nonce(nonce)
        return jsonify(message="NONCE has expired"), 401

    #
    # So good so far, everything seems ok
    # It's time to check if we have a sign out or a sign in
    #

    # Checks if a user with the given address has already been registered in db (sign in)
    user = user_db_service.get_user_by_address(address)
    # If we have a sign out
    if user is None:
        # Here, we have an important check to do in order to avoid flooding of the users db
        # Let's check for a proof of goodwill (@see pybitid_demo.services.fake_tx_db_service)
        if not tx_db_service.check_proof_of_goodwill(address):
            return jsonify(message="Address is invalid or not legal"), 401
        else:
            # Creates a new user and stores it in db
            user = User(address)
            if not user_db_service.create_user(user):
                return jsonify(
                    message="Ooops ! Something went wrong but we work on it"
                ), 500

    # To finalize the authentication, let's set the user id in the nonce and update it in db
    nonce.uid = user.uid
    if not nonce_db_service.update_nonce(nonce):
        return jsonify(
            message="Ooops ! Something went wrong but we work on it"), 500
    # Everything was ok: user is authenticated
    return jsonify(address=address, nonce=nonce.sid)
Example #11
0
 def test_fail_uri_verification_if_invalid_callback_url(self):
     bad_bitid_uri = "%s%s?x=%s" % (NETLOC, PATH, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #12
0
 def test_fail_uri_verification_if_bad_scheme(self):
     bad_bitid_uri = "%s?x=%s" % (CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #13
0
 def test_fail_uri_verification_if_bad_uri(self):
     is_valid = bitid.uri_valid("garbage", CALLBACK_URI)
     self.assertFalse(is_valid)
Example #14
0
 def test_verify_uri(self):
     bitid_uri = bitid.build_uri(CALLBACK_URI, NONCE)
     is_valid = bitid.uri_valid(bitid_uri, CALLBACK_URI)
     self.assertTrue(is_valid)
Example #15
0
 def test_fail_uri_verification_if_missing_nonce(self):
     bad_bitid_uri = "%s%s" % (NETLOC, PATH)
     is_valid = bitid.uri_valid(bad_bitid_uri, CALLBACK_URI)
     self.assertFalse(is_valid)
Example #16
0
    def authenticate(self, bitid_uri=None, callback_uri=None, 
                     signature=None, address=None, errors=[]):
        if bitid_uri is None or callback_uri is None or signature is None or address is None:
            errors.append('Invalid parameters')
            return None

        #
        # Let's start by a bunch of validations
        #

        use_testnet = getattr(settings, 'BITID_USE_TESTNET', self.USE_TESTNET_DEFAULT)
    
        # Checks the address
        if not bitid.address_valid(address, use_testnet):
            errors.append("Address is invalid or not legal")
            return None
        # Checks the bitid uri
        if not bitid.uri_valid(bitid_uri, callback_uri):
            errors.append("BitID URI is invalid or not legal")
            return None
        # Checks the signature
        if not bitid.signature_valid(address, signature, 
                                     bitid_uri, callback_uri,
                                     use_testnet):
            errors.append("Signature is incorrect")
            return None

        # Checks the nonce
        nid = bitid.extract_nonce(bitid_uri)
        # Tries to retrieve the nonce from db
        try:
            nonce = Nonce.objects.get(nid=nid)
        except ObjectDoesNotExist:
            errors.append("NONCE is illegal")
            return None

        if nonce.has_expired():
            nonce.delete()
            errors.append("NONCE has expired")
            return None
        
        #
        # So good so far, everything seems ok
        # It's time to check if we have a sign out or a sign in
        #


        # Checks if a user with the given address has already been registered in db (sign in)
        try:
            user = User.objects.get(username=address)
        except ObjectDoesNotExist:
            # Here, we have an important check to do in order to avoid flooding of the users db
            # Let's check for a proof of goodwill (@see pybitid_demo.services.fake_tx_db_service)
            if not self.goodwill_check(address):
                errors.append("Address is invalid or not legal")
                return None
            # Creates a new user and stores it in db
            user = User.objects.create_user(username=address)
            user.save()

        # To finalize the authentication, let's set the user id in the nonce and update it in db
        nonce.user = user
        nonce.save()

        return user
Example #17
0
def callback():
    '''
    This function validates the response sent by the client about the challenge
    This is the route called by the bitcoin wallet when the challenge has been signed
    '''
    # Retrieves the callback uri
    callback_uri = get_callback_uri()
    # Extracts data from the posted request (from form of from json data according to the method used by the client)
    container = request.get_json(False, True, False) if request.mimetype == "application/json" else request.form
    bitid_uri = container["uri"]
    signature = container["signature"]
    address   = container["address"]
        
    #
    # Let's start by a bunch of validations
    #
    
    # Checks the address
    if not bitid.address_valid(address, USE_TESTNET):
        return jsonify(message = "Address is invalid or not legal"), 401
    # Checks the bitid uri
    if not bitid.uri_valid(bitid_uri, callback_uri):
        return jsonify(message = "BitID URI is invalid or not legal"), 401
    # Checks the signature
    if not bitid.signature_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
        return jsonify(message = "Signature is incorrect"), 401
    
    # Note that the previous 3 steps could also be done in 1 step with following code:
    # if not bitid.challenge_valid(address, signature, bitid_uri, callback_uri, USE_TESTNET):
    #    return jsonify(message = "Sorry but something does not match"), 401
    
    # Checks the nonce
    nid = bitid.extract_nonce(bitid_uri)
    # Tries to retrieve the nonce from db
    nonce = nonce_db_service.get_nonce_by_nid(nid)
    if nonce is None:
        return jsonify(message = "NONCE is illegal"), 401
    elif nonce.has_expired():
        nonce_db_service.delete_nonce(nonce)
        return jsonify(message = "NONCE has expired"), 401
        
    #
    # So good so far, everything seems ok
    # It's time to check if we have a sign out or a sign in
    #
    
    # Checks if a user with the given address has already been registered in db (sign in)
    user = user_db_service.get_user_by_address(address)
    # If we have a sign out
    if user is None:
        # Here, we have an important check to do in order to avoid flooding of the users db
        # Let's check for a proof of goodwill (@see pybitid_demo.services.fake_tx_db_service) 
        if not tx_db_service.check_proof_of_goodwill(address):
            return jsonify(message = "Address is invalid or not legal"), 401
        else:
            # Creates a new user and stores it in db
            user = User(address)
            if not user_db_service.create_user(user):
                return jsonify(message = "Ooops ! Something went wrong but we work on it"), 500
    
    # To finalize the authentication, let's set the user id in the nonce and update it in db
    nonce.uid = user.uid
    if not nonce_db_service.update_nonce(nonce):
        return jsonify(message = "Ooops ! Something went wrong but we work on it"), 500
    # Everything was ok: user is authenticated
    return jsonify(address = address, nonce = nonce.sid)