File: xal.py

package info (click to toggle)
python-xbox-webapi 2.1.0-1.2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 2,900 kB
  • sloc: python: 4,973; makefile: 79
file content (112 lines) | stat: -rw-r--r-- 2,939 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
"""
Example scripts that performs XBL authentication via XAL
"""
import argparse
import asyncio
import json
import os
import uuid

from pydantic import BaseModel
from pydantic.json import pydantic_encoder

from xbox.webapi.authentication.models import (
    SisuAuthorizationResponse,
    XalAppParameters,
    XalClientParameters,
)
from xbox.webapi.authentication.xal import (
    APP_PARAMS_GAMEPASS_BETA,
    CLIENT_PARAMS_ANDROID,
    XALManager,
)
from xbox.webapi.common.signed_session import SignedSession
from xbox.webapi.scripts import XAL_TOKENS_FILE


class XALStore(BaseModel):
    """Used to store/load authorization data"""

    sisu: SisuAuthorizationResponse
    device_id: uuid.UUID
    app_params: XalAppParameters
    client_params: XalClientParameters


def user_prompt_authentication(auth_url: str) -> str:
    """
    Handles the auth callback when user is prompted to authenticate via URL
    in webbrowser

    Takes the redirect URL from stdin
    """

    redirect_url = input(
        f"Continue auth with the following URL:\n\n"
        f"URL: {auth_url}\n\n"
        f"Provide redirect URI: "
    )
    return redirect_url


async def do_auth(device_id: uuid.UUID, token_filepath: str):
    async with SignedSession() as session:
        app_params = APP_PARAMS_GAMEPASS_BETA
        client_params = CLIENT_PARAMS_ANDROID

        store = None
        # Load existing sisu authorization data, if it exists
        if os.path.exists(token_filepath):
            with open(token_filepath) as f:
                store = json.load(f)

            # Convert SISU authorization data
            store = XALStore(**store)

        if store:
            raise NotImplementedError("Token refreshing")

        # Do authentication
        xal = XALManager(session, device_id, app_params, client_params)
        response = await xal.auth_flow(user_prompt_authentication)
        print(f"Sisu auth finished:\n\n{response}")

        # Save authorization data
        store = XALStore(
            sisu=response,
            device_id=device_id,
            app_params=app_params,
            client_params=client_params,
        )

        with open(token_filepath, mode="w") as f:
            print(f"Finished authentication, writing tokens to {token_filepath}")
            json.dump(store, f, default=pydantic_encoder)


async def async_main():
    parser = argparse.ArgumentParser(description="Authenticate with XBL via XAL")
    parser.add_argument(
        "--tokens",
        "-t",
        default=XAL_TOKENS_FILE,
        help=f"Token filepath. Default: '{XAL_TOKENS_FILE}'",
    )
    parser.add_argument(
        "--device-id",
        "-did",
        default=uuid.uuid4(),
        type=uuid.UUID,
        help="Device ID (for device auth)",
    )
    args = parser.parse_args()

    await do_auth(args.device_id, args.tokens)


def main():
    asyncio.run(async_main())


if __name__ == "__main__":
    main()