grammers icon indicating copy to clipboard operation
grammers copied to clipboard

sign_in problem

Open 0xthecableguy opened this issue 1 year ago • 6 comments

hello, can't authorize client via telegram

if !client.is_authorized().await? {
        if state.awaiting_phone_number {
            if let Some(phone) = msg.text() {
                state.phone_number = Some(phone.to_string());
                state.awaiting_phone_number = false;
                state.awaiting_passcode = true;
                let token = client.request_login_code(phone).await?;
                state.token = Some(Arc::new(token));
                bot.send_message(msg.chat.id, "Phone number received! Please provide the passcode.")
                    .await?;
            }
        } else if state.awaiting_passcode {
            if let Some(code) = msg.text() {
                state.passcode = Some(code.to_string());
                state.awaiting_passcode = false;
                if let Some(token) = &state.token {
                    let token = Arc::clone(token); // Clone the Arc
                    match client.sign_in(&token, code).await {
                        Ok(_) => {
                            bot.send_message(msg.chat.id, "Successfully authorized!")
                                .await?;
                        }
                        Err(SignInError::PasswordRequired(password_token)) => {
                            let hint = password_token.hint().unwrap_or("No hint");
                            state.awaiting_2fa = true;
                            state.password_token = Some(password_token.clone());
                            bot.send_message(msg.chat.id, format!("2FA required. Hint: {}. Please enter your 2FA password.", hint))
                                .await?;
                        }
                        Err(e) => {
                            bot.send_message(msg.chat.id, format!("Failed to sign in: {}", e))
                                .await?;
                            return Err(e.into());
                        }
                    }
                }
            }
        } else if state.awaiting_2fa {
            if let Some(password) = msg.text() {
                if let Some(password_token) = &state.password_token {
                    match client.check_password(password_token.clone(), password).await {
                        Ok(_) => {
                            bot.send_message(msg.chat.id, "Successfully authorized with 2FA!")
                                .await?;
                        }
                        Err(e) => {
                            bot.send_message(msg.chat.id, format!("Failed to authorize with 2FA: {}", e))
                                .await?;
                            return Err(e.into());
                        }
                    }
                }
            }
        }
    } else {
        bot.send_message(msg.chat.id, "Already authorized!")
            .await?;
    }

I got phone_number from user via telegram bot, then fall into state awaiting passcode, create token:

    let token = client.request_login_code(phone).await?;

and then i get passcode from telegram to my cellphone, typing it into bot... and got:

Incomplete login attempt. Dear ***, Telegram blocked an attempt to log into your account from a new device on 16/09/2024 at 22:46:49 UTC.

Device: app_name, 0.6.0, Mac OS 64-bit, Desktop, 14.6.1 Location: ***

Nobody gained access to your chats because the login was not completed. The code was entered correctly, but sign in was not allowed, because this code was previously shared by your account.

Please don't share login codes with others, because they allow anyone to log in to your account and access your chats.

is there any way to authorize this way?

0xthecableguy avatar Sep 17 '24 12:09 0xthecableguy

Did you use the library from crates.io, or the git version? If the former, try the git version.

Lonami avatar Sep 18 '24 20:09 Lonami

i use following:

grammers = { git = "https://github.com/Lonami/grammers.git", branch = "master" }
grammers-client = { git = "https://github.com/Lonami/grammers.git", package = "grammers-client", branch = "master" }
grammers-session = { git = "https://github.com/Lonami/grammers.git", package = "grammers-session", branch = "master" }

strange thing is that telegram says me: "The code was entered correctly, but sign in was not allowed, because this code was previously shared by your account."

maybe some trouble with storing token in the user states' structures?

#[derive(Default, Clone)]
pub struct AuthStages {
    pub awaiting_phone_number: bool,
    pub awaiting_passcode: bool,
    pub awaiting_2fa: bool,
    pub phone_number: Option<String>,
    pub passcode: Option<String>,
    pub two_fa: Option<String>,
    pub client: Option<Client>,
    pub token: Option<Arc<LoginToken>>,
    pub password_token: Option<PasswordToken>,
}

#[derive(Default)]
pub struct AppState {
    pub user_state: Mutex<HashMap<u64, AuthStages>>,
}

0xthecableguy avatar Sep 18 '24 21:09 0xthecableguy

If the code is sent in a Telegram message, it will immediately expire.

Lonami avatar Sep 18 '24 21:09 Lonami

so how should i transfer it here

client.sign_in(&token, code)

I got the code, sending it via telegram bot, processing this message, and sending code and token to the authorization fn

0xthecableguy avatar Sep 18 '24 21:09 0xthecableguy

pub(crate) async fn auth_data_processing(bot: Bot, msg: Message, app_state: Arc<AppState>, mut state: AuthStages) -> anyhow::Result<()> {
    let user_id = msg.from.as_ref().map(|user| user.id.0).unwrap_or(0);
    
    // Check and set client
    if state.client.is_none() {
        let session_file = format!("{}.session", msg.chat.id);
        let client = Client::connect(Config {
            session: Session::load_file_or_create(session_file.clone())?,
            api_id: API_ID,
            api_hash: API_HASH.to_string(),
            params: Default::default(),
        }).await?;
        state.client = Some(client.clone());
        // client.session().save_to_file(format!("{}.session", msg.chat.id))?;
    }
    
    let client = state.client.as_ref().unwrap();

    // Handle authorization
    if !client.is_authorized().await? {
        if state.awaiting_phone_number {
            if let Some(phone) = msg.text() {
                state.phone_number = Some(phone.to_string());
                state.awaiting_phone_number = false;
                state.awaiting_passcode = true;
                let token = client.request_login_code(phone).await?;
                state.token = Some(Arc::new(token));
                bot.send_message(msg.chat.id, "Phone number received! Please provide the passcode.")
                    .await?;
                
                let mut user_states = app_state.user_state.lock().await;
                user_states.insert(user_id, state.clone());
            }
        } else if state.awaiting_passcode {
            if let Some(code) = msg.text() {
                info!("got code: {}", code);
                state.passcode = Some(code.to_string());
                state.awaiting_passcode = false;
                if let Some(token) = state.token.as_ref() {
                    // let token = Arc::clone(token); // Clone the Arc
                    sleep(Dur::from_secs(2)).await;
                    match client.sign_in(&token, code).await {
                        Ok(_) => {
                            bot.send_message(msg.chat.id, "Successfully authorized!")
                                .await?;
                        }
                        Err(SignInError::PasswordRequired(password_token)) => {
                            let hint = password_token.hint().unwrap_or("No hint");
                            state.awaiting_2fa = true;
                            state.password_token = Some(password_token.clone());
                            bot.send_message(msg.chat.id, format!("2FA required. Hint: {}. Please enter your 2FA password.", hint))
                                .await?;
                        }
                        Err(e) => {
                            bot.send_message(msg.chat.id, format!("Failed to sign in: {}", e))
                                .await?;
                            return Err(e.into());
                        }
                    }
                }
            }
        } else if state.awaiting_2fa {
            if let Some(password) = msg.text() {
                if let Some(password_token) = &state.password_token {
                    match client.check_password(password_token.clone(), password).await {
                        Ok(_) => {
                            bot.send_message(msg.chat.id, "Successfully authorized with 2FA!")
                                .await?;
                        }
                        Err(e) => {
                            bot.send_message(msg.chat.id, format!("Failed to authorize with 2FA: {}", e))
                                .await?;
                            return Err(e.into());
                        }
                    }
                }
            }
        }
    } else {
        bot.send_message(msg.chat.id, "Already authorized!")
            .await?;
    }

    // Update the state in user_states
    let mut user_states = app_state.user_state.lock().await;
    user_states.insert(user_id, state);

    Ok(())
}

in case you would like see the code of the auth fn

0xthecableguy avatar Sep 18 '24 21:09 0xthecableguy

sending it via telegram bot

Don't. It expires.

Lonami avatar Sep 19 '24 06:09 Lonami