add add_authenticator to steamapi module
This commit is contained in:
parent
e4d7ea4475
commit
2e4058cfca
3 changed files with 88 additions and 7 deletions
|
@ -1,5 +1,7 @@
|
||||||
use crate::{steamapi::Session, SteamGuardAccount};
|
use crate::{
|
||||||
use serde::Deserialize;
|
steamapi::{AddAuthenticatorResponse, Session},
|
||||||
|
SteamGuardAccount,
|
||||||
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
@ -55,11 +57,6 @@ fn generate_device_id() -> String {
|
||||||
return format!("android:{}", uuid::Uuid::new_v4().to_string());
|
return format!("android:{}", uuid::Uuid::new_v4().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct AddAuthenticatorResponse {
|
|
||||||
pub response: SteamGuardAccount,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AccountLinkError {
|
pub enum AccountLinkError {
|
||||||
/// No phone number on the account
|
/// No phone number on the account
|
||||||
|
|
|
@ -47,6 +47,7 @@ pub struct SteamGuardAccount {
|
||||||
pub uri: String,
|
pub uri: String,
|
||||||
pub fully_enrolled: bool,
|
pub fully_enrolled: bool,
|
||||||
pub device_id: String,
|
pub device_id: String,
|
||||||
|
pub secret_1: String,
|
||||||
#[serde(rename = "Session")]
|
#[serde(rename = "Session")]
|
||||||
pub session: Option<steamapi::Session>,
|
pub session: Option<steamapi::Session>,
|
||||||
}
|
}
|
||||||
|
@ -84,6 +85,7 @@ impl SteamGuardAccount {
|
||||||
uri: String::from(""),
|
uri: String::from(""),
|
||||||
fully_enrolled: false,
|
fully_enrolled: false,
|
||||||
device_id: String::from(""),
|
device_id: String::from(""),
|
||||||
|
secret_1: "".into(),
|
||||||
session: Option::None,
|
session: Option::None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,11 @@ use std::iter::FromIterator;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
use crate::SteamGuardAccount;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref STEAM_COOKIE_URL: Url = "https://steamcommunity.com".parse::<Url>().unwrap();
|
static ref STEAM_COOKIE_URL: Url = "https://steamcommunity.com".parse::<Url>().unwrap();
|
||||||
|
static ref STEAM_API_BASE: String = "https://api.steampowered.com".into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
@ -340,6 +343,37 @@ impl SteamApiClient {
|
||||||
pub fn add_phone_number(&self, phone_number: String) -> anyhow::Result<bool> {
|
pub fn add_phone_number(&self, phone_number: String) -> anyhow::Result<bool> {
|
||||||
return self.phoneajax("add_phone_number", phone_number.as_str());
|
return self.phoneajax("add_phone_number", phone_number.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Starts the authenticator linking process.
|
||||||
|
/// This doesn't check any prereqisites to ensure the request will pass validation on Steam's side (eg. sms/email confirmations).
|
||||||
|
/// A valid `Session` is required for this request. Cookies are not needed for this request, but they are set anyway.
|
||||||
|
///
|
||||||
|
/// Host: api.steampowered.com
|
||||||
|
/// Endpoint: POST /ITwoFactorService/AddAuthenticator/v0001
|
||||||
|
pub fn add_authenticator(&self, device_id: String) -> anyhow::Result<AddAuthenticatorResponse> {
|
||||||
|
ensure!(matches!(self.session, Some(_)));
|
||||||
|
let params = hashmap! {
|
||||||
|
"access_token" => self.session.as_ref().unwrap().token.clone(),
|
||||||
|
"steamid" => self.session.as_ref().unwrap().steam_id.to_string(),
|
||||||
|
"authenticator_type" => "1".into(),
|
||||||
|
"device_identifier" => device_id,
|
||||||
|
"sms_phone_id" => "1".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = self
|
||||||
|
.post(format!(
|
||||||
|
"{}/ITwoFactorService/AddAuthenticator/v0001",
|
||||||
|
STEAM_API_BASE.to_string()
|
||||||
|
))
|
||||||
|
.form(¶ms)
|
||||||
|
.send()?
|
||||||
|
.text()?;
|
||||||
|
trace!("raw login response: {}", text);
|
||||||
|
|
||||||
|
let resp: AddAuthenticatorResponse = serde_json::from_str(text.as_str())?;
|
||||||
|
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -380,3 +414,51 @@ fn test_login_response_parse() {
|
||||||
);
|
);
|
||||||
assert_eq!(oauth.webcookie, "6298070A226E5DAD49938D78BCF36F7A7118FDD5");
|
assert_eq!(oauth.webcookie, "6298070A226E5DAD49938D78BCF36F7A7118FDD5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct AddAuthenticatorResponse {
|
||||||
|
pub response: AddAuthenticatorResponseInner,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct AddAuthenticatorResponseInner {
|
||||||
|
/// Shared secret between server and authenticator
|
||||||
|
pub shared_secret: String,
|
||||||
|
/// Authenticator serial number (unique per token)
|
||||||
|
pub serial_number: String,
|
||||||
|
/// code used to revoke authenticator
|
||||||
|
pub revocation_code: String,
|
||||||
|
/// URI for QR code generation
|
||||||
|
pub uri: String,
|
||||||
|
/// Current server time
|
||||||
|
pub server_time: u64,
|
||||||
|
/// Account name to display on token client
|
||||||
|
pub account_name: String,
|
||||||
|
/// Token GID assigned by server
|
||||||
|
pub token_gid: String,
|
||||||
|
/// Secret used for identity attestation (e.g., for eventing)
|
||||||
|
pub identity_secret: String,
|
||||||
|
/// Spare shared secret
|
||||||
|
pub secret_1: String,
|
||||||
|
/// Result code
|
||||||
|
pub status: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAuthenticatorResponse {
|
||||||
|
pub fn to_steam_guard_account(&self) -> SteamGuardAccount {
|
||||||
|
SteamGuardAccount {
|
||||||
|
shared_secret: self.response.shared_secret,
|
||||||
|
serial_number: self.response.serial_number,
|
||||||
|
revocation_code: self.response.revocation_code,
|
||||||
|
uri: self.response.uri,
|
||||||
|
server_time: self.response.server_time,
|
||||||
|
account_name: self.response.account_name,
|
||||||
|
token_gid: self.response.token_gid,
|
||||||
|
identity_secret: self.response.identity_secret,
|
||||||
|
secret_1: self.response.secret_1,
|
||||||
|
fully_enrolled: false,
|
||||||
|
device_id: "".into(),
|
||||||
|
session: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue