@@ -58,6 +58,8 @@ pub(crate) const EXPERIMENTAL_MESSAGE: &str =
5858#[ cfg( feature = "launch" ) ]
5959pub ( crate ) const MANIFEST_URL : & str =
6060 "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json" ;
61+ #[ cfg( feature = "auth" ) ]
62+ pub ( crate ) const LAUNCHER_CLIENT_ID : & str = "00000000402B5328" ;
6163
6264/// OAuth 2.0 Authentication
6365///
@@ -112,7 +114,7 @@ impl Oauth {
112114 let mut builder = AuthenticationBuilder :: builder ( ) ;
113115 builder
114116 . port ( self . port )
115- . client_id ( & self . client_id )
117+ . client_id ( Some ( & self . client_id ) )
116118 . of_type ( AuthType :: Oauth ) ;
117119 let auth_info = builder
118120 . get_info ( )
@@ -144,10 +146,10 @@ impl Oauth {
144146 AuthenticationBuilder :: builder ( )
145147 . bedrockrel ( Some ( bedrock_relm) )
146148 . of_type ( AuthType :: Oauth )
147- . client_secret ( client_secret)
148- . client_id ( & self . client_id )
149+ . client_secret ( Some ( client_secret) )
150+ . client_id ( Some ( & self . client_id ) )
149151 . port ( Some ( self . port ) )
150- . launch ( )
152+ . launch ( None , None )
151153 . await
152154 }
153155
@@ -216,6 +218,11 @@ pub enum AuthType {
216218 /// This is used for refreshing your token with Minecraft.
217219 #[ cfg( feature = "auth" ) ]
218220 Refresh ,
221+
222+ /// Minecraft authentification method
223+ ///
224+ /// Uses Minecraft Auth menthod (habdy if you want the minecraft background)
225+ Minecraft ,
219226}
220227
221228/// Represents a builder for authentication configurations.
@@ -226,10 +233,10 @@ pub enum AuthType {
226233#[ cfg( feature = "auth" ) ]
227234pub struct AuthenticationBuilder {
228235 auth_type : AuthType ,
229- client_id : String ,
236+ client_id : Option < String > ,
230237 scope : Option < String > ,
231- port : u16 ,
232- client_secrect : String ,
238+ port : Option < u16 > ,
239+ client_secret : Option < String > ,
233240 bedrockrel : bool ,
234241 refresh_token : Option < String > ,
235242}
@@ -244,6 +251,8 @@ pub struct AuthInfo {
244251 pub device_code : Option < CodeResponse > ,
245252 /// OAuth URL that you will recive based on AuthType::OAuth.
246253 pub ouath_url : Option < String > ,
254+ /// Redirect URL: Only needed when using minecraft auth
255+ pub redirect_url : Option < String > ,
247256}
248257
249258#[ cfg( feature = "auth" ) ]
@@ -252,10 +261,10 @@ impl AuthenticationBuilder {
252261 pub fn builder ( ) -> Self {
253262 Self {
254263 auth_type : AuthType :: Oauth ,
255- client_id : "" . to_string ( ) ,
264+ client_id : None ,
256265 scope : Some ( SCOPE . to_string ( ) ) ,
257- port : 8000 ,
258- client_secrect : "" . to_string ( ) ,
266+ port : Some ( 8000 ) ,
267+ client_secret : None ,
259268 bedrockrel : false ,
260269 refresh_token : None ,
261270 }
@@ -270,24 +279,28 @@ impl AuthenticationBuilder {
270279 }
271280
272281 /// Client ID from your application Required for `OAuth` & `DeviceCode`.
273- pub fn client_id ( & mut self , client_id : & str ) -> & mut Self {
274- self . client_id = client_id. to_string ( ) ;
282+ pub fn client_id ( & mut self , client_id : Option < & str > ) -> & mut Self {
283+ if client_id. is_some ( ) {
284+ self . client_id = client_id. map ( |id| id. to_string ( ) ) ;
285+ }
275286 self
276287 }
277288
278289 /// Port for the Temporary https Required for `OAuth``.
279290 pub fn port < T : Optional < u16 > > ( & mut self , port : T ) -> & mut Self {
280291 let port = match port. into ( ) {
281- Some ( port) => port,
282- None => 8000 ,
292+ Some ( port) => Some ( port) ,
293+ None => None ,
283294 } ;
284295 self . port = port;
285296 self
286297 }
287298
288299 /// Client Secret from your application Required for `OAuth` & `DeviceCode`.
289- pub fn client_secret ( & mut self , client_secret : & str ) -> & mut Self {
290- self . client_secrect = client_secret. to_string ( ) ;
300+ pub fn client_secret ( & mut self , client_secret : Option < & str > ) -> & mut Self {
301+ if client_secret. is_some ( ) {
302+ self . client_secret = client_secret. map ( |secret| secret. to_string ( ) ) ;
303+ }
291304 self
292305 }
293306
@@ -324,36 +337,63 @@ impl AuthenticationBuilder {
324337 /// Gets the code for device code method
325338 pub async fn get_info ( & mut self ) -> AuthInfo {
326339 let client = Client :: new ( ) ;
327- if self . auth_type == AuthType :: DeviceCode {
328- let code = device_authentication_code ( client, & self . client_id )
329- . await
330- . unwrap ( ) ;
331- AuthInfo {
332- device_code : Some ( code) ,
333- ouath_url : None ,
340+
341+ match self . auth_type {
342+ AuthType :: DeviceCode => {
343+ let client_id = & self . client_id . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
344+ let code = device_authentication_code ( client, client_id) . await . unwrap ( ) ;
345+ AuthInfo {
346+ device_code : Some ( code) ,
347+ ouath_url : None ,
348+ redirect_url : None ,
349+ }
334350 }
335- } else {
336- let url = format ! (
337- "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize/?client_id={}&response_type=code&redirect_uri=http://localhost:{}&response_mode=query&scope={}&state=12345" ,
338- self . client_id, self . port, SCOPE
339- ) ;
340- AuthInfo {
341- device_code : None ,
342- ouath_url : Some ( url) ,
351+ AuthType :: Oauth | AuthType :: Refresh => {
352+ let client_id = & self . client_id . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
353+ let url = format ! (
354+ "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize/?client_id={}&response_type=code&redirect_uri=http://localhost:{}&response_mode=query&scope={}&state=12345" ,
355+ client_id,
356+ self . port. expect( "EXPECTED PORT" ) ,
357+ self . scope. clone( ) . expect( "Expected Scope" )
358+ ) ;
359+ AuthInfo {
360+ device_code : None ,
361+ ouath_url : Some ( url) ,
362+ redirect_url : None ,
363+ }
364+ }
365+ AuthType :: Minecraft => {
366+ let redirect_url = "https://login.live.com/oauth20_desktop.srf" ;
367+ let url = format ! (
368+ "https://login.live.com/oauth20_authorize.srf?client_id={LAUNCHER_CLIENT_ID}&redirect_uri={}&response_type=code&scope=service::user.auth.xboxlive.com::MBI_SSL" ,
369+ redirect_url
370+ ) ;
371+
372+ AuthInfo {
373+ device_code : None ,
374+ ouath_url : Some ( url) ,
375+ redirect_url : Some ( redirect_url. to_string ( ) ) ,
376+ }
343377 }
344378 }
345379 }
346380
347381 /// Launchs the authentication process.
348- pub async fn launch ( & mut self ) -> Result < CustomAuthData , Box < dyn std:: error:: Error > > {
382+ pub async fn launch (
383+ & mut self ,
384+ code : Option < & str > ,
385+ redirect_url : Option < String > ,
386+ ) -> Result < CustomAuthData , Box < dyn std:: error:: Error > > {
349387 dbg ! ( & self . auth_type, & self . client_id) ;
350388 let client = Client :: new ( ) ;
351389
352390 match self . auth_type {
353391 AuthType :: Oauth => {
354- dbg ! ( & self . client_secrect, self . port) ;
355- print ! ( "{}" , self . client_id) ;
356- let server = ouath ( self . port ) ?. await ?;
392+ dbg ! ( & self . client_secret, self . port, & self . client_secret) ;
393+ let client_id = & self . client_id . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
394+ let client_secret = & self . client_secret . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
395+
396+ let server = ouath ( self . port . expect ( "EXPECTED PORT" ) ) ?. await ?;
357397 let server_token = ouath_token (
358398 client. clone ( ) ,
359399 None ,
@@ -363,10 +403,10 @@ impl AuthenticationBuilder {
363403 . expect ( "\x1b [31mXbox Expected code.\x1b [0m" )
364404 . as_str ( ) ,
365405 ) ,
366- & self . client_id ,
406+ client_id,
367407 self . scope . as_deref ( ) . unwrap_or_default ( ) ,
368- self . port ,
369- & self . client_secrect ,
408+ format ! ( "https://localhost:{}" , self . port. expect ( "EXPECTED PORT" ) ) ,
409+ Some ( client_secret ) ,
370410 )
371411 . await ?;
372412 let xbl = xbl ( client. clone ( ) , & server_token. access_token ) . await ?;
@@ -384,10 +424,12 @@ impl AuthenticationBuilder {
384424 }
385425 }
386426 AuthType :: DeviceCode => {
427+ let client_id = & self . client_id . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
428+
387429 print ! ( "{} \n Status: WIP (Work In Progress)" , EXPERIMENTAL_MESSAGE ) ;
388- let code = device_authentication_code ( client. clone ( ) , & self . client_id ) . await ?;
430+ let code = device_authentication_code ( client. clone ( ) , client_id) . await ?;
389431 let code_token =
390- authenticate_device ( client. clone ( ) , & code. device_code , & self . client_id ) . await ?;
432+ authenticate_device ( client. clone ( ) , & code. device_code , client_id) . await ?;
391433 let xbl = xbl ( client. clone ( ) , & code_token. token ) . await ?;
392434 let xts = xsts ( client. clone ( ) , & xbl. token , self . bedrockrel ) . await ?;
393435
@@ -403,6 +445,9 @@ impl AuthenticationBuilder {
403445 }
404446 }
405447 AuthType :: Refresh => {
448+ let client_id = & self . client_id . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
449+ let client_secret = & self . client_secret . clone ( ) . expect ( "EXPECTED CLIENT_ID" ) ;
450+
406451 if self . refresh_token == None {
407452 return Err ( Box :: new ( errors:: AuthErrors :: AuthenticationFailure (
408453 "Missing Refresh Token" . to_string ( ) ,
@@ -412,10 +457,41 @@ impl AuthenticationBuilder {
412457 client. clone ( ) ,
413458 self . refresh_token . clone ( ) ,
414459 None ,
415- & self . client_id ,
460+ client_id,
416461 self . scope . as_deref ( ) . unwrap_or_default ( ) ,
417- self . port ,
418- & self . client_secrect ,
462+ if self . port . is_some ( ) {
463+ format ! ( "https://localhost:{}" , self . port. expect( "EXPECTED PORT" ) )
464+ } else {
465+ redirect_url. expect ( "EXPECTED REDIRECT URL" )
466+ } ,
467+ Some ( client_secret) ,
468+ )
469+ . await ?;
470+ let xbl = xbl ( client. clone ( ) , & server_token. access_token ) . await ?;
471+ let xts = xsts ( client. clone ( ) , & xbl. token , self . bedrockrel ) . await ?;
472+
473+ if self . bedrockrel {
474+ Ok ( CustomAuthData {
475+ access_token : None ,
476+ uuid : None ,
477+ expires_in : 0 ,
478+ xts_token : Some ( xts. token ) ,
479+ } )
480+ } else {
481+ Ok ( bearer_token ( client, & xbl. display_claims . xui [ 0 ] . uhs , & xts. token ) . await ?)
482+ }
483+ }
484+ AuthType :: Minecraft => {
485+ dbg ! ( self . port) ;
486+
487+ let server_token = ouath_token (
488+ client. clone ( ) ,
489+ None ,
490+ code,
491+ LAUNCHER_CLIENT_ID ,
492+ "service::user.auth.xboxlive.com::MBI_SSL" ,
493+ redirect_url. expect ( "EXPECTED REDIRECT URL" ) ,
494+ None ,
419495 )
420496 . await ?;
421497 let xbl = xbl ( client. clone ( ) , & server_token. access_token ) . await ?;
0 commit comments