diff --git a/examples/src/bin/auth_azure.rs b/examples/src/bin/auth_azure.rs index 824bd2b..fa73336 100644 --- a/examples/src/bin/auth_azure.rs +++ b/examples/src/bin/auth_azure.rs @@ -15,6 +15,11 @@ use xal::{ }; use xal_examples::auth_main; +// Replace with your own Azure Client parameters +const CLIENT_ID: &'static str = "388ea51c-0b25-4029-aae2-17df49d23905"; +const REDIRECT_URL: &'static str = "http://localhost:8080/auth/callback"; +const CLIENT_SECRET: Option<&'static str> = None; + pub struct HttpCallbackHandler { bind_host: String, redirect_url_base: String, @@ -61,15 +66,14 @@ async fn main() -> Result<(), Error> { eprintln!("NOTE: --flow authorization-code required!"); auth_main( XalAppParameters { - app_id: "388ea51c-0b25-4029-aae2-17df49d23905".into(), + client_id: CLIENT_ID.into(), title_id: None, auth_scopes: vec![ Scope::new("Xboxlive.signin".into()), Scope::new("Xboxlive.offline_access".into()), ], - redirect_uri: Some( - RedirectUrl::new("http://localhost:8080/auth/callback".into()).unwrap(), - ), + redirect_uri: Some(RedirectUrl::new(REDIRECT_URL.into()).unwrap()), + client_secret: CLIENT_SECRET.map(|x| x.to_string()), }, CLIENT_ANDROID(), "RETAIL".into(), diff --git a/src/authenticator.rs b/src/authenticator.rs index 2c5d0c7..c5dabc8 100644 --- a/src/authenticator.rs +++ b/src/authenticator.rs @@ -407,10 +407,10 @@ impl XalAuthenticator { /// Create an internal [`oauth2::Client`] /// /// Refer to [`oauth2`] crate for it's usage - pub fn oauth_client(&self, client_secret: Option) -> Result { + pub fn oauth_client(&self) -> Result { let client = OAuthClient::new( - ClientId::new(self.app_params.app_id.to_string()), - client_secret, + ClientId::new(self.app_params.client_id.to_string()), + self.app_params.client_secret.clone().map(ClientSecret::new), AuthUrl::new(Constants::OAUTH20_AUTHORIZE_URL.to_string())?, Some(TokenUrl::new(Constants::OAUTH20_TOKEN_URL.to_string())?), ) @@ -438,13 +438,14 @@ impl XalAuthenticator { /// # async fn demo_code() { /// let mut authenticator = XalAuthenticator::new( /// XalAppParameters { - /// app_id: "388ea51c-0b25-4029-aae2-17df49d23905".into(), + /// client_id: "388ea51c-0b25-4029-aae2-17df49d23905".into(), /// title_id: None, /// auth_scopes: vec![ /// Scope::new("Xboxlive.signin".into()), /// Scope::new("Xboxlive.offline_access".into()) /// ], - /// redirect_uri: Some(RedirectUrl::new("https://login.live.com/oauth20_desktop.srf".into()).unwrap()) + /// redirect_uri: Some(RedirectUrl::new("https://login.live.com/oauth20_desktop.srf".into()).unwrap()), + /// client_secret: None, /// }, /// client_params::CLIENT_ANDROID(), /// "RETAIL".into() @@ -461,7 +462,7 @@ impl XalAuthenticator { implicit_flow: bool, ) -> Result<(EndUserVerificationUrl, CsrfToken), Error> { let client = - self.oauth_client(None)? + self.oauth_client()? .set_redirect_uri(self.app_params.redirect_uri.clone().ok_or( Error::InvalidRedirectUrl("Redirect URL was not provided".into()), )?); @@ -508,7 +509,7 @@ impl XalAuthenticator { pub async fn initiate_device_code_auth( &mut self, ) -> Result { - self.oauth_client(None)? + self.oauth_client()? .exchange_device_code() .unwrap() .add_scopes(self.app_params.auth_scopes.clone()) @@ -555,7 +556,7 @@ impl XalAuthenticator { S: Fn(std::time::Duration) -> SF, SF: std::future::Future, { - self.oauth_client(None)? + self.oauth_client()? .exchange_device_access_token(device_auth_resp) .request_async(&async_http_client, sleep_fn, None) .await @@ -592,7 +593,7 @@ impl XalAuthenticator { authorization_code: AuthorizationCode, code_verifier: Option, ) -> Result { - let client = self.oauth_client(None)?; + let client = self.oauth_client()?; let mut req = client.exchange_code(authorization_code); @@ -656,7 +657,7 @@ impl XalAuthenticator { T: serde::de::DeserializeOwned, { let resp = self - .oauth_client(None)? + .oauth_client()? .exchange_refresh_token(refresh_token) .add_scopes(scopes) .request_async(&async_http_client) @@ -791,7 +792,7 @@ impl XalAuthenticator { ))?; let json_body = request::SisuAuthenticationRequest { - app_id: &self.app_params.app_id, + app_id: &self.app_params.client_id, title_id: &title_id, redirect_uri: self.app_params.redirect_uri.as_deref().ok_or( Error::InvalidRedirectUrl("sisu_authenticate requires Redirect URL".to_string()), @@ -892,7 +893,7 @@ impl XalAuthenticator { ) -> Result { let json_body = request::SisuAuthorizationRequest { access_token: &format!("t={}", access_token.access_token().secret()), - app_id: &self.app_params.app_id, + app_id: &self.app_params.client_id, device_token: &device_token.token, sandbox: &self.sandbox_id.clone(), site_name: "user.auth.xboxlive.com", diff --git a/src/models.rs b/src/models.rs index 62c0bd3..abaeffc 100644 --- a/src/models.rs +++ b/src/models.rs @@ -506,14 +506,16 @@ impl ToString for DeviceType { /// Mandatory for XAL authentication flow #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct XalAppParameters { - /// App Id (For authorization/permission scope) - pub app_id: String, - /// App Title-Id (For TitleToken) + /// OAuth2 Client Id + pub client_id: String, + /// App Title-Id (Required for SISU auth flow, for TitleToken) pub title_id: Option, /// Scopes pub auth_scopes: Vec, /// Redirect Uri (For OAuth2 code response) pub redirect_uri: Option, + /// OAuth2 Client Secret + pub client_secret: Option, } /// Application parameter constants @@ -544,52 +546,56 @@ pub mod app_params { /// Xbox Beta App pub fn APP_XBOX_BETA() -> XalAppParameters { XalAppParameters { - app_id: "000000004415494b".into(), + client_id: "000000004415494b".into(), title_id: Some("177887386".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], // Originally "ms-xal-000000004415494b://auth" redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Xbox App pub fn APP_XBOX() -> XalAppParameters { XalAppParameters { - app_id: "000000004c12ae6f".into(), + client_id: "000000004c12ae6f".into(), title_id: Some("328178078".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], // Originally "ms-xal-000000004c12ae6f://auth" redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Gamepass App pub fn APP_GAMEPASS() -> XalAppParameters { XalAppParameters { - app_id: "000000004c20a908".into(), + client_id: "000000004c20a908".into(), title_id: Some("1016898439".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], // Originally "ms-xal-000000004c20a908://auth" redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Gamepass Beta App pub fn APP_GAMEPASS_BETA() -> XalAppParameters { XalAppParameters { - app_id: "000000004c20a908".into(), + client_id: "000000004c20a908".into(), title_id: Some("1016898439".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], // Originally "ms-xal-public-beta-000000004c20a908://auth" redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } @@ -598,86 +604,92 @@ pub mod app_params { /// Uses default `oauth20_desktop.srf` redirect uri pub fn APP_FAMILY_SETTINGS() -> XalAppParameters { XalAppParameters { - app_id: "00000000482C8F49".into(), + client_id: "00000000482C8F49".into(), title_id: Some("1618633878".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Old Xbox App (non-sisu-flow) pub fn APP_OLD_XBOX_APP() -> XalAppParameters { XalAppParameters { - app_id: "0000000048093EE3".into(), + client_id: "0000000048093EE3".into(), title_id: None, auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Minecraft for Windows (JAVA) pub fn MC_JAVA_WIN32() -> XalAppParameters { XalAppParameters { - app_id: "00000000402b5328".into(), + client_id: "00000000402b5328".into(), title_id: None, auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Minecraft Bedrock (Nintendo Switch) pub fn MC_BEDROCK_SWITCH() -> XalAppParameters { XalAppParameters { - app_id: "00000000441cc96b".into(), + client_id: "00000000441cc96b".into(), title_id: Some("2047319603".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Minecraft Bedrock (Android) pub fn MC_BEDROCK_ANDROID() -> XalAppParameters { XalAppParameters { - app_id: "0000000048183522".into(), + client_id: "0000000048183522".into(), title_id: Some("1739947436".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /// Minecraft Bedrock (iOS) pub fn MC_BEDROCK_IOS() -> XalAppParameters { XalAppParameters { - app_id: "000000004c17c01a".into(), + client_id: "000000004c17c01a".into(), title_id: Some("1810924247".into()), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: Some( RedirectUrl::new(crate::Constants::OAUTH20_DESKTOP_REDIRECT_URL.into()).unwrap(), ), + client_secret: None, } } /* /// Minecraft Bedrock (Win32)) pub const MC_BEDROCK_WIN32: XalAppParameters = XalAppParameters { - app_id: "".into(), + client_id: "".into(), title_id: "896928775".into(), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: None, }; pub const MC_BEDROCK_PLAYSTATION: XalAppParameters = XalAppParameters { - app_id: "".into(), + client_id: "".into(), title_id: "2044456598".into(), auth_scopes: vec![Scope::new(Constants::SCOPE_SERVICE_USER_AUTH.to_string())], redirect_uri: None, diff --git a/src/tokenstore.rs b/src/tokenstore.rs index 786de34..0f1de92 100644 --- a/src/tokenstore.rs +++ b/src/tokenstore.rs @@ -190,10 +190,10 @@ mod tests { #[test] fn read_from_string() { - let tokens_str = r#"{"app_params":{"app_id":"00000000441cc96b","title_id":"42","auth_scopes":["service::user.auth.xboxlive.com::MBI_SSL"],"redirect_uri":"https://login.live.com/oauth20_desktop.srf"},"client_params":{"user_agent":"XAL","device_type":"NINTENDO","client_version":"0.0.0","query_display":"touch"},"sandbox_id":"RETAIL","live_token":{"access_token":"accessTokenABC","token_type":"bearer","expires_in":86400,"refresh_token":"refreshTokenABC","scope":"service::user.auth.xboxlive.com::MBI_SSL"}}"#; + let tokens_str = r#"{"app_params":{"client_id":"00000000441cc96b","title_id":"42","auth_scopes":["service::user.auth.xboxlive.com::MBI_SSL"],"redirect_uri":"https://login.live.com/oauth20_desktop.srf"},"client_params":{"user_agent":"XAL","device_type":"NINTENDO","client_version":"0.0.0","query_display":"touch"},"sandbox_id":"RETAIL","live_token":{"access_token":"accessTokenABC","token_type":"bearer","expires_in":86400,"refresh_token":"refreshTokenABC","scope":"service::user.auth.xboxlive.com::MBI_SSL"}}"#; let ts = TokenStore::deserialize_from_string(tokens_str).unwrap(); - assert_eq!(ts.app_params.app_id, "00000000441cc96b"); + assert_eq!(ts.app_params.client_id, "00000000441cc96b"); assert_eq!(ts.app_params.title_id, Some("42".into())); assert_eq!( ts.app_params.auth_scopes.first().unwrap().as_str(),