diff --git a/pallets/pass/src/lib.rs b/pallets/pass/src/lib.rs index 1eea17e..8018fc6 100644 --- a/pallets/pass/src/lib.rs +++ b/pallets/pass/src/lib.rs @@ -98,6 +98,10 @@ pub mod pallet { pub type Sessions, I: 'static = ()> = StorageMap<_, Blake2_128Concat, T::AccountId, (T::AccountId, BlockNumberFor)>; + #[pallet::storage] + pub type AuthenticationAttempts, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, DeviceId, Result>; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { @@ -154,19 +158,9 @@ pub mod pallet { #[pallet::feeless_if( |_: &OriginFor, device_id: &DeviceId, credential: &CredentialOf, _: &Option>| -> bool { - Pallet::::account_id_for(credential.user_id()) - .and_then(|account_id| { - ensure!( - Pallet::::account_exists(&account_id), - Error::::AccountNotFound - ); - let device = Devices::::get(&account_id, device_id) - .ok_or::(Error::::DeviceNotFound.into())?; - device - .verify_user(credential) - .ok_or(Error::::CredentialInvalid.into()) - }) - .is_ok() + let authentication_attempt = Pallet::::try_authenticate(device_id, credential); + AuthenticationAttempts::::insert(device_id, authentication_attempt.clone()); + authentication_attempt.is_ok() } )] #[pallet::call_index(3)] @@ -177,17 +171,14 @@ pub mod pallet { duration: Option>, ) -> DispatchResult { let who = ensure_signed(origin)?; - let account_id = Self::account_id_for(credential.user_id())?; - ensure!( - Self::account_exists(&account_id), - Error::::AccountNotFound - ); - - let device = Devices::::get(&account_id, device_id) - .ok_or(Error::::DeviceNotFound)?; - device - .verify_user(&credential) - .ok_or(Error::::CredentialInvalid)?; + let account_id = if let Some(authentication_attempt) = + AuthenticationAttempts::::get(device_id) + { + AuthenticationAttempts::::remove(device_id); + authentication_attempt + } else { + Self::try_authenticate(&device_id, &credential) + }?; Self::do_add_session(&who, &account_id, duration); Ok(()) @@ -267,6 +258,24 @@ impl, I: 'static> Pallet { Ok(()) } + pub(crate) fn try_authenticate( + device_id: &DeviceId, + credential: &CredentialOf, + ) -> Result { + let account_id = Self::account_id_for(credential.user_id())?; + ensure!( + Self::account_exists(&account_id), + Error::::AccountNotFound + ); + let device = + Devices::::get(&account_id, device_id).ok_or(Error::::DeviceNotFound)?; + device + .verify_user(credential) + .ok_or(Error::::CredentialInvalid)?; + + Ok(account_id) + } + pub(crate) fn do_add_device( who: &T::AccountId, attestation: DeviceAttestationOf,