diff --git a/end2end-tests/tests/common/cert.rs b/end2end-tests/tests/common/cert.rs
index 021dfa2ea970f5b75bd89d618739255631be74f6..6e1a363be9c512faabc9ab4efe6e09cb1b9ff45a 100644
--- a/end2end-tests/tests/common/cert.rs
+++ b/end2end-tests/tests/common/cert.rs
@@ -18,7 +18,7 @@ use super::node_runtime::runtime_types::gdev_runtime;
 use super::node_runtime::runtime_types::pallet_certification;
 use super::*;
 use sp_keyring::AccountKeyring;
-use subxt::{sp_runtime::MultiAddress, PairSigner};
+use subxt::{sp_runtime::MultiAddress, PairSigner, Signer};
 
 pub async fn certify(
     api: &Api,
@@ -26,15 +26,29 @@ pub async fn certify(
     from: AccountKeyring,
     to: AccountKeyring,
 ) -> Result<()> {
-    let from = PairSigner::new(from.pair());
+    let signer = PairSigner::new(from.pair());
+    let from = from.to_account_id();
     let to = to.to_account_id();
 
+    let issuer_index = api
+        .storage()
+        .identity()
+        .identity_index_of(from, None)
+        .await?
+        .unwrap();
+    let receiver_index = api
+        .storage()
+        .identity()
+        .identity_index_of(to, None)
+        .await?
+        .unwrap();
+
     let _events = create_block_with_extrinsic(
         client,
         api.tx()
             .cert()
-            .add_cert(to)
-            .create_signed(&from, ())
+            .add_cert(issuer_index, receiver_index)
+            .create_signed(&signer, ())
             .await?,
     )
     .await?;
diff --git a/pallets/certification/src/lib.rs b/pallets/certification/src/lib.rs
index 1c3e5936d0884f406f787b28dc4ffa3dcac896fc..a7e20c39d5103daa613252e3edd5b630c5162e6a 100644
--- a/pallets/certification/src/lib.rs
+++ b/pallets/certification/src/lib.rs
@@ -68,8 +68,8 @@ pub mod pallet {
             + MaybeSerializeDeserialize
             + Debug
             + MaxEncodedLen;
-        /// Something that give the IdtyIndex on an account id
-        type IdtyIndexOf: Convert<Self::AccountId, Option<Self::IdtyIndex>>;
+        /// Something that give the owner key of an identity
+        type OwnerKeyOf: Convert<Self::IdtyIndex, Option<Self::AccountId>>;
         ///
         type IsCertAllowed: IsCertAllowed<Self::IdtyIndex>;
         #[pallet::constant]
@@ -238,8 +238,6 @@ pub mod pallet {
         CannotCertifySelf,
         /// Certification non autorisée
         CertNotAllowed,
-        /// An identity must receive certifications before it can issue them.
-        IdtyMustReceiveCertsBeforeCanIssue,
         /// This identity has already issued the maximum number of certifications
         IssuedTooManyCert,
         /// Issuer not found
@@ -248,8 +246,6 @@ pub mod pallet {
         NotEnoughCertReceived,
         /// This identity has already issued a certification too recently
         NotRespectCertPeriod,
-        /// Receiver not found
-        ReceiverNotFound,
     }
 
     #[pallet::hooks]
@@ -272,23 +268,31 @@ pub mod pallet {
         ) -> DispatchResultWithPostInfo {
             ensure_root(origin)?;
 
+            // Forbid self cert
+            ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf);
+
             let block_number = frame_system::pallet::Pallet::<T>::block_number();
 
             if verify_rules {
-                let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer);
-                if issuer_idty_cert_meta.received_count == 0 {
-                    return Err(Error::<T, I>::IdtyMustReceiveCertsBeforeCanIssue.into());
-                }
-                // Verify rules CertPeriod and MaxByIssuer
-                if issuer_idty_cert_meta.received_count
-                    < T::MinReceivedCertToBeAbleToIssueCert::get()
-                {
-                    return Err(Error::<T, I>::NotEnoughCertReceived.into());
-                } else if issuer_idty_cert_meta.next_issuable_on > block_number {
-                    return Err(Error::<T, I>::NotRespectCertPeriod.into());
-                } else if issuer_idty_cert_meta.issued_count >= T::MaxByIssuer::get() {
-                    return Err(Error::<T, I>::IssuedTooManyCert.into());
-                }
+                // Verify rule MinReceivedCertToBeAbleToIssueCert
+                let issuer_idty_cert_meta = StorageIdtyCertMeta::<T, I>::get(issuer);
+                ensure!(
+                    issuer_idty_cert_meta.received_count
+                        >= T::MinReceivedCertToBeAbleToIssueCert::get(),
+                    Error::<T, I>::NotEnoughCertReceived
+                );
+
+                // Verify rule MaxByIssuer
+                ensure!(
+                    issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(),
+                    Error::<T, I>::IssuedTooManyCert
+                );
+
+                // Verify rule CertPeriod
+                ensure!(
+                    block_number >= issuer_idty_cert_meta.next_issuable_on,
+                    Error::<T, I>::NotRespectCertPeriod
+                );
             };
 
             Self::do_add_cert(block_number, issuer, receiver)
@@ -301,32 +305,45 @@ pub mod pallet {
         #[pallet::weight(1_000_000_000)]
         pub fn add_cert(
             origin: OriginFor<T>,
-            receiver: T::AccountId,
+            issuer: T::IdtyIndex,
+            receiver: T::IdtyIndex,
         ) -> DispatchResultWithPostInfo {
             let who = ensure_signed(origin)?;
-            ensure!(who != receiver, Error::<T, I>::CannotCertifySelf);
-            let issuer = T::IdtyIndexOf::convert(who).ok_or(Error::<T, I>::IssuerNotFound)?;
-            let receiver =
-                T::IdtyIndexOf::convert(receiver).ok_or(Error::<T, I>::ReceiverNotFound)?;
-            if !T::IsCertAllowed::is_cert_allowed(issuer, receiver) {
-                return Err(Error::<T, I>::CertNotAllowed.into());
-            }
 
-            let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer);
-            if issuer_idty_cert_meta.received_count == 0 {
-                return Err(Error::<T, I>::IdtyMustReceiveCertsBeforeCanIssue.into());
-            }
+            // Forbid self cert
+            ensure!(issuer != receiver, Error::<T, I>::CannotCertifySelf);
 
-            let block_number = frame_system::pallet::Pallet::<T>::block_number();
+            // Verify caller ownership
+            let issuer_owner_key =
+                T::OwnerKeyOf::convert(issuer).ok_or(Error::<T, I>::IssuerNotFound)?;
+            ensure!(issuer_owner_key == who, DispatchError::BadOrigin);
 
-            // Verify rules CertPeriod and MaxByIssuer
-            if issuer_idty_cert_meta.received_count < T::MinReceivedCertToBeAbleToIssueCert::get() {
-                return Err(Error::<T, I>::NotEnoughCertReceived.into());
-            } else if issuer_idty_cert_meta.next_issuable_on > block_number {
-                return Err(Error::<T, I>::NotRespectCertPeriod.into());
-            } else if issuer_idty_cert_meta.issued_count >= T::MaxByIssuer::get() {
-                return Err(Error::<T, I>::IssuedTooManyCert.into());
-            }
+            // Verify compatibility with other pallets state
+            ensure!(
+                T::IsCertAllowed::is_cert_allowed(issuer, receiver),
+                Error::<T, I>::CertNotAllowed
+            );
+
+            // Verify rule MinReceivedCertToBeAbleToIssueCert
+            let issuer_idty_cert_meta = <StorageIdtyCertMeta<T, I>>::get(issuer);
+            ensure!(
+                issuer_idty_cert_meta.received_count
+                    >= T::MinReceivedCertToBeAbleToIssueCert::get(),
+                Error::<T, I>::NotEnoughCertReceived
+            );
+
+            // Verify rule MaxByIssuer
+            ensure!(
+                issuer_idty_cert_meta.issued_count < T::MaxByIssuer::get(),
+                Error::<T, I>::IssuedTooManyCert
+            );
+
+            // Verify rule CertPeriod
+            let block_number = frame_system::pallet::Pallet::<T>::block_number();
+            ensure!(
+                block_number >= issuer_idty_cert_meta.next_issuable_on,
+                Error::<T, I>::NotRespectCertPeriod
+            );
 
             Self::do_add_cert(block_number, issuer, receiver)
         }
diff --git a/pallets/certification/src/mock.rs b/pallets/certification/src/mock.rs
index 3bbbe3c22ace119776d449683ffb3d0ae2f7939a..96e919f7ce2c6cbe6f739468d19bdfb2bc9fb88f 100644
--- a/pallets/certification/src/mock.rs
+++ b/pallets/certification/src/mock.rs
@@ -102,7 +102,7 @@ impl pallet_certification::Config for Test {
     type CertPeriod = CertPeriod;
     type Event = Event;
     type IdtyIndex = IdtyIndex;
-    type IdtyIndexOf = sp_runtime::traits::ConvertInto;
+    type OwnerKeyOf = sp_runtime::traits::ConvertInto;
     type IsCertAllowed = ();
     type MaxByIssuer = MaxByIssuer;
     type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert;
diff --git a/pallets/certification/src/tests.rs b/pallets/certification/src/tests.rs
index 37c56ad3b9089e5687939e567506e099bf92c922..2667ecce5b552287cb3898b6ed5d0c75d87def9f 100644
--- a/pallets/certification/src/tests.rs
+++ b/pallets/certification/src/tests.rs
@@ -30,8 +30,8 @@ fn test_must_receive_cert_before_can_issue() {
     })
     .execute_with(|| {
         assert_eq!(
-            DefaultCertification::add_cert(Origin::signed(0), 1),
-            Err(Error::<Test, _>::IdtyMustReceiveCertsBeforeCanIssue.into())
+            DefaultCertification::add_cert(Origin::signed(0), 0, 1),
+            Err(Error::<Test, _>::NotEnoughCertReceived.into())
         );
     });
 }
@@ -51,7 +51,7 @@ fn test_cannot_certify_self() {
         run_to_block(2);
 
         assert_eq!(
-            DefaultCertification::add_cert(Origin::signed(0), 0),
+            DefaultCertification::add_cert(Origin::signed(0), 0, 0),
             Err(Error::<Test, _>::CannotCertifySelf.into())
         );
     });
@@ -155,17 +155,17 @@ fn test_cert_period() {
             }
         );
         assert_eq!(
-            DefaultCertification::add_cert(Origin::signed(0), 3),
+            DefaultCertification::add_cert(Origin::signed(0), 0, 3),
             Err(Error::<Test, _>::NotRespectCertPeriod.into())
         );
         run_to_block(CertPeriod::get());
-        assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 3));
+        assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 0, 3));
         run_to_block(CertPeriod::get() + 1);
         assert_eq!(
-            DefaultCertification::add_cert(Origin::signed(0), 4),
+            DefaultCertification::add_cert(Origin::signed(0), 0, 4),
             Err(Error::<Test, _>::NotRespectCertPeriod.into())
         );
         run_to_block((2 * CertPeriod::get()) + 1);
-        assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 4));
+        assert_ok!(DefaultCertification::add_cert(Origin::signed(0), 0, 4));
     });
 }
diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs
index 2b457332402349f07e6213ace646bcc5c2e7ea1b..919cc9393cfdb72820bda28ad332a66b6c5aee10 100644
--- a/pallets/duniter-wot/src/lib.rs
+++ b/pallets/duniter-wot/src/lib.rs
@@ -116,6 +116,9 @@ where
         .is_ok()
     }
     fn can_validate_identity(idty_index: IdtyIndex) -> bool {
+        // TODO replace this code by te commented one for distance feature
+        /*let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index);
+        idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32*/
         pallet_membership::Pallet::<T, I>::claim_membership(
             RawOrigin::Root.into(),
             Some(idty_index),
@@ -154,6 +157,15 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::IsCertAllowed<IdtyI
     }
 }
 
+impl<T: Config<I>, I: 'static> sp_membership::traits::IsIdtyAllowedToClaimMembership<IdtyIndex>
+    for Pallet<T, I>
+{
+    fn is_idty_allowed_to_claim_membership(idty_index: &IdtyIndex) -> bool {
+        let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index);
+        idty_cert_meta.received_count >= T::MinCertForMembership::get() as u32
+    }
+}
+
 impl<T: Config<I>, I: 'static> sp_membership::traits::IsIdtyAllowedToRenewMembership<IdtyIndex>
     for Pallet<T, I>
 {
@@ -205,22 +217,7 @@ where
             // So, in any case, we must do nothing
             sp_membership::Event::<IdtyIndex, MetaData>::MembershipRevoked(_) => {}
             sp_membership::Event::<IdtyIndex, MetaData>::MembershipRenewed(_) => {}
-            sp_membership::Event::<IdtyIndex, MetaData>::MembershipRequested(idty_index) => {
-                let idty_cert_meta =
-                    pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index);
-                let received_count = idty_cert_meta.received_count;
-
-                // TODO insert `receiver` in distance queue if received_count >= MinCertForMembership
-                if received_count >= T::MinCertForMembership::get() as u32 {
-                    // TODO insert `receiver` in distance queue
-                    if Self::dispath_idty_call(pallet_identity::Call::validate_identity {
-                        idty_index: *idty_index,
-                    }) && received_count == T::MinReceivedCertToBeAbleToIssueCert::get()
-                    {
-                        Self::do_apply_first_issuable_on(*idty_index);
-                    }
-                }
-            }
+            sp_membership::Event::<IdtyIndex, MetaData>::MembershipRequested(_) => {}
             sp_membership::Event::<IdtyIndex, MetaData>::PendingMembershipExpired(idty_index) => {
                 Self::dispath_idty_call(pallet_identity::Call::remove_identity {
                     idty_index: *idty_index,
@@ -243,7 +240,7 @@ impl<T: Config<I>, I: 'static> pallet_identity::traits::OnIdtyChange<T> for Pall
                     true,
                 ) {
                     sp_std::if_std! {
-                        println!("fail to force add cert: {:?}", e)
+                        println!("fail to force add cert: {:?}", e)
                     }
                 }
             }
@@ -274,32 +271,8 @@ impl<T: Config<I>, I: 'static> pallet_certification::traits::OnNewcert<IdtyIndex
         receiver: IdtyIndex,
         receiver_received_count: u32,
     ) -> Weight {
-        if pallet_membership::Pallet::<T, I>::is_member(&receiver) {
-            if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() {
-                Self::do_apply_first_issuable_on(receiver);
-            }
-        } else if pallet_membership::Pallet::<T, I>::is_in_pending_memberships(receiver)
-            && receiver_received_count >= T::MinCertForMembership::get()
-        {
-            if T::IsSubWot::get() {
-                if let Err(e) = pallet_membership::Pallet::<T, I>::claim_membership(
-                    RawOrigin::Root.into(),
-                    Some(receiver),
-                ) {
-                    sp_std::if_std! {
-                        println!("fail to claim membership: {:?}", e)
-                    }
-                }
-            } else {
-                // TODO insert `receiver` in distance queue
-                Self::dispath_idty_call(pallet_identity::Call::validate_identity {
-                    idty_index: receiver,
-                });
-            }
-
-            if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() {
-                Self::do_apply_first_issuable_on(receiver);
-            }
+        if receiver_received_count == T::MinReceivedCertToBeAbleToIssueCert::get() {
+            Self::do_apply_first_issuable_on(receiver);
         }
         0
     }
diff --git a/pallets/duniter-wot/src/mock.rs b/pallets/duniter-wot/src/mock.rs
index 7c1490b3832e86baf553667202748277f6e24f7d..b94c67dd58bfc9acb6831623d0102177194ac8a8 100644
--- a/pallets/duniter-wot/src/mock.rs
+++ b/pallets/duniter-wot/src/mock.rs
@@ -29,6 +29,15 @@ type AccountId = u64;
 type Block = frame_system::mocking::MockBlock<Test>;
 type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
 
+pub struct IdentityIndexOf<T: pallet_identity::Config>(PhantomData<T>);
+impl<T: pallet_identity::Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>>
+    for IdentityIndexOf<T>
+{
+    fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> {
+        pallet_identity::Pallet::<T>::identity_index_of(account_id)
+    }
+}
+
 // Configure a mock runtime to test the pallet.
 frame_support::construct_runtime!(
     pub enum Test where
@@ -118,8 +127,6 @@ impl pallet_identity::Config for Test {
     type IdtyData = ();
     type IdtyNameValidator = IdtyNameValidatorTestImpl;
     type IdtyIndex = IdtyIndex;
-    type IdtyValidationOrigin = system::EnsureRoot<AccountId>;
-    type IsMember = Membership;
     type NewOwnerKeySigner = UintAuthorityId;
     type NewOwnerKeySignature = TestSignature;
     type OnIdtyChange = DuniterWot;
@@ -136,11 +143,12 @@ parameter_types! {
 }
 
 impl pallet_membership::Config<Instance1> for Test {
+    type IsIdtyAllowedToClaimMembership = DuniterWot;
     type IsIdtyAllowedToRenewMembership = DuniterWot;
     type IsIdtyAllowedToRequestMembership = DuniterWot;
     type Event = Event;
     type IdtyId = IdtyIndex;
-    type IdtyIdOf = Identity;
+    type IdtyIdOf = IdentityIndexOf<Self>;
     type MembershipPeriod = MembershipPeriod;
     type MetaData = crate::MembershipMetaData<u64>;
     type OnEvent = DuniterWot;
@@ -160,7 +168,7 @@ impl pallet_certification::Config<Instance1> for Test {
     type CertPeriod = CertPeriod;
     type Event = Event;
     type IdtyIndex = IdtyIndex;
-    type IdtyIndexOf = Identity;
+    type OwnerKeyOf = Identity;
     type IsCertAllowed = DuniterWot;
     type MaxByIssuer = MaxByIssuer;
     type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert;
@@ -191,11 +199,12 @@ parameter_types! {
 }
 
 impl pallet_membership::Config<Instance2> for Test {
+    type IsIdtyAllowedToClaimMembership = SmithsSubWot;
     type IsIdtyAllowedToRenewMembership = SmithsSubWot;
     type IsIdtyAllowedToRequestMembership = SmithsSubWot;
     type Event = Event;
     type IdtyId = IdtyIndex;
-    type IdtyIdOf = Identity;
+    type IdtyIdOf = IdentityIndexOf<Self>;
     type MembershipPeriod = SmithsMembershipPeriod;
     type MetaData = crate::MembershipMetaData<u64>;
     type OnEvent = SmithsSubWot;
@@ -215,7 +224,7 @@ impl pallet_certification::Config<Instance2> for Test {
     type CertPeriod = SmithsCertPeriod;
     type Event = Event;
     type IdtyIndex = IdtyIndex;
-    type IdtyIndexOf = Identity;
+    type OwnerKeyOf = Identity;
     type IsCertAllowed = SmithsSubWot;
     type MaxByIssuer = SmithsMaxByIssuer;
     type MinReceivedCertToBeAbleToIssueCert = SmithsMinReceivedCertToBeAbleToIssueCert;
diff --git a/pallets/duniter-wot/src/tests.rs b/pallets/duniter-wot/src/tests.rs
index 4a712578504a246ed12fe0a41f20d1e969d1f9b9..bd3fb937c79637ed3d2d32f7a61d27cd78b14911 100644
--- a/pallets/duniter-wot/src/tests.rs
+++ b/pallets/duniter-wot/src/tests.rs
@@ -66,11 +66,18 @@ fn test_join_smiths() {
 
         // Then, Alice should be able to send a smith cert to Dave
         run_to_block(3);
-        assert_ok!(SmithsCert::add_cert(Origin::signed(1), 4));
+        assert_ok!(SmithsCert::add_cert(Origin::signed(1), 1, 4));
 
-        // Then, if Bob certify Dave, he should become member
+        // Then, Bob should be able to send a smith cert to Dave
         run_to_block(4);
-        assert_ok!(SmithsCert::add_cert(Origin::signed(2), 4));
+        assert_ok!(SmithsCert::add_cert(Origin::signed(2), 2, 4));
+
+        // Then, Dave should be able to claim his membership
+        run_to_block(4);
+        assert_ok!(SmithsMembership::claim_membership(
+            Origin::signed(4),
+            Some(4)
+        ));
         System::assert_has_event(Event::SmithsMembership(
             pallet_membership::Event::MembershipAcquired(4),
         ));
@@ -114,7 +121,7 @@ fn test_revoke_smiths_them_rejoin() {
         ));
 
         // Then, Alice should be able to send a smith cert to Dave
-        assert_ok!(SmithsCert::add_cert(Origin::signed(1), 4));
+        assert_ok!(SmithsCert::add_cert(Origin::signed(1), 1, 4));
     });
 }
 
@@ -173,40 +180,23 @@ fn test_new_idty_validation() {
 
         // Bob should be able to certify Ferdie
         run_to_block(4);
-        assert_ok!(Cert::add_cert(Origin::signed(2), 6));
-
-        let events = System::events();
-        // 3 events should have occurred: NewCert, MembershipAcquired and IdtyValidated
-        assert_eq!(events.len(), 3);
-        assert_eq!(
-            events[0],
-            EventRecord {
-                phase: Phase::Initialization,
-                event: Event::Cert(pallet_certification::Event::NewCert {
-                    issuer: 2,
-                    issuer_issued_count: 5,
-                    receiver: 6,
-                    receiver_received_count: 2
-                }),
-                topics: vec![],
-            }
-        );
-        assert_eq!(
-            events[1],
-            EventRecord {
-                phase: Phase::Initialization,
-                event: Event::Membership(pallet_membership::Event::MembershipAcquired(6)),
-                topics: vec![],
-            }
-        );
-        assert_eq!(
-            events[2],
-            EventRecord {
-                phase: Phase::Initialization,
-                event: Event::Identity(pallet_identity::Event::IdtyValidated { idty_index: 6 }),
-                topics: vec![],
-            }
-        );
+        assert_ok!(Cert::add_cert(Origin::signed(2), 2, 6));
+        System::assert_has_event(Event::Cert(pallet_certification::Event::NewCert {
+            issuer: 2,
+            issuer_issued_count: 5,
+            receiver: 6,
+            receiver_received_count: 2,
+        }));
+
+        // Anyone should be able to validate Ferdie identity
+        run_to_block(5);
+        assert_ok!(Identity::validate_identity(Origin::signed(42), 6));
+        System::assert_has_event(Event::Membership(
+            pallet_membership::Event::MembershipAcquired(6),
+        ));
+        System::assert_has_event(Event::Identity(pallet_identity::Event::IdtyValidated {
+            idty_index: 6,
+        }));
 
         // After PendingMembershipPeriod, Ferdie identity should not expire
         run_to_block(6);
@@ -304,8 +294,8 @@ fn test_idty_membership_expire_them_requested() {
 
         // Alice can't renew her cert to Charlie
         assert_noop!(
-            Cert::add_cert(Origin::signed(1), 3),
-            pallet_certification::Error::<Test, Instance1>::ReceiverNotFound
+            Cert::add_cert(Origin::signed(1), 1, 3),
+            pallet_certification::Error::<Test, Instance1>::CertNotAllowed
         );
     });
 }
diff --git a/pallets/identity/src/lib.rs b/pallets/identity/src/lib.rs
index 5c54f9495cc3956a35e6b363158b0eade2051ab2..d3d36af60d540b796342ca43c4047e59ca13c461 100644
--- a/pallets/identity/src/lib.rs
+++ b/pallets/identity/src/lib.rs
@@ -94,10 +94,6 @@ pub mod pallet {
             + MaxEncodedLen;
         /// Handle logic to validate an identity name
         type IdtyNameValidator: IdtyNameValidator;
-        /// Origin allowed to validate identity
-        type IdtyValidationOrigin: EnsureOrigin<Self::Origin>;
-        ///
-        type IsMember: sp_runtime::traits::IsMember<Self::IdtyIndex>;
         /// On identity confirmed by its owner
         type OnIdtyChange: OnIdtyChange<Self>;
         /// Signing key of new owner key payload
@@ -366,7 +362,7 @@ pub mod pallet {
             idty_index: T::IdtyIndex,
         ) -> DispatchResultWithPostInfo {
             // Verification phase //
-            T::IdtyValidationOrigin::ensure_origin(origin)?;
+            let _ = ensure_signed(origin)?;
 
             let mut idty_value =
                 Identities::<T>::try_get(idty_index).map_err(|_| Error::<T>::IdtyNotFound)?;
@@ -639,9 +635,9 @@ pub mod pallet {
     }
 }
 
-impl<T: Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>> for Pallet<T> {
-    fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> {
-        Self::identity_index_of(account_id)
+impl<T: Config> sp_runtime::traits::Convert<T::IdtyIndex, Option<T::AccountId>> for Pallet<T> {
+    fn convert(idty_index: T::IdtyIndex) -> Option<T::AccountId> {
+        Identities::<T>::get(idty_index).map(|idty_val| idty_val.owner_key)
     }
 }
 
diff --git a/pallets/identity/src/mock.rs b/pallets/identity/src/mock.rs
index d6f973e040d38c5d3112d71b7c2e809f102f0d1c..082cb28a1daac7024c8b619b5002bd62e8b5670a 100644
--- a/pallets/identity/src/mock.rs
+++ b/pallets/identity/src/mock.rs
@@ -24,7 +24,7 @@ use frame_system as system;
 use sp_core::H256;
 use sp_runtime::{
     testing::{Header, TestSignature, UintAuthorityId},
-    traits::{BlakeTwo256, IdentityLookup, IsMember},
+    traits::{BlakeTwo256, IdentityLookup},
 };
 
 type AccountId = u64;
@@ -90,13 +90,6 @@ impl pallet_identity::traits::IdtyNameValidator for IdtyNameValidatorTestImpl {
     }
 }
 
-pub struct IsMemberTestImpl;
-impl IsMember<u64> for IsMemberTestImpl {
-    fn is_member(_: &u64) -> bool {
-        true
-    }
-}
-
 impl pallet_identity::Config for Test {
     type ChangeOwnerKeyPeriod = ChangeOwnerKeyPeriod;
     type ConfirmPeriod = ConfirmPeriod;
@@ -106,8 +99,6 @@ impl pallet_identity::Config for Test {
     type IdtyData = ();
     type IdtyNameValidator = IdtyNameValidatorTestImpl;
     type IdtyIndex = u64;
-    type IdtyValidationOrigin = system::EnsureRoot<AccountId>;
-    type IsMember = IsMemberTestImpl;
     type NewOwnerKeySigner = UintAuthorityId;
     type NewOwnerKeySignature = TestSignature;
     type OnIdtyChange = ();
diff --git a/pallets/membership/src/lib.rs b/pallets/membership/src/lib.rs
index 1232c04d9e276baf3ae70a94612901aa9740fac5..657c4f152931f7f25280536facf2d465075f6354 100644
--- a/pallets/membership/src/lib.rs
+++ b/pallets/membership/src/lib.rs
@@ -59,7 +59,11 @@ pub mod pallet {
 
     #[pallet::config]
     pub trait Config<I: 'static = ()>: frame_system::Config {
+        /// Ask the runtime if the identity can claim the membership
+        type IsIdtyAllowedToClaimMembership: IsIdtyAllowedToClaimMembership<Self::IdtyId>;
+        /// Ask the runtime if the identity can renew his membership
         type IsIdtyAllowedToRenewMembership: IsIdtyAllowedToRenewMembership<Self::IdtyId>;
+        /// Ask the runtime if the identity can request the membership
         type IsIdtyAllowedToRequestMembership: IsIdtyAllowedToRequestMembership<Self::IdtyId>;
         /// Because this pallet emits events, it depends on the runtime's definition of an event.
         type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
@@ -169,6 +173,8 @@ pub mod pallet {
 
     #[pallet::error]
     pub enum Error<T, I = ()> {
+        /// Identity not allowed to claim membership
+        IdtyNotAllowedToClaimMembership,
         /// Identity not allowed to request membership
         IdtyNotAllowedToRequestMembership,
         /// Identity not allowed to renew membership
@@ -248,9 +254,15 @@ pub mod pallet {
             // Verify phase
             let idty_id = Self::ensure_origin_and_get_idty_id(origin, maybe_idty_id)?;
 
-            if Membership::<T, I>::contains_key(&idty_id) {
-                return Err(Error::<T, I>::MembershipAlreadyAcquired.into());
-            }
+            ensure!(
+                !Membership::<T, I>::contains_key(&idty_id),
+                Error::<T, I>::MembershipAlreadyAcquired
+            );
+
+            ensure!(
+                T::IsIdtyAllowedToClaimMembership::is_idty_allowed_to_claim_membership(&idty_id),
+                Error::<T, I>::IdtyNotAllowedToClaimMembership
+            );
 
             let metadata = PendingMembership::<T, I>::take(&idty_id)
                 .ok_or(Error::<T, I>::MembershipRequestNotFound)?;
@@ -271,15 +283,16 @@ pub mod pallet {
             // Verify phase
             let idty_id = Self::ensure_origin_and_get_idty_id(origin, maybe_idty_id)?;
 
-            if !T::IsIdtyAllowedToRenewMembership::is_idty_allowed_to_renew_membership(&idty_id) {
-                return Err(Error::<T, I>::IdtyNotAllowedToRenewMembership.into());
-            }
-
             ensure!(
                 Self::get_membership(&idty_id).is_some(),
                 Error::<T, I>::MembershipNotFound
             );
 
+            ensure!(
+                T::IsIdtyAllowedToRenewMembership::is_idty_allowed_to_renew_membership(&idty_id),
+                Error::<T, I>::IdtyNotAllowedToRenewMembership,
+            );
+
             let _ = Self::do_renew_membership(idty_id);
 
             Ok(().into())
diff --git a/pallets/membership/src/mock.rs b/pallets/membership/src/mock.rs
index 4e1b49dd5772e86dfbc7455b0242229bad2b768d..e9ea07467cbde7fc38e857443f417048e26574dd 100644
--- a/pallets/membership/src/mock.rs
+++ b/pallets/membership/src/mock.rs
@@ -84,6 +84,7 @@ parameter_types! {
 }
 
 impl pallet_membership::Config for Test {
+    type IsIdtyAllowedToClaimMembership = ();
     type IsIdtyAllowedToRenewMembership = ();
     type IsIdtyAllowedToRequestMembership = ();
     type Event = Event;
diff --git a/primitives/membership/src/traits.rs b/primitives/membership/src/traits.rs
index 2690cb58e6b164e675f038b268329d133d34744e..a6e7d6ad6fc9f87a04a878954f5169413fe953f8 100644
--- a/primitives/membership/src/traits.rs
+++ b/primitives/membership/src/traits.rs
@@ -16,6 +16,16 @@
 
 use frame_support::pallet_prelude::Weight;
 
+pub trait IsIdtyAllowedToClaimMembership<IdtyId> {
+    fn is_idty_allowed_to_claim_membership(idty_id: &IdtyId) -> bool;
+}
+
+impl<IdtyId> IsIdtyAllowedToClaimMembership<IdtyId> for () {
+    fn is_idty_allowed_to_claim_membership(_: &IdtyId) -> bool {
+        true
+    }
+}
+
 pub trait IsIdtyAllowedToRenewMembership<IdtyId> {
     fn is_idty_allowed_to_renew_membership(idty_id: &IdtyId) -> bool;
 }
diff --git a/resources/metadata.scale b/resources/metadata.scale
index 90750afa43fe6d866bf9ea3912c915d6b4a4ed08..745d186e552bbd0323d9e2e78cf80fd620892fe9 100644
Binary files a/resources/metadata.scale and b/resources/metadata.scale differ
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index bc5e82e5a2cd58b8de55327a998033f2c325c48f..20dc90e790acc01fa39c977bd067a0eb29c71719 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -193,7 +193,7 @@ macro_rules! pallets_config {
             type OnNewSession = OnNewSessionHandler<Runtime>;
             type OnRemovedMember = OnRemovedAuthorityMemberHandler<Runtime>;
             type MemberId = IdtyIndex;
-            type MemberIdOf = Identity;
+            type MemberIdOf = common_runtime::providers::IdentityIndexOf<Self>;
             type MaxAuthorities = MaxAuthorities;
             type MaxKeysLife = frame_support::pallet_prelude::ConstU32<1_500>;
             type MaxOfflineSessions = frame_support::pallet_prelude::ConstU32<2_400>;
@@ -427,8 +427,6 @@ macro_rules! pallets_config {
 			type IdtyData = IdtyData;
             type IdtyIndex = IdtyIndex;
             type IdtyNameValidator = IdtyNameValidatorImpl;
-            type IdtyValidationOrigin = EnsureRoot<Self::AccountId>;
-            type IsMember = Membership;
             type NewOwnerKeySigner = <NewOwnerKeySignature as sp_runtime::traits::Verify>::Signer;
 			type NewOwnerKeySignature = NewOwnerKeySignature;
             type OnIdtyChange = (common_runtime::handlers::OnIdtyChangeHandler<Runtime>, Wot);
@@ -438,11 +436,12 @@ macro_rules! pallets_config {
         }
 
         impl pallet_membership::Config<frame_support::instances::Instance1> for Runtime {
+			type IsIdtyAllowedToClaimMembership = Wot;
             type IsIdtyAllowedToRenewMembership = Wot;
             type IsIdtyAllowedToRequestMembership = Wot;
             type Event = Event;
             type IdtyId = IdtyIndex;
-            type IdtyIdOf = Identity;
+            type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>;
             type MembershipPeriod = MembershipPeriod;
             type MetaData = pallet_duniter_wot::MembershipMetaData<AccountId>;
             type OnEvent = OnMembershipEventHandler<Wot, Runtime>;
@@ -454,7 +453,7 @@ macro_rules! pallets_config {
             type CertPeriod = CertPeriod;
             type Event = Event;
             type IdtyIndex = IdtyIndex;
-            type IdtyIndexOf = Identity;
+            type OwnerKeyOf = Identity;
             type IsCertAllowed = Wot;
             type MaxByIssuer = MaxByIssuer;
             type MinReceivedCertToBeAbleToIssueCert = MinReceivedCertToBeAbleToIssueCert;
@@ -474,11 +473,12 @@ macro_rules! pallets_config {
         }
 
         impl pallet_membership::Config<Instance2> for Runtime {
-            type IsIdtyAllowedToRenewMembership = ();
-            type IsIdtyAllowedToRequestMembership = ();
+			type IsIdtyAllowedToClaimMembership = SmithsSubWot;
+            type IsIdtyAllowedToRenewMembership = SmithsSubWot;
+            type IsIdtyAllowedToRequestMembership = SmithsSubWot;
             type Event = Event;
             type IdtyId = IdtyIndex;
-            type IdtyIdOf = Identity;
+            type IdtyIdOf = common_runtime::providers::IdentityIndexOf<Self>;
             type MembershipPeriod = SmithMembershipPeriod;
             type MetaData = SmithsMembershipMetaData<opaque::SessionKeysWrapper>;
             type OnEvent = OnSmithMembershipEventHandler<SmithsSubWot, Runtime>;
@@ -490,7 +490,7 @@ macro_rules! pallets_config {
             type CertPeriod = SmithCertPeriod;
             type Event = Event;
             type IdtyIndex = IdtyIndex;
-            type IdtyIndexOf = Identity;
+            type OwnerKeyOf = Identity;
             type IsCertAllowed = SmithsSubWot;
             type MaxByIssuer = SmithMaxByIssuer;
             type MinReceivedCertToBeAbleToIssueCert = SmithMinReceivedCertToBeAbleToIssueCert;
@@ -514,7 +514,7 @@ macro_rules! pallets_config {
         impl sp_runtime::traits::IsMember<AccountId> for SmithMembersStorage {
             fn is_member(account_id: &AccountId) -> bool {
                 use sp_runtime::traits::Convert as _;
-                if let Some(idty_index) = Identity::convert(account_id.clone()) {
+                if let Some(idty_index) = common_runtime::providers::IdentityIndexOf::<Runtime>::convert(account_id.clone()) {
                     pallet_membership::Pallet::<Runtime, Instance2>::is_member(&idty_index)
                 } else {
                     false
diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs
index 3e32943062b3f258ff3796b490a83de9f7501edd..9a20e56a26d4b5e5ca7acb6c215d75a41ba74c11 100644
--- a/runtime/common/src/providers.rs
+++ b/runtime/common/src/providers.rs
@@ -33,6 +33,16 @@ impl<
     }
 }
 
+pub struct IdentityIndexOf<T: pallet_identity::Config>(PhantomData<T>);
+
+impl<T: pallet_identity::Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>>
+    for IdentityIndexOf<T>
+{
+    fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> {
+        pallet_identity::Pallet::<T>::identity_index_of(account_id)
+    }
+}
+
 pub struct UdMembersStorage<T: pallet_identity::Config>(PhantomData<T>);
 
 impl<T> frame_support::traits::StoredMap<AccountId, FirstEligibleUd> for UdMembersStorage<T>
diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs
index 7e05a45b77e1e3b3971fdad75b231b4b790d6d4f..4255e3e6dd68e822badc905c699489d52fca8b88 100644
--- a/runtime/g1/src/lib.rs
+++ b/runtime/g1/src/lib.rs
@@ -137,7 +137,6 @@ impl Contains<Call> for BaseCallFilter {
                 pallet_membership::Call::claim_membership { .. }
                     | pallet_membership::Call::revoke_membership { .. }
             ) | Call::Session(_)
-                | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. })
         )
     }
 }
diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs
index 80744615582a146b6557207d353a641bc9631cca..8476ea5e79ff7c3ad7ad8a05bc8fd86e0a74f26f 100644
--- a/runtime/gdev/src/lib.rs
+++ b/runtime/gdev/src/lib.rs
@@ -144,7 +144,6 @@ impl Contains<Call> for BaseCallFilter {
                     | pallet_membership::Call::claim_membership { .. }
                     | pallet_membership::Call::revoke_membership { .. }
             ) | Call::Session(_)
-                | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. })
                 | Call::AuthorityMembers(pallet_authority_members::Call::go_online { .. })
         )
     }
@@ -159,7 +158,6 @@ impl Contains<Call> for BaseCallFilter {
                     | pallet_membership::Call::claim_membership { .. }
                     | pallet_membership::Call::revoke_membership { .. }
             ) | Call::Session(_)
-                | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. })
         )
     }
 }
diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs
index 2553564fc4a5f09871b0e586f62401e4db1fb564..4baa629356fdee62ea773043f3f2d4ce0e623f96 100644
--- a/runtime/gtest/src/lib.rs
+++ b/runtime/gtest/src/lib.rs
@@ -138,7 +138,6 @@ impl Contains<Call> for BaseCallFilter {
                 pallet_membership::Call::claim_membership { .. }
                     | pallet_membership::Call::revoke_membership { .. }
             ) | Call::Session(_)
-                | Call::SmithsMembership(pallet_membership::Call::claim_membership { .. })
         )
     }
 }