def verify_authentication(resolver_client: ResolverClient, token: str) -> dict:
        """
        Verify if the authentication token is allowed for authentication.
        :param resolver_client: resolver client interface
        :param token: jwt authentication token
        :return: decoded verified authentication token

        :raises:
            IdentityAuthenticationFailed: if not allowed for authentication
        """
        try:
            unverified_token = JwtTokenHelper.decode_token(token)
            for field in ('iss', 'sub', 'aud', 'iat', 'exp'):
                if field not in unverified_token:
                    raise IdentityValidationError(f'Invalid token, missing {field} field')
            issuer = Issuer.from_string(unverified_token['iss'])
            doc = resolver_client.get_document(issuer.did)
            get_controller_doc = resolver_client.get_document
            issuer_key = RegisterDocumentHelper.get_valid_issuer_key_for_auth(doc, issuer.name, get_controller_doc)
            if not issuer_key:
                raise IdentityInvalidRegisterIssuerError(f'Invalid issuer {issuer}')
            verified_token = JwtTokenHelper.decode_and_verify_token(token, issuer_key.public_key_base58,
                                                                    unverified_token['aud'])

            IdentityAuthValidation.validate_allowed_for_auth(resolver_client, issuer_key.issuer, verified_token['sub'])

            return {'iss': verified_token['iss'],
                    'sub': verified_token['sub'],
                    'aud': verified_token['aud'],
                    'iat': verified_token['iat'],
                    'exp': verified_token['exp']}
        except (IdentityValidationError, IdentityResolverError,
                IdentityInvalidRegisterIssuerError, IdentityNotAllowed) as err:
            raise IdentityAuthenticationFailed('Not authenticated') from err
Exemple #2
0
    def from_challenge_token(resolver_client: ResolverClient,
                             challenge_token: str) -> 'Proof':
        """
        Build proof from challenge token.
        :param resolver_client: resolver client to get the registered documents
        :param challenge_token: jwt challenge token
        :return: valid proof

        :raises:
            IdentityValidationError: if invalid challenge token
        """
        decoded_token = JwtTokenHelper.decode_token(challenge_token)
        iss = decoded_token.get('iss')
        aud = decoded_token.get('aud')
        if not iss or not aud:
            raise IdentityValidationError(
                'Invalid challenge token, missing \'iss\' or \'aud\'')

        issuer = Issuer.from_string(iss)
        doc = resolver_client.get_document(issuer.did)
        get_controller_doc = resolver_client.get_document
        issuer_key = RegisterDocumentHelper.get_valid_issuer_key_for_control_only(
            doc, issuer.name, get_controller_doc)
        if not issuer_key:
            raise IdentityInvalidRegisterIssuerError(
                f'Invalid issuer {issuer}')
        verified_token = JwtTokenHelper.decode_and_verify_token(
            challenge_token, issuer_key.public_key_base58, aud)
        return Proof(issuer_key.issuer, aud.encode('ascii'),
                     verified_token['proof'])
Exemple #3
0
    def get_valid_doc_from_token(
            token: str,
            get_controller_doc: GetControllerDocFunc) -> RegisterDocument:
        """
        Get a valid RegisterDocument from a resolver token.
        :param token: resolver token
        :param get_controller_doc: get controller register document function
        :return: valid register document

        :raises:
            IdentityResolverError: if invalid token
            IdentityResolverError: if invalid document
        """
        try:
            unverified = JwtTokenHelper.decode_token(token)
            doc = RegisterDocumentBuilder().build_from_dict(unverified['doc'])
            issuer = Issuer.from_string(unverified['iss'])
            issuer_key = RegisterDocumentHelper.get_valid_issuer_key_for_control_only(
                doc, issuer.name, get_controller_doc)
            if not issuer_key:
                raise IdentityInvalidRegisterIssuerError(
                    f'Invalid issuer {issuer}')
            JwtTokenHelper.decode_and_verify_token(
                token, issuer_key.public_key_base58, unverified['aud'])
            return doc
        except (KeyError, ValueError, IdentityValidationError,
                IdentityInvalidRegisterIssuerError) as exc:
            raise IdentityResolverError(
                f'Can not deserialized invalid resolver token: \'{exc}\''
            ) from exc
Exemple #4
0
    def build_from_dict(self, data: dict) -> RegisterDocument:
        """
        Build a valid immutable register document from dict.
        :param data: register document as dict
        :return: valid register document

        :raises:
            IdentityInvalidDocumentError: if invalid dict data
            IdentityInvalidDocumentError: if invalid document
            IdentityRegisterDocumentKeyConflictError: if key name is not unique
        """
        try:
            for k in data['publicKey']:
                self.add_public_key_obj(RegisterPublicKey.from_dict(k))
            for k in data.get('authentication', []):
                self.add_authentication_key_obj(RegisterAuthenticationPublicKey.from_dict(k))
            for k in data.get('delegateAuthentication', []):
                self.add_authentication_delegation_obj(RegisterDelegationProof.from_dict(k))
            for k in data.get('delegateControl', []):
                self.add_control_delegation_obj(RegisterDelegationProof.from_dict(k))
            raw_controller = data.get('controller')
            controller = Issuer.from_string(raw_controller) if raw_controller else None
            return self.build(data['id'], DIDType(data['ioticsDIDType']), data['proof'], data.get('revoked', False),
                              Metadata.from_dict(data.get('metadata', {})), data.get('creator'),
                              data['ioticsSpecVersion'], data['updateTime'], controller)
        except (TypeError, KeyError, ValueError) as err:
            raise IdentityInvalidDocumentError(f'Can not parse invalid register document: \'{err}\'') from err
Exemple #5
0
def auth_deleg_proof():
    issuer1 = Issuer.from_string(
        'did:iotics:iotHHHHKpPGWyEC4FFo4d6oyzVVk6MXLmEgY#ctrl1')
    issuer2 = Issuer.from_string(
        'did:iotics:iotHHHHKpPGWyEC4FFo4d6oyzVVk6MXLmEgY#ctrl2')
    issuer3 = Issuer.from_string(
        'did:iotics:iotHHHHKpPGWyEC4FFo4d6oyzVVk6MXLmEgY#ctrl3')
    return {
        '#DelegAuthKey1':
        RegisterDelegationProof.build('#DelegAuthKey1',
                                      issuer1,
                                      proof='proof',
                                      revoked=False),
        '#DelegAuthKey2':
        RegisterDelegationProof.build('#DelegAuthKey2',
                                      issuer2,
                                      proof='proof',
                                      revoked=False),
        '#DelegAuthKey3':
        RegisterDelegationProof.build('#DelegAuthKey3',
                                      issuer3,
                                      proof='proof',
                                      revoked=False),
    }
    def from_dict(data: dict):
        """
        Build a register delegation public key from dict.
        :param data: register delegation public key as dict
        :return: valid register delegation key

        :raises:
            IdentityValidationError: if invalid register delegation public key as dict
        """
        try:
            controller = Issuer.from_string(data['controller'])
            proof_type = DelegationProofType(data.get('proofType', DelegationProofType.DID.value))
            return RegisterDelegationProof.build(data['id'], controller, data['proof'],
                                                 data.get('revoked', False),
                                                 proof_type)
        except (TypeError, KeyError, ValueError) as err:
            raise IdentityValidationError(f'Can not parse invalid register delegation proof: \'{err}\'') from err
Exemple #7
0
def test_can_build_issuer_from_string_with_invalid_string_raises_validation_error(did):
    with pytest.raises(IdentityValidationError):
        Issuer.from_string(f'{did}aNameWithoutSep')
Exemple #8
0
def test_building_issuer_from_string_with_invalid_did_raises_validation_error(name):
    with pytest.raises(IdentityValidationError):
        Issuer.from_string(f'invalidDID{name}')
Exemple #9
0
def test_building_issuer_from_string_with_invalid_name_raises_validation_error(did):
    with pytest.raises(IdentityValidationError):
        Issuer.from_string(f'{did}#invalid name')
Exemple #10
0
def test_can_build_issuer_from_string(did, name):
    issuer_string = f'{did}{name}'
    issuer = Issuer.from_string(issuer_string)
    assert issuer.did == did
    assert issuer.name == name
Exemple #11
0
def test_can_build_a_register_doc_from_an_other_doc_overriding_values(
        full_doc):
    existing_doc = full_doc
    new_creator = 'did:iotics:iotEEEEKpPGWyEC4FFo4d6oyzVVk6MEEEEgY'
    new_controller = Issuer.build(
        'did:iotics:iotEEEEKpPGWyEC4FFo4d6oyzHHHHMEEEEgY', '#NewController')
    new_metadata = Metadata(label='a label')
    new_version = SUPPORTED_VERSIONS[0]
    new_pub_key = RegisterPublicKey(name='#new_pub_key1',
                                    base58=get_public_base_58_key(),
                                    revoked=False)
    new_auth_key = RegisterAuthenticationPublicKey(
        name='#new_auth_key1', base58=get_public_base_58_key(), revoked=False)
    a_controller = Issuer.from_string(
        'did:iotics:iotHjrmKpPGWyEC4FFo4d6oyzVVk6MXEEEEE#AController')
    new_control_deleg_proof = RegisterDelegationProof(
        name='#new_deleg_control_key1',
        controller=a_controller,
        proof='a_deleg_proof_validated_by_the_resolver',
        revoked=False)
    new_auth_deleg_key = RegisterDelegationProof(
        name='#new_deleg_auth_key1',
        controller=a_controller,
        proof='a_deleg_proof_validated_by_the_resolver',
        revoked=False)

    new_doc = RegisterDocumentBuilder() \
        .add_public_key_obj(new_pub_key) \
        .add_authentication_key_obj(new_auth_key) \
        .add_control_delegation_obj(new_control_deleg_proof) \
        .add_authentication_delegation_obj(new_auth_deleg_key) \
        .build_from_existing(existing_doc,
                             revoked=True,
                             metadata=new_metadata,
                             creator=new_creator,
                             spec_version=new_version,
                             controller=new_controller)
    # Can not change
    assert new_doc.did == existing_doc.did
    assert new_doc.purpose == existing_doc.purpose
    assert new_doc.proof == existing_doc.proof
    # Overridden values
    assert new_doc.revoked
    assert new_doc.metadata == new_metadata
    assert new_doc.creator == new_creator
    assert new_doc.spec_version == new_version
    assert new_doc.controller == new_controller

    assert new_doc.public_keys == {
        **existing_doc.public_keys,
        **{
            new_pub_key.name: new_pub_key
        }
    }
    assert new_doc.auth_keys == {
        **existing_doc.auth_keys,
        **{
            new_auth_key.name: new_auth_key
        }
    }
    assert new_doc.control_delegation_proof == {
        **existing_doc.control_delegation_proof,
        **{
            new_control_deleg_proof.name: new_control_deleg_proof
        }
    }
    assert new_doc.auth_delegation_proof == {
        **existing_doc.auth_delegation_proof,
        **{
            new_auth_deleg_key.name: new_auth_deleg_key
        }
    }
    assert new_doc.update_time >= existing_doc.update_time