or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# GPSOAuth

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: gpsoauth

7

- **Language**: Python

8

- **Installation**: `pip install gpsoauth`

9

10

## Core Imports

11

12

```python

13

import gpsoauth

14

```

15

16

For accessing specific utilities:

17

18

```python

19

from gpsoauth.google import construct_signature, key_from_b64, parse_auth_response, key_to_struct

20

from gpsoauth.util import bytes_to_int, int_to_bytes

21

```

22

23

## Basic Usage

24

25

### Master Login Flow (Primary Method)

26

27

```python

28

import gpsoauth

29

30

# Account credentials and device identifier

31

email = 'example@gmail.com'

32

password = 'my-password'

33

android_id = '0123456789abcdef'

34

35

# Step 1: Perform master login to get master token

36

master_response = gpsoauth.perform_master_login(email, password, android_id)

37

master_token = master_response['Token']

38

39

# Step 2: Use master token to get service-specific auth token

40

auth_response = gpsoauth.perform_oauth(

41

email, master_token, android_id,

42

service='sj',

43

app='com.google.android.music',

44

client_sig='38918a453d07199354f8b19af05ec6562ced5788'

45

)

46

auth_token = auth_response['Auth']

47

48

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

49

```

50

51

### Alternative Token Exchange Flow

52

53

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

54

55

```python

56

import gpsoauth

57

58

email = 'example@gmail.com'

59

android_id = '0123456789abcdef'

60

oauth_token = '...' # Obtained from https://accounts.google.com/EmbeddedSetup

61

62

# Exchange web OAuth token for master token

63

master_response = gpsoauth.exchange_token(email, oauth_token, android_id)

64

master_token = master_response['Token']

65

66

# Continue with oauth flow as above

67

auth_response = gpsoauth.perform_oauth(

68

email, master_token, android_id,

69

service='sj',

70

app='com.google.android.music',

71

client_sig='38918a453d07199354f8b19af05ec6562ced5788'

72

)

73

```

74

75

## Capabilities

76

77

### Master Authentication

78

79

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

80

81

```python { .api }

82

def perform_master_login(

83

email: str,

84

password: str,

85

android_id: str,

86

service: str = "ac2dm",

87

device_country: str = "us",

88

operator_country: str = "us",

89

lang: str = "en",

90

sdk_version: int = 17,

91

proxy: MutableMapping[str, str] | None = None,

92

client_sig: str = "38918a453d07199354f8b19af05ec6562ced5788"

93

) -> dict[str, str]:

94

"""

95

Perform a master login, which is what Android does when you first add

96

a Google account.

97

98

Parameters:

99

- email: Google account email address

100

- password: Google account password

101

- android_id: Android device identifier (16-character hex string)

102

- service: Service type for authentication (default: "ac2dm")

103

- device_country: Device country code (default: "us")

104

- operator_country: Operator country code (default: "us")

105

- lang: Language code (default: "en")

106

- sdk_version: Android SDK version number (default: 17)

107

- proxy: Optional proxy configuration dictionary

108

- client_sig: Client signature hash for app identification

109

110

Returns:

111

dict: Authentication response containing keys like:

112

- 'Auth': Master authentication token

113

- 'Token': OAuth refresh token

114

- 'Email': Account email

115

- 'SID': Session ID

116

- 'LSID': Long-term session ID

117

- Other account metadata fields

118

"""

119

```

120

121

### Token Exchange Authentication

122

123

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

124

125

```python { .api }

126

def exchange_token(

127

email: str,

128

token: str,

129

android_id: str,

130

service: str = "ac2dm",

131

device_country: str = "us",

132

operator_country: str = "us",

133

lang: str = "en",

134

sdk_version: int = 17,

135

proxy: MutableMapping[str, str] | None = None,

136

client_sig: str = "38918a453d07199354f8b19af05ec6562ced5788"

137

) -> dict[str, str]:

138

"""

139

Exchanges a web oauth_token for a master token.

140

141

Parameters:

142

- email: Google account email address

143

- token: OAuth token obtained from web authentication flow

144

- android_id: Android device identifier (16-character hex string)

145

- service: Service type for authentication (default: "ac2dm")

146

- device_country: Device country code (default: "us")

147

- operator_country: Operator country code (default: "us")

148

- lang: Language code (default: "en")

149

- sdk_version: Android SDK version number (default: 17)

150

- proxy: Optional proxy configuration dictionary

151

- client_sig: Client signature hash for app identification

152

153

Returns:

154

dict: Authentication response with same structure as perform_master_login

155

"""

156

```

157

158

### Service OAuth

159

160

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

161

162

```python { .api }

163

def perform_oauth(

164

email: str,

165

master_token: str,

166

android_id: str,

167

service: str,

168

app: str,

169

client_sig: str,

170

device_country: str = "us",

171

operator_country: str = "us",

172

lang: str = "en",

173

sdk_version: int = 17,

174

proxy: MutableMapping[str, str] | None = None

175

) -> dict[str, str]:

176

"""

177

Use a master token from master_login to perform OAuth to a specific Google service.

178

179

Parameters:

180

- email: Google account email address

181

- master_token: Master token from perform_master_login or exchange_token

182

- android_id: Android device identifier (16-character hex string)

183

- service: Target Google service identifier (e.g., 'sj' for Google Music)

184

- app: Application package name (e.g., 'com.google.android.music')

185

- client_sig: Client signature hash for the target application

186

- device_country: Device country code (default: "us")

187

- operator_country: Operator country code (default: "us")

188

- lang: Language code (default: "en")

189

- sdk_version: Android SDK version number (default: 17)

190

- proxy: Optional proxy configuration dictionary

191

192

Returns:

193

dict: Service authentication response containing:

194

- 'Auth': Service-specific authentication token

195

- 'SID': Session ID

196

- 'LSID': Long-term session ID

197

- Other service-specific metadata

198

"""

199

```

200

201

### Cryptographic Utilities

202

203

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

204

205

```python { .api }

206

def construct_signature(email: str, password: str, key: RsaKey) -> bytes:

207

"""

208

Construct encrypted password signature for authentication.

209

210

Parameters:

211

- email: Account email address

212

- password: Account password

213

- key: RSA public key for encryption

214

215

Returns:

216

bytes: Base64-encoded encrypted signature

217

"""

218

219

def key_from_b64(b64_key: bytes) -> RsaKey:

220

"""

221

Extract RSA key from base64-encoded key data.

222

223

Parameters:

224

- b64_key: Base64-encoded key bytes

225

226

Returns:

227

RsaKey: Parsed RSA key object

228

"""

229

230

def key_to_struct(key: RsaKey) -> bytes:

231

"""

232

Convert RSA key to binary struct format.

233

234

Parameters:

235

- key: RSA key object

236

237

Returns:

238

bytes: Binary key structure

239

"""

240

241

def parse_auth_response(text: str) -> dict[str, str]:

242

"""

243

Parse Google authentication response text into dictionary.

244

245

Parameters:

246

- text: Raw authentication response text

247

248

Returns:

249

dict: Parsed key-value pairs from response

250

"""

251

```

252

253

### Data Conversion Utilities

254

255

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

256

257

```python { .api }

258

def bytes_to_int(bytes_seq: bytes) -> int:

259

"""

260

Convert bytes sequence to integer using big-endian encoding.

261

262

Parameters:

263

- bytes_seq: Byte sequence to convert

264

265

Returns:

266

int: Converted integer value

267

"""

268

269

def int_to_bytes(num: int, pad_multiple: int = 1) -> bytes:

270

"""

271

Convert integer to bytes with optional padding.

272

273

Parameters:

274

- num: Integer to convert (must be non-negative)

275

- pad_multiple: Padding multiple for byte alignment (default: 1)

276

277

Returns:

278

bytes: Big-endian byte representation

279

280

Raises:

281

ValueError: If num is negative

282

"""

283

```

284

285

## Constants and Configuration

286

287

```python { .api }

288

__version__: str

289

# Package version string

290

291

B64_KEY_7_3_29: bytes

292

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

293

294

ANDROID_KEY_7_3_29: RsaKey

295

# Parsed RSA key from Google Play Services

296

297

AUTH_URL: str

298

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

299

300

USER_AGENT: str

301

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

302

303

CIPHERS: list[str]

304

# List of allowed SSL cipher suites for Google authentication

305

306

SSL_DEFAULT_CIPHERS: str | None

307

# Default SSL ciphers (version-dependent, may be None)

308

```

309

310

## Custom Classes

311

312

```python { .api }

313

class SSLContext(ssl.SSLContext):

314

"""

315

SSL context wrapper that prevents ALPN protocol issues.

316

"""

317

def set_alpn_protocols(self, alpn_protocols: Iterable[str]) -> None:

318

"""

319

Override to prevent 403 Bad Authentication errors.

320

ALPN headers cause Google to return authentication failures.

321

"""

322

323

class AuthHTTPAdapter(requests.adapters.HTTPAdapter):

324

"""

325

HTTP adapter with custom TLS settings for Google authentication.

326

"""

327

def init_poolmanager(self, *args: Any, **kwargs: Any) -> None:

328

"""

329

Initialize connection pool with secure SSL settings optimized for Google.

330

Uses secure defaults but disables ssl.OP_NO_TICKET to prevent 403 errors.

331

"""

332

```

333

334

## Types

335

336

```python { .api }

337

from collections.abc import MutableMapping

338

from typing import Any, Iterable

339

from Cryptodome.PublicKey.RSA import RsaKey

340

import ssl

341

import requests.adapters

342

343

# Type aliases and imports used in API signatures

344

RsaKey = Cryptodome.PublicKey.RSA.RsaKey # RSA public key object from pycryptodomex

345

MutableMapping = collections.abc.MutableMapping # Generic mapping type for proxy parameters

346

```

347

348

## Error Handling

349

350

The library may raise various exceptions during authentication:

351

352

- **HTTP-related exceptions**: From the `requests` library (connection errors, timeouts, etc.)

353

- **Authentication failures**: Returned as error details in the response dictionary rather than exceptions

354

- **BadAuthentication errors**: May require using the alternative `exchange_token` flow

355

- **ValueError**: Raised by `int_to_bytes` for negative input values

356

357

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.

358

359

## Dependencies

360

361

- **pycryptodomex** (>= 3.0): Cryptographic operations for signature construction

362

- **requests** (>= 2.0.0): HTTP client for authentication requests

363

- **urllib3** (>= 1.26.0): Connection pooling and SSL handling