diff --git a/steamguard/src/fixtures/api-responses/login-response1.json b/steamguard/src/fixtures/api-responses/login-response1.json new file mode 100644 index 0000000..b16eb66 --- /dev/null +++ b/steamguard/src/fixtures/api-responses/login-response1.json @@ -0,0 +1 @@ +{"success":true,"requires_twofactor":false,"redirect_uri":"steammobile://mobileloginsucceeded","login_complete":true,"oauth":"{\"steamid\":\"78562647129469312\",\"account_name\":\"feuarus\",\"oauth_token\":\"fd2fdb3d0717bad2220d98c7ec61c7bd\",\"wgtoken\":\"72E7013D598A4F68C7E268F6FA3767D89D763732\",\"wgtoken_secure\":\"21061EA13C36D7C29812CAED900A215171AD13A2\",\"webcookie\":\"6298070A226E5DAD49938D78BCF36F7A7118FDD5\"}"} \ No newline at end of file diff --git a/steamguard/src/steamapi.rs b/steamguard/src/steamapi.rs index f61c56b..f936603 100644 --- a/steamguard/src/steamapi.rs +++ b/steamguard/src/steamapi.rs @@ -7,7 +7,7 @@ use reqwest::{ Url, }; use rsa::{PublicKey, RsaPublicKey}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Deserializer}; use std::collections::HashMap; use std::iter::FromIterator; use std::str::FromStr; @@ -30,11 +30,26 @@ struct LoginResponse { requires_twofactor: bool, #[serde(default)] message: String, + // #[serde(rename = "oauth")] + // oauth_raw: String, + #[serde(default, deserialize_with = "oauth_data_from_string")] oauth: Option, transfer_urls: Option>, transfer_parameters: Option, } +/// For some reason, the `oauth` field in the login response is a string of JSON, not a JSON object. +/// Deserializes to `Option` because the `oauth` field is not always there. +fn oauth_data_from_string<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + // for some reason, deserializing to &str doesn't work but this does. + let s: String = Deserialize::deserialize(deserializer)?; + let data: OAuthData = serde_json::from_str(s.as_str()).map_err(serde::de::Error::custom)?; + Ok(Some(data)) +} + #[derive(Debug, Clone, Serialize, Deserialize)] struct LoginTransferParameters { steamid: String, @@ -414,6 +429,7 @@ impl SteamApiClient { .send()?; let text = resp.text()?; trace!("raw login response: {}", text); + println!("raw login response: {}", text); let login_resp: LoginResponse = serde_json::from_str(text.as_str())?; @@ -470,3 +486,18 @@ fn test_oauth_data_parse() { assert_eq!(oauth.wgtoken_secure, "21061EA13C36D7C29812CAED900A215171AD13A2"); assert_eq!(oauth.webcookie, "6298070A226E5DAD49938D78BCF36F7A7118FDD5"); } + +#[test] +fn test_login_response_parse() { + let result = serde_json::from_str::(include_str!("fixtures/api-responses/login-response1.json")); + + assert!(matches!(result, Ok(_)), "got error: {}", result.unwrap_err()); + let resp = result.unwrap(); + + let oauth = resp.oauth.unwrap(); + assert_eq!(oauth.steamid, "78562647129469312"); + assert_eq!(oauth.oauth_token, "fd2fdb3d0717bad2220d98c7ec61c7bd"); + assert_eq!(oauth.wgtoken, "72E7013D598A4F68C7E268F6FA3767D89D763732"); + assert_eq!(oauth.wgtoken_secure, "21061EA13C36D7C29812CAED900A215171AD13A2"); + assert_eq!(oauth.webcookie, "6298070A226E5DAD49938D78BCF36F7A7118FDD5"); +}