Repository: meilisearch/meilisearch
File: meilisearch-http/src/extractors/authentication/mod.rs (Rust)

Code before:
        token: String,
        index: Option<String>,
        data: Option<D>,
    ) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        match Self::authenticate(auth, token, index).await? {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),
                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None => Err(AuthenticationError::InvalidToken.into()),
        }
    }

    async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        let auth_clone = auth.clone();
        let master_key: Option<&String> = auth_clone.get_master_key();

        match Self::authenticate(auth, String::new(), None).await? {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),

                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None => match master_key {
                Some(_) => Err(AuthenticationError::MissingAuthorizationHeader.into()),
                None => Err(AuthenticationError::MissingMasterKey.into()),
            },
        }
    }

    async fn authenticate(
        auth: AuthController,
        token: String,
        index: Option<String>,
    ) -> Result<Option<AuthFilter>, ResponseError>
    where
        P: Policy + 'static,

Review comment (security):
In this case, you have to clone auth because the reference to the master_key is moved, however, you don't need the content of the master key but you want to know if the master key is set, I suggest changing these lines into:
```suggestion
        let missing_master_key = auth.get_master_key().is_none();
```

This would avoid cloning the auth controller, then I suggest changing the below match (Lines 54-67) into:
```rust
        match Self::authenticate(auth, String::new(), None).await? {
            Some(filters) => match data {
                // [ ... ]
            },
            None if missing_master_key => Err(AuthenticationError::MissingMasterKey.into()),
            None => Err(AuthenticationError::MissingAuthorizationHeader.into()),
        }
```

Code after:
        token: String,
        index: Option<String>,
        data: Option<D>,
    ) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        match Self::authenticate(auth, token, index).await? {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),
                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None => Err(AuthenticationError::InvalidToken.into()),
        }
    }

    async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
    where
        P: Policy + 'static,
    {
        let missing_master_key = auth.get_master_key().is_none();

        match Self::authenticate(auth, String::new(), None).await? {
            Some(filters) => match data {
                Some(data) => Ok(Self {
                    data,
                    filters,
                    _marker: PhantomData,
                }),

                None => Err(AuthenticationError::IrretrievableState.into()),
            },
            None if missing_master_key => Err(AuthenticationError::MissingMasterKey.into()),
            None => Err(AuthenticationError::MissingAuthorizationHeader.into()),
        }
    }

    async fn authenticate(
        auth: AuthController,
        token: String,
        index: Option<String>,
    ) -> Result<Option<AuthFilter>, ResponseError>
    where
        P: Policy + 'static,
    {
        tokio::task::spawn_blocking(move || P::authenticate(auth, token.as_ref(), index.as_deref()))
            .await