Skip to content

Commit 91b0dcf

Browse files
committed
Add title auth
1 parent db16403 commit 91b0dcf

File tree

2 files changed

+79
-3
lines changed

2 files changed

+79
-3
lines changed

auth/xal_auth.py

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
import uuid
77
import base64
88
import hashlib
9+
import json
910
import asyncio
1011
import httpx
1112
from urllib import parse
12-
from typing import Optional
13+
from typing import Optional, Tuple
1314

1415
import ms_cv
1516
from auth.signed_session import SignedSession
@@ -121,6 +122,58 @@ async def _get_device_token(self) -> httpx.Response:
121122
request = self.session.build_request('POST', url, headers=headers, json=post_body)
122123
return await self.session.send_signed(request)
123124

125+
async def _get_title_token(
126+
self, device_token: str, access_token: str
127+
) -> httpx.Response:
128+
url = "https://title.auth.xboxlive.com/title/authenticate"
129+
headers = {"x-xbl-contract-version": "1", "MS-CV": self.cv.increment()}
130+
post_body = {
131+
"RelyingParty": "http://auth.xboxlive.com",
132+
"TokenType": "JWT",
133+
"Properties": {
134+
"AuthMethod": "RPS",
135+
"DeviceToken": device_token,
136+
"RpsTicket": f"t={access_token}",
137+
"SiteName": "user.auth.xboxlive.com",
138+
},
139+
}
140+
141+
request = self.session.build_request(
142+
"POST", url, headers=headers, json=post_body
143+
)
144+
return await self.session.send_signed(request)
145+
146+
async def get_title_token2(
147+
self,
148+
device_token: str,
149+
title_id: str = "49312658",
150+
title_version: str = "10.0.10011.16384",
151+
title_build: str = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF",
152+
title_content_id: str = "73DE1908-F71B-4C5C-821E-ED00A426E221",
153+
) -> httpx.Response:
154+
url = "https://title.auth.xboxlive.com/title/authenticate"
155+
headers = {"x-xbl-contract-version": "1", "MS-CV": self.cv.increment()}
156+
post_body = {
157+
"RelyingParty": "http://auth.xboxlive.com",
158+
"TokenType": "JWT",
159+
"Properties": {
160+
"DeviceToken": device_token,
161+
"TitleAttestation": json.dumps(
162+
{
163+
"Id": title_id,
164+
"Version": title_version,
165+
"Build": title_build,
166+
"ContentId": title_content_id,
167+
}
168+
),
169+
},
170+
}
171+
172+
request = self.session.build_request(
173+
"POST", url, headers=headers, json=post_body
174+
)
175+
return await self.session.send_signed(request)
176+
124177
async def _do_sisu_authentication(
125178
self,
126179
device_token_jwt: str,
@@ -277,7 +330,7 @@ async def sisu_authentication(
277330
device_token: str,
278331
code_challenge: str,
279332
state: str
280-
) -> (SisuAuthenticationResponse, str):
333+
) -> Tuple[SisuAuthenticationResponse, str]:
281334
print('::: SISU AUTHENTICATION :::')
282335
resp = await self._do_sisu_authentication(device_token, code_challenge, state)
283336
assert resp.status_code == 200,\

protocol/packets.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class VideoControlFlags:
4848
'data' / Bytes(this.data_size)
4949
)
5050

51+
class QosControlFlags:
52+
REINITIALIZE = 0x1
53+
5154
qos_server_policy = Struct(
5255
'schema_version' / Int32ul,
5356
'policy_length' / Int32ul,
@@ -59,4 +62,24 @@ class VideoControlFlags:
5962
qos_server_handshake = Struct(
6063
'protocol_version' / Int32ul,
6164
'min_supported_client_version' / Int32ul
62-
)
65+
)
66+
67+
qos_client_policy = Struct(
68+
'schema_version' / Int32ul
69+
)
70+
71+
qos_client_handshake = Struct(
72+
'protocol_version' / Int32ul,
73+
'initial_frame_id' / Int32ul
74+
)
75+
76+
qos_control = Struct(
77+
'flags' / Int32ul
78+
)
79+
80+
qos_data = Struct(
81+
'flags' / Int32ul,
82+
'frame_id' / Int32ul,
83+
# TBD
84+
)
85+

0 commit comments

Comments
 (0)