diff --git a/fclauncher/app.go b/fclauncher/app.go index 9a147ae..603a4a8 100644 --- a/fclauncher/app.go +++ b/fclauncher/app.go @@ -56,6 +56,8 @@ func (a *App) CheckPrerequisites() { a.Auth, err = TokenRefresh(*a, a.Auth) if err == nil { authenticated = true + } else { + fmt.Printf("token reauth failed, requesting device code: %s\n", err) } } if !authenticated { diff --git a/fclauncher/auth.go b/fclauncher/auth.go index aa952c5..9884181 100644 --- a/fclauncher/auth.go +++ b/fclauncher/auth.go @@ -12,46 +12,45 @@ import ( wruntime "github.com/wailsapp/wails/v2/pkg/runtime" ) - type LauncherAuth struct { - Id string - Name string + Id string + Name string Token string } type McProfile struct { - Id string + Id string Name string } type devcodeResp struct { - User_code string - Device_code string + User_code string + Device_code string Verification_url string - Expires_in string - Interval int - Message string + Expires_in string + Interval int + Message string } type authenticationResp struct { - Access_token string - Token_type string - Refresh_token string - Expires_in string - Error string + Access_token string + Token_type string + Refresh_token string + Expires_in string + Error string Error_description string } type xboxAuthProperties struct { AuthMethod string - SiteName string - RpsTicket string + SiteName string + RpsTicket string } type xboxAuthRequest struct { - Properties xboxAuthProperties + Properties xboxAuthProperties RelyingParty string - TokenType string + TokenType string } type xboxDisplayClaim struct { @@ -69,40 +68,40 @@ type xboxDisplayClaims struct { } type xboxAuthResponse struct { - IssueInstant time.Time - NotAfter time.Time - Token string + IssueInstant time.Time + NotAfter time.Time + Token string DisplayClaims xboxDisplayClaims } type XSTSProperties struct { - SandboxId string + SandboxId string UserTokens []string } type XSTSRequest struct { - Properties XSTSProperties + Properties XSTSProperties RelyingParty string - TokenType string + TokenType string } type McAuthRequest struct { - Xtoken string `json:"xtoken"` + Xtoken string `json:"xtoken"` Platform string `json:"platform"` } type McAuthResponse struct { - Username string + Username string Access_token string - Expires_in string - Token_type string + Expires_in string + Token_type string } func AuthCode(a App) (authenticationResp, error) { authentication := authenticationResp{} resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", url.Values{ "client_id": {client_id}, - "scope": {"XboxLive.SignIn XboxLive.offline_access"}, + "scope": {"XboxLive.SignIn XboxLive.offline_access"}, }) if err != nil { return authentication, fmt.Errorf("Unable to request device code: %e\n", err) @@ -119,9 +118,9 @@ func AuthCode(a App) (authenticationResp, error) { ticker := time.NewTicker(time.Second * time.Duration(codeResp.Interval)) for range ticker.C { resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", url.Values{ - "client_id": {client_id}, - "grant_type": {"urn:ietf:params:oauth:grant-type:device_code"}, - "device_code": {codeResp.Device_code}, + "client_id": {client_id}, + "grant_type": {"urn:ietf:params:oauth:grant-type:device_code"}, + "device_code": {codeResp.Device_code}, }) if err != nil { return authentication, fmt.Errorf("Authentication request error %e\n", err) @@ -138,10 +137,10 @@ func AuthCode(a App) (authenticationResp, error) { func TokenRefresh(app App, auth authenticationResp) (authenticationResp, error) { resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", url.Values{ - "client_id": {client_id}, - "grant_type": {"refresh_token"}, - "refresh_token": {auth.Refresh_token}, - "scope": {"XboxLive.SignIn XboxLive.offline_access"}, + "client_id": {client_id}, + "grant_type": {"refresh_token"}, + "refresh_token": {auth.Refresh_token}, + "scope": {"XboxLive.SignIn XboxLive.offline_access"}, }) if err != nil { return authenticationResp{}, fmt.Errorf("unable to request refresh token: %e\n", err) @@ -150,12 +149,15 @@ func TokenRefresh(app App, auth authenticationResp) (authenticationResp, error) data, _ := io.ReadAll(resp.Body) authResp := authenticationResp{} json.Unmarshal(data, &authResp) + if authResp.Error != "" { + return authResp, fmt.Errorf("unable to request new token: %s", authResp.Error_description) + } return authResp, nil } func MicrosoftAuth(auth authenticationResp) (LauncherAuth, error) { //Xbox Live Auth - req, _ := json.Marshal(xboxAuthRequest{Properties: xboxAuthProperties{AuthMethod: "RPS", SiteName: "user.auth.xboxlive.com", RpsTicket: "d="+auth.Access_token}, RelyingParty: "http://auth.xboxlive.com", TokenType: "JWT"}) + req, _ := json.Marshal(xboxAuthRequest{Properties: xboxAuthProperties{AuthMethod: "RPS", SiteName: "user.auth.xboxlive.com", RpsTicket: "d=" + auth.Access_token}, RelyingParty: "http://auth.xboxlive.com", TokenType: "JWT"}) client := http.Client{} httpreq, _ := http.NewRequest("POST", "https://user.auth.xboxlive.com/user/authenticate", bytes.NewBuffer(req)) httpreq.Header.Add("x-xbl-contract-version", "1") @@ -169,7 +171,7 @@ func MicrosoftAuth(auth authenticationResp) (LauncherAuth, error) { if httpResp.StatusCode != 200 { return LauncherAuth{}, fmt.Errorf("unable to obtain xbox live token: %s\n", httpResp.Status) } - d,_ := io.ReadAll(httpResp.Body) + d, _ := io.ReadAll(httpResp.Body) xblAuth := xboxAuthResponse{} json.Unmarshal(d, &xblAuth) xstsData, _ := json.Marshal(XSTSRequest{Properties: XSTSProperties{SandboxId: "RETAIL", UserTokens: []string{xblAuth.Token}}, RelyingParty: "rp://api.minecraftservices.com/", TokenType: "JWT"}) @@ -186,7 +188,7 @@ func MicrosoftAuth(auth authenticationResp) (LauncherAuth, error) { d, _ = io.ReadAll(httpResp.Body) mcApi := xboxAuthResponse{} json.Unmarshal(d, &mcApi) - mcAuthData, _ := json.Marshal(McAuthRequest{Xtoken: "XBL 3.0 x=" + mcApi.DisplayClaims.Xui[0].Uhs+ ";" + mcApi.Token, Platform: "PC_LAUNCHER"}) + mcAuthData, _ := json.Marshal(McAuthRequest{Xtoken: "XBL 3.0 x=" + mcApi.DisplayClaims.Xui[0].Uhs + ";" + mcApi.Token, Platform: "PC_LAUNCHER"}) httpReqMC, _ := http.NewRequest("POST", "https://api.minecraftservices.com/launcher/login", bytes.NewBuffer(mcAuthData)) httpReqMC.Header.Add("Content-Type", "application/json") httpReqMC.Header.Add("Accept", "application/json")