or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-gpsoauth

A python client library for Google Play Services OAuth.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/gpsoauth@2.0.x

To install, run

npx @tessl/cli install tessl/pypi-gpsoauth@2.0.0

index.mddocs/

GPSOAuth

A Python client library for Google Play Services OAuth that enables programmatic authentication with Google services using the "master token" flow. This library implements the authentication protocol that allows Python applications to pose as Google apps and obtain OAuth tokens for various Google services without interactive authentication.

Package Information

  • Package Name: gpsoauth
  • Language: Python
  • Installation: pip install gpsoauth

Core Imports

import gpsoauth

For accessing specific utilities:

from gpsoauth.google import construct_signature, key_from_b64, parse_auth_response, key_to_struct
from gpsoauth.util import bytes_to_int, int_to_bytes

Basic Usage

Master Login Flow (Primary Method)

import gpsoauth

# Account credentials and device identifier
email = 'example@gmail.com'
password = 'my-password'
android_id = '0123456789abcdef'

# Step 1: Perform master login to get master token
master_response = gpsoauth.perform_master_login(email, password, android_id)
master_token = master_response['Token']

# Step 2: Use master token to get service-specific auth token
auth_response = gpsoauth.perform_oauth(
    email, master_token, android_id,
    service='sj', 
    app='com.google.android.music',
    client_sig='38918a453d07199354f8b19af05ec6562ced5788'
)
auth_token = auth_response['Auth']

# Use auth_token in Authorization header: "GoogleLogin auth={auth_token}"

Alternative Token Exchange Flow

For cases where BadAuthentication errors occur with the master login flow:

import gpsoauth

email = 'example@gmail.com'
android_id = '0123456789abcdef'
oauth_token = '...'  # Obtained from https://accounts.google.com/EmbeddedSetup

# Exchange web OAuth token for master token
master_response = gpsoauth.exchange_token(email, oauth_token, android_id)
master_token = master_response['Token']

# Continue with oauth flow as above
auth_response = gpsoauth.perform_oauth(
    email, master_token, android_id,
    service='sj',
    app='com.google.android.music', 
    client_sig='38918a453d07199354f8b19af05ec6562ced5788'
)

Capabilities

Master Authentication

Primary authentication method that performs the initial Google account login to obtain a master token.

def perform_master_login(
    email: str,
    password: str,
    android_id: str,
    service: str = "ac2dm",
    device_country: str = "us",
    operator_country: str = "us",
    lang: str = "en",
    sdk_version: int = 17,
    proxy: MutableMapping[str, str] | None = None,
    client_sig: str = "38918a453d07199354f8b19af05ec6562ced5788"
) -> dict[str, str]:
    """
    Perform a master login, which is what Android does when you first add
    a Google account.

    Parameters:
    - email: Google account email address
    - password: Google account password
    - android_id: Android device identifier (16-character hex string)
    - service: Service type for authentication (default: "ac2dm")
    - device_country: Device country code (default: "us")
    - operator_country: Operator country code (default: "us")
    - lang: Language code (default: "en")
    - sdk_version: Android SDK version number (default: 17)
    - proxy: Optional proxy configuration dictionary
    - client_sig: Client signature hash for app identification

    Returns:
    dict: Authentication response containing keys like:
        - 'Auth': Master authentication token
        - 'Token': OAuth refresh token
        - 'Email': Account email
        - 'SID': Session ID
        - 'LSID': Long-term session ID
        - Other account metadata fields
    """

Token Exchange Authentication

Alternative authentication method for exchanging web OAuth tokens when the master login flow fails.

def exchange_token(
    email: str,
    token: str,
    android_id: str,
    service: str = "ac2dm",
    device_country: str = "us",
    operator_country: str = "us",
    lang: str = "en",
    sdk_version: int = 17,
    proxy: MutableMapping[str, str] | None = None,
    client_sig: str = "38918a453d07199354f8b19af05ec6562ced5788"
) -> dict[str, str]:
    """
    Exchanges a web oauth_token for a master token.

    Parameters:
    - email: Google account email address
    - token: OAuth token obtained from web authentication flow
    - android_id: Android device identifier (16-character hex string)
    - service: Service type for authentication (default: "ac2dm")
    - device_country: Device country code (default: "us")
    - operator_country: Operator country code (default: "us")
    - lang: Language code (default: "en")
    - sdk_version: Android SDK version number (default: 17)
    - proxy: Optional proxy configuration dictionary
    - client_sig: Client signature hash for app identification

    Returns:
    dict: Authentication response with same structure as perform_master_login
    """

Service OAuth

Uses a master token to obtain service-specific authentication tokens for accessing Google APIs.

def perform_oauth(
    email: str,
    master_token: str,
    android_id: str,
    service: str,
    app: str,
    client_sig: str,
    device_country: str = "us",
    operator_country: str = "us",
    lang: str = "en",
    sdk_version: int = 17,
    proxy: MutableMapping[str, str] | None = None
) -> dict[str, str]:
    """
    Use a master token from master_login to perform OAuth to a specific Google service.

    Parameters:
    - email: Google account email address
    - master_token: Master token from perform_master_login or exchange_token
    - android_id: Android device identifier (16-character hex string)
    - service: Target Google service identifier (e.g., 'sj' for Google Music)
    - app: Application package name (e.g., 'com.google.android.music')
    - client_sig: Client signature hash for the target application
    - device_country: Device country code (default: "us")
    - operator_country: Operator country code (default: "us")
    - lang: Language code (default: "en")
    - sdk_version: Android SDK version number (default: 17)
    - proxy: Optional proxy configuration dictionary

    Returns:
    dict: Service authentication response containing:
        - 'Auth': Service-specific authentication token
        - 'SID': Session ID
        - 'LSID': Long-term session ID
        - Other service-specific metadata
    """

Cryptographic Utilities

Low-level cryptographic functions for signature construction and key handling.

def construct_signature(email: str, password: str, key: RsaKey) -> bytes:
    """
    Construct encrypted password signature for authentication.

    Parameters:
    - email: Account email address
    - password: Account password
    - key: RSA public key for encryption

    Returns:
    bytes: Base64-encoded encrypted signature
    """

def key_from_b64(b64_key: bytes) -> RsaKey:
    """
    Extract RSA key from base64-encoded key data.

    Parameters:
    - b64_key: Base64-encoded key bytes

    Returns:
    RsaKey: Parsed RSA key object
    """

def key_to_struct(key: RsaKey) -> bytes:
    """
    Convert RSA key to binary struct format.

    Parameters:
    - key: RSA key object

    Returns:
    bytes: Binary key structure
    """

def parse_auth_response(text: str) -> dict[str, str]:
    """
    Parse Google authentication response text into dictionary.

    Parameters:
    - text: Raw authentication response text

    Returns:
    dict: Parsed key-value pairs from response
    """

Data Conversion Utilities

Utility functions for converting between bytes and integers in cryptographic operations.

def bytes_to_int(bytes_seq: bytes) -> int:
    """
    Convert bytes sequence to integer using big-endian encoding.

    Parameters:
    - bytes_seq: Byte sequence to convert

    Returns:
    int: Converted integer value
    """

def int_to_bytes(num: int, pad_multiple: int = 1) -> bytes:
    """
    Convert integer to bytes with optional padding.

    Parameters:
    - num: Integer to convert (must be non-negative)
    - pad_multiple: Padding multiple for byte alignment (default: 1)

    Returns:
    bytes: Big-endian byte representation

    Raises:
    ValueError: If num is negative
    """

Constants and Configuration

__version__: str
# Package version string

B64_KEY_7_3_29: bytes
# Base64-encoded Google Play Services key (version 7.3.29)

ANDROID_KEY_7_3_29: RsaKey
# Parsed RSA key from Google Play Services

AUTH_URL: str
# Google authentication endpoint URL ("https://android.clients.google.com/auth")

USER_AGENT: str  
# User agent string for HTTP requests ("GoogleAuth/1.4")

CIPHERS: list[str]
# List of allowed SSL cipher suites for Google authentication

SSL_DEFAULT_CIPHERS: str | None
# Default SSL ciphers (version-dependent, may be None)

Custom Classes

class SSLContext(ssl.SSLContext):
    """
    SSL context wrapper that prevents ALPN protocol issues.
    """
    def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None:
        """
        Override to prevent 403 Bad Authentication errors.
        ALPN headers cause Google to return authentication failures.
        """

class AuthHTTPAdapter(requests.adapters.HTTPAdapter):
    """
    HTTP adapter with custom TLS settings for Google authentication.
    """
    def init_poolmanager(self, *args: Any, **kwargs: Any) -> None:
        """
        Initialize connection pool with secure SSL settings optimized for Google.
        Uses secure defaults but disables ssl.OP_NO_TICKET to prevent 403 errors.
        """

Types

from collections.abc import MutableMapping
from typing import Any, Iterable
from Cryptodome.PublicKey.RSA import RsaKey
import ssl
import requests.adapters

# Type aliases and imports used in API signatures
RsaKey = Cryptodome.PublicKey.RSA.RsaKey  # RSA public key object from pycryptodomex
MutableMapping = collections.abc.MutableMapping  # Generic mapping type for proxy parameters

Error Handling

The library may raise various exceptions during authentication:

  • HTTP-related exceptions: From the requests library (connection errors, timeouts, etc.)
  • Authentication failures: Returned as error details in the response dictionary rather than exceptions
  • BadAuthentication errors: May require using the alternative exchange_token flow
  • ValueError: Raised by int_to_bytes for negative input values

When authentication fails, check the response dictionary for error details rather than catching exceptions. If you encounter BadAuthentication errors with perform_master_login, try the alternative flow using exchange_token with a web OAuth token obtained from the Google embedded setup page.

Dependencies

  • pycryptodomex (>= 3.0): Cryptographic operations for signature construction
  • requests (>= 2.0.0): HTTP client for authentication requests
  • urllib3 (>= 1.26.0): Connection pooling and SSL handling