-
Notifications
You must be signed in to change notification settings - Fork 183
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
Microsoft Accounts #234
Comments
sadly its not so straight forward, cause its kinda expected that you do this interactively, I am not sure if MSA has flows enabled that allow username password authentication like that. edit: seems like I am wrong, prismarine is able to use device code flows https://github.com/PrismarineJS/node-minecraft-protocol/blob/master/src/client/microsoftAuth.js |
Actually PrismarineJS doesn't use the device code flow by default, it only does if it can't authenticate on Xbox live with a username / password Over the last few days I've been developing a custom Minecraft proxy and I needed Microsoft auth for someone, so I tried to implement it. Actually, my implementation is somewhat compatible with the one of pyCraft, so it might work right away (provided that you only call authenticate and join_server) |
Hmmm, so how can I use that, because I tried a lot stuff with your implementation and I can't get that to work. |
Actually, I meant compatible as in "doesn't need to rewrite everything that uses the auth_token variable", my token classes use pretty much the same functions as the current one, so it might work, but I'm not sure how seamless it would be That said, if something were to work, it would look something like this: auth_token= MicrosoftAuthenticationToken()
auth_token.authenticate("email", "password")
connection = Connection("127.0.0.1", 25565, auth_token=auth_token)
... Just for context, I don't actually know how to use pycraft even tho I read a lot of its code for my project, so there might be something I missed. |
I have a similar process that gets the bearer token (drawback is that it ofc doesn't support 2FA enabled accounts). It's in rust but it should be easy enough to understand. |
I made it on Python! Just change a little for it |
Links not working. Anyone else has any clue about the Microsoft Login situation? |
If you are still struggling you can use helper/Auth.py as an example on how to implement it using a local http server and your default webbrowser.
The reason I implemented it in two steps was that a server for which one only has console access does not provide a default browser. See README#server. And as the usual you need an Azure App for this to work to begin with. See README#microsoft-login. |
You need register a toke. For more information, See wiki.vg |
404? |
@martinersej #253 U can add this code to ur authentication.py # ... imports
import os
# other code.....
class Microsoft_AuthenticationToken(object):
"""
Represents an authentication token.
See https://wiki.vg/Microsoft_Authentication_Scheme.
"""
UserLoginURL = "https://login.live.com/oauth20_authorize.srf?\
client_id=00000000402b5328&response_type=code\
&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=\
https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"
oauth20_URL = 'https://login.live.com/oauth20_token.srf'
XBL_URL = 'https://user.auth.xboxlive.com/user/authenticate'
XSTS_URL = 'https://xsts.auth.xboxlive.com/xsts/authorize'
LOGIN_WITH_XBOX_URL = "https://api.minecraftservices.com/\
authentication/login_with_xbox"
CheckAccount_URL = 'https://api.minecraftservices.com/entitlements/mcstore'
Profile_URL = 'https://api.minecraftservices.com/minecraft/profile'
jwt_Token = ''
def __init__(self, access_token=None):
self.access_token = access_token
self.profile = Profile()
def GetoAuth20(self, code='') -> object:
if code == '':
print("Please copy this link to your browser to open:"
"\n%s" % self.UserLoginURL)
code = input(
"After logging in,"
"paste the 'code' field in your browser's address bar here:")
oauth20 = requests.post(
self.oauth20_URL,
data={
"client_id": "00000000402b5328",
"code": "{}".format(code),
"grant_type": "authorization_code",
"redirect_uri": "https://login.live.com/oauth20_desktop.srf",
"scope": "service::user.auth.xboxlive.com::MBI_SSL"
},
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=15)
oauth20 = json.loads(oauth20.text)
if 'error' in oauth20:
print("Error: %s" % oauth20["error"])
return 1
else:
self.oauth20_access_token = oauth20['access_token']
self.oauth20_refresh_token = oauth20['refresh_token']
oauth20_access_token = oauth20['access_token']
oauth20_refresh_token = oauth20['refresh_token']
return {
"access_token": oauth20_access_token,
"refresh_token": oauth20_refresh_token
}
def GetXBL(self, access_token: str) -> object:
XBL = requests.post(self.XBL_URL,
json={
"Properties": {
"AuthMethod": "RPS",
"SiteName": "user.auth.xboxlive.com",
"RpsTicket": "{}".format(access_token)
},
"RelyingParty": "http://auth.xboxlive.com",
"TokenType": "JWT"
},
headers=HEADERS,
timeout=15)
return {
"Token": json.loads(XBL.text)['Token'],
"uhs": json.loads(XBL.text)['DisplayClaims']['xui'][0]['uhs']
}
def GetXSTS(self, access_token: str) -> object:
XBL = requests.post(self.XSTS_URL,
json={
"Properties": {
"SandboxId": "RETAIL",
"UserTokens": ["{}".format(access_token)]
},
"RelyingParty":
"rp://api.minecraftservices.com/",
"TokenType": "JWT"
},
headers=HEADERS,
timeout=15)
return {
"Token": json.loads(XBL.text)['Token'],
"uhs": json.loads(XBL.text)['DisplayClaims']['xui'][0]['uhs']
}
def GetXBOX(self, access_token: str, uhs: str) -> str:
mat_jwt = requests.post(
self.LOGIN_WITH_XBOX_URL,
json={"identityToken": "XBL3.0 x={};{}".format(uhs, access_token)},
headers=HEADERS,
timeout=15)
self.access_token = json.loads(mat_jwt.text)['access_token']
return self.access_token
def CheckAccount(self, jwt_Token: str) -> bool:
CheckAccount = requests.get(
self.CheckAccount_URL,
headers={"Authorization": "Bearer {}".format(jwt_Token)},
timeout=15)
CheckAccount = len(json.loads(CheckAccount.text)['items'])
if CheckAccount != 0:
return True
else:
return False
def GetProfile(self, access_token: str) -> object:
if self.CheckAccount(access_token):
Profile = requests.get(
self.Profile_URL,
headers={"Authorization": "Bearer {}".format(access_token)},
timeout=15)
Profile = json.loads(Profile.text)
if 'error' in Profile:
return False
self.profile.id_ = Profile["id"]
self.profile.name = Profile["name"]
self.username = Profile["name"]
return True
else:
return False
@property
def authenticated(self):
"""
Attribute which is ``True`` when the token is authenticated and
``False`` when it isn't.
"""
if not self.username:
return False
if not self.access_token:
return False
if not self.oauth20_refresh_token:
return False
if not self.profile:
return False
return True
def authenticate(self):
"Get verification information for a Microsoft account"
oauth20 = self.GetoAuth20()
if oauth20 == 1:
return False
XBL = self.GetXBL(oauth20['access_token'])
XSTS = self.GetXSTS(XBL['Token'])
XBOX = self.GetXBOX(XSTS['Token'], XSTS['uhs'])
if self.GetProfile(XBOX):
print('GameID: {}'.format(self.profile.id_))
self.PersistenceLogoin_w()
return True
else:
print('Account does not exist')
return False
def refresh(self):
"""
Refreshes the `AuthenticationToken`. Used to keep a user logged in
between sessions and is preferred over storing a user's password in a
file.
Returns:
Returns `True` if `AuthenticationToken` was successfully refreshed.
Otherwise it raises an exception.
Raises:
minecraft.exceptions.YggdrasilError
ValueError - if `AuthenticationToken.access_token` or
`AuthenticationToken.client_token` isn't set.
"""
if self.access_token is None:
raise ValueError("'access_token' not set!'")
if self.oauth20_refresh_token is None:
raise ValueError("'oauth20_refresh_token' is not set!")
oauth20 = requests.post(
self.oauth20_URL,
data={
"client_id": "00000000402b5328",
"refresh_token": "{}".format(self.oauth20_refresh_token),
"grant_type": "refresh_token",
"redirect_uri": "https://login.live.com/oauth20_desktop.srf",
"scope": "service::user.auth.xboxlive.com::MBI_SSL"
},
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=15)
oauth20 = json.loads(oauth20.text)
if 'error' in oauth20:
print("Error: %s" % oauth20["error"])
return False
else:
self.oauth20_access_token = oauth20['access_token']
self.oauth20_refresh_token = oauth20['refresh_token']
XBL = self.GetXBL(self.oauth20_access_token)
XSTS = self.GetXSTS(XBL['Token'])
XBOX = self.GetXBOX(XSTS['Token'], XSTS['uhs'])
if self.GetProfile(XBOX):
self.PersistenceLogoin_w()
print('account: {}'.format(self.profile.id_))
return True
else:
print('Account does not exist')
return False
def join(self, server_id):
"""
Informs the Mojang session-server that we're joining the
MineCraft server with id ``server_id``.
Parameters:
server_id - ``str`` with the server id
Returns:
``True`` if no errors occured
Raises:
:class:`minecraft.exceptions.YggdrasilError`
"""
if not self.authenticated:
err = "AuthenticationToken hasn't been authenticated yet!"
raise YggdrasilError(err)
res = _make_request(
SESSION_SERVER, "join", {
"accessToken": self.access_token,
"selectedProfile": self.profile.to_dict(),
"serverId": server_id
})
if res.status_code != 204:
_raise_from_response(res)
return True
def PersistenceLogoin_w(self):
"Save access token persistent login"
ProjectDir = os.path.dirname(os.path.dirname('{}'.format(__file__)))
PersistenceDir = '{}/Persistence'.format(ProjectDir)
if not self.authenticated:
err = "AuthenticationToken hasn't been authenticated yet!"
raise YggdrasilError(err)
if not os.path.exists(PersistenceDir):
os.mkdir(PersistenceDir)
print(PersistenceDir)
"Save access_token and oauth20_refresh_token"
with open("{}/{}".format(PersistenceDir, self.username),
mode='w',
encoding='utf-8') as file_obj:
file_obj.write('{{"{}": "{}","{}": "{}"}}'.format(
'access_token', self.access_token, 'oauth20_refresh_token',
self.oauth20_refresh_token))
file_obj.close()
return True
def PersistenceLogoin_r(self, GameID: str):
"Load access token persistent login"
ProjectDir = os.path.dirname(os.path.dirname('{}'.format(__file__)))
PersistenceDir = '{}/Persistence'.format(ProjectDir)
if not os.path.exists(PersistenceDir):
return False
"Load access_token and oauth20_refresh_token"
if os.path.isfile("{}/{}".format(PersistenceDir, GameID)):
with open("{}/{}".format(PersistenceDir, GameID),
mode='r',
encoding='utf-8') as file_obj:
Persistence = file_obj.read()
file_obj.close()
Persistence = json.loads(Persistence)
self.access_token = Persistence["access_token"]
self.oauth20_refresh_token = Persistence[
"oauth20_refresh_token"]
self.refresh()
return self.authenticated
else:
return False auth = minecraft.authentication.Microsoft_AuthenticationToken()
auth.authenticate()
conn = minecraft.networking.connection.Connection("mc.hypixel.net", 25565, auth, None, "1.8") |
I think u need to update ur authentication.py file to get microsoft accounts to work with that.
U can example do that
authentication.AuthenticationToken().authenticate(username, password, microsoft_account=True)
.The text was updated successfully, but these errors were encountered: