Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2fa support for microsoft accounts #791

Closed
MrGeorgen opened this issue Dec 15, 2020 · 15 comments · Fixed by #806
Closed

2fa support for microsoft accounts #791

MrGeorgen opened this issue Dec 15, 2020 · 15 comments · Fixed by #806

Comments

@MrGeorgen
Copy link

Nice to Microsoft accounts are now supported. Would be nice 2 factor authentication could also be added

@rom1504
Copy link
Member

rom1504 commented Dec 15, 2020

@MrGeorgen what would you expect would be the interface in this case?
print the browser URL to the console and let the user handle it?

@MrGeorgen
Copy link
Author

@MrGeorgen what would you expect would be the interface in this case?
print the browser URL to the console and let the user handle it?

yeah that's one way or open the url automatically in the standard browser

@Electroid
Copy link

Downstream projects may want to implement this in different ways. I'd suggest a callback with the URL as the argument, and the default callback would be printing to console.

@kashalls
Copy link
Contributor

kashalls commented Jan 5, 2021

I have a couple of methods I could look into adding this. The primary issue with using 2FA is that it requires human involvement.

  1. Detect Windows or Other. If Windows, Load up the Windows UX and open a window to ask the user to authenticate with XBOX Live. If not, figure something out.
  2. Another thing we can look into is try logging in, then if login is unauthorized, direct user to a mineflayer website, that allows them to authenticate with Xbox and returns a token they need to use to login.
  3. Pull a Device Token from a Logged In Minecraft and maybe generate an xbox auth token we can use to login into minecraft: https://github.com/XB1-Hexdecimal/XboxAuthTool/blob/master/XboxAuthTool/Program.cs

Didn't have much time tonight to think about it. Will see about it in the morning.

@extremeheat
Copy link
Member

extremeheat commented Jan 5, 2021

A simple solution is to just use the token in the launcher accounts json. This is already done for mojang accounts, it should be relatively simple to make that its own authentication method, it doesn’t have to be tied to mojang accounts.

Sending the user to a page is also possible, and once the auth is complete the website will callback to the app requesting the auth. The only problem here is it requires hosting a webserver on the nmp side on localhost so the browser can redirect to it. And it gets a bit complicated for people hosting mineflayer on remote machines. To do it this way, first we’d need to implementation session refreshing otherwise the users would have to sign in manually every time.

Re the device tokens, maybe that could work. Although I believe these are hardware based so it could be a bit complicated. And it gets complicated because nmp is an open source project, and people would have to setup their own app with Microsoft to be able to auth.

@kashalls
Copy link
Contributor

kashalls commented Jan 5, 2021

Might I add it might be even more difficult for multi-user bots to auth. It would get time consuming.

@extremeheat Any chance you know of any documentation for the launcher files? Microsoft Authentication abandons the use of launcher_accounts.json and opts for launcher_entitlements.json and launcher_msa_credentials.json

Formatting of the msa_credentials file needs to be documented before I can implement it.
Once I figure out everything, I'll update microsoftAuth.js and PR it.

@extremeheat
Copy link
Member

extremeheat commented Jan 5, 2021

Launcher_accounts.json is still used. It has the final access token used to talk to the Minecraft api/session server. I took a look at the msa credentials file, it seems to cache info from the Xbox api which is undocumented. Mojang uses a library to implement the Xbox auth, and that library is closed source, so you’ll have to reverse engineer it. Basically, the flow is: get ms auth token with Xbox scope -> get Xbox user tokens -> get XSTS -> send to Minecraft api -> mc api verifies xsts with xbox api -> server returns mc api/session server token. The Xbox user token data is stored in the msa credentials file, and it can be refreshed and used to obtain a XSTS token.

But again, it’s not necessary to do this other than to be able to refresh the token. The simple fix I mentioned was to just use the mojang API token in the launcher accounts json. This is used to talk to session server and has not changed. If it expires we can just have the user login again on the official launcher. The official launcher also has support for multiple accounts at the same time. The code to do this was already created by @ph0t0shop , it just needs to be decoupled from the mojang account code.

@kashalls
Copy link
Contributor

kashalls commented Jan 9, 2021

Currently working on 2FA support for nmp.

Here's the rundown for what we need to do though.

  • The user explicitly states they are using Two Factor Authentication
  1. Prompt a window with a URL, (electron or console) with the following url:
    https://login.live.com/oauth20_authorize.srf?client_id=000000004C12AE6F&redirect_uri=https://login.live.com/oauth20_desktop.srf&response_type=token&display=touch&scope=service::user.auth.xboxlive.com::MBI_SSL

  2. Catch response tokens in the hash involving access_token and refresh_token, we SAVE the refresh_token.

  3. Use our friendly non-documented but exposed "exchangeRpsTicketForUserToken" method from xboxlive-auth module.

  4. Exchange returned userToken for an XSTSToken (+ userHash) via exchangeTokensForXSTSIdentity method.

When the xsts token has expired, use the stored refresh token to get a fresh accesstoken (see https://docs.microsoft.com/en-us/advertising/guides/authentication-oauth-live-connect?view=bingads-13#refresh-accesstoken) and go to step 3.

Cudos to the @XboxReplay team for helping figure this out.

@extremeheat
Copy link
Member

Sounds like a lot of this should be implemented outside of nmp, possibly into the library. This isn’t Minecraft related and can be used for other non-nmp projects. The browser based way is already known, and it’s documented on wiki.vg, the problem with that was that it does not work headless. So if you run a bot for example on a remote server/the cloud, this is not an option, which is why I proposed pushing tokens. Also the current auth is very much hit or miss, it doesn’t work for me when I tried it (no 2FA) and there’s several other issues of it not working too. This is why I mentioned the hosting webserver part: the ms oauth lets you redirect to any url to send the return data to, so we can host a server in Xbox auth library, wait for a http callback -> take tokens and store them. The tokens can then be refreshed later. Also maybe the XboxReplay team can look into using the device tokens ? So the web server would not be needed at all.

@rom1504
Copy link
Member

rom1504 commented Jan 9, 2021

As mentioned in discord, using https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code seems pretty reasonable

  1. Put only user in createClient
  2. Give url to user for them to auth
  3. That gives us a device token
  4. We store that device token
  5. We auth ourselves with the device token

Next time we go directly to step 5

@ghost
Copy link

ghost commented Jan 12, 2021

Im a little bit unsettled, is it working now or not? Because i get an Error and i dont know how i can use my MCMicrosoftaccount to sign in. If it is possible, how? And if not when could it be possible?
My Error:

(node:2052) UnhandledPromiseRejectionWarning: Error: Unable to authenticate with Xbox Live: {"statusCode":401,"reason":"UNAUTHORIZED"}
at C:\Users\Lord 42\MCBot\node_modules\minecraft-protocol\src\client\microsoftAuth.js:27:30
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async module.exports (C:\Users\Lord 42\MCBot\node_modules\minecraft-protocol\src\client\microsoftAuth.js:25:25)
(Use node --trace-warnings ...to show where the warning was created) (node:2052) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag--unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:2052) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit

@rom1504
Copy link
Member

rom1504 commented Jan 12, 2021

@MikeMottonix it works only sometimes.
I listed above the steps to take to make it work always

@kashalls
Copy link
Contributor

@extremeheat is going to implement this I believe. I had a sudden loss in the family and I am needed somewhere else for the time - being. If it's not started by Saturday I'll start it.

@extremeheat
Copy link
Member

Reviewing this right now with @azure/msal-node. It seems that in order to use device code authentication you need an Azure app registered, I get 400s when trying to use the Minecraft client ID (00000000402b5328) or the Xbox Live app one in the XboxReplay library we're currently using. It seems to work fine if using one registered on Azure (that are in the UUID form). This might be due to the authority, I've tried https://login.microsoftonline.com/consumers and https://login.microsoftonline.com/common, neither of which work.

So to do this I think either the maintainers can make a Azure app to handle the auth, or people using the library will have to individually register their own apps. There's steps on the page rom1504 posted, basically to get the client ID:
client_id | Required | The Application (client) ID that the Azure portal – App registrations experience assigned to your app.

@extremeheat
Copy link
Member

For anyone that has a Microsoft account with Minecraft, try the fix in #806

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants