Skip to content

Commit a5f545f

Browse files
Fix cookie login (#491)
- Support captcha on twofactor path - Fix sid verification - Fix OAuth response parsing
1 parent fca2689 commit a5f545f

File tree

1 file changed

+71
-6
lines changed

1 file changed

+71
-6
lines changed

vk_api/vk_api.py

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
RE_NUMBER_HASH = re.compile(r"al_page: '3', hash: '([a-z0-9]+)'")
3535
RE_AUTH_HASH = re.compile(r"Authcheck\.init\('([a-z_0-9]+)'")
3636
RE_TOKEN_URL = re.compile(r'location\.href = "(.*?)"\+addr;')
37+
RE_AUTH_TOKEN_URL = re.compile(r'window\.init = ({.*?});')
3738

3839
RE_PHONE_PREFIX = re.compile(r'label ta_r">\+(.*?)<')
3940
RE_PHONE_POSTFIX = re.compile(r'phone_postfix">.*?(\d+).*?<')
@@ -342,7 +343,7 @@ def _vk_login(self, captcha_sid=None, captcha_key=None):
342343
if 'act=blocked' in response.url:
343344
raise AccountBlocked('Account is blocked')
344345

345-
def _pass_twofactor(self, auth_response):
346+
def _pass_twofactor(self, auth_response, captcha_sid=None, captcha_key=None):
346347
""" Двухфакторная аутентификация
347348
348349
:param auth_response: страница с приглашением к аутентификации
@@ -361,6 +362,15 @@ def _pass_twofactor(self, auth_response):
361362
'hash': auth_hash,
362363
'remember': int(remember_device),
363364
}
365+
if captcha_sid and captcha_key:
366+
self.logger.info(
367+
'Using captcha code: {}: {}'.format(
368+
captcha_sid,
369+
captcha_key
370+
)
371+
)
372+
values['captcha_sid'] = captcha_sid
373+
values['captcha_key'] = captcha_key
364374

365375
response = self.http.post(
366376
'https://vk.com/al_login.php?act=a_authcheck_code',
@@ -377,6 +387,14 @@ def _pass_twofactor(self, auth_response):
377387
return self._pass_twofactor(auth_response)
378388

379389
elif status == '2':
390+
if data['payload'][1][1] != 2:
391+
# Regular captcha
392+
self.logger.info('Captcha code is required')
393+
394+
captcha_sid = data['payload'][1][0][1:-1]
395+
captcha = Captcha(self, captcha_sid, self._pass_twofactor, (auth_response,))
396+
397+
return self.error_handlers[CAPTCHA_ERROR_CODE](captcha)
380398
raise TwoFactorError('Recaptcha required')
381399

382400
raise TwoFactorError(get_unknown_exc_str('2FA; unknown status'))
@@ -435,13 +453,15 @@ def check_sid(self):
435453
self.logger.info('No remixsid')
436454
return
437455

438-
response = self.http.get('https://vk.com/feed2.php').json()
456+
feed_url = 'https://vk.com/feed.php'
457+
response = self.http.get(feed_url)
439458

440-
if response['user']['id'] != -1:
441-
self.logger.info('remixsid is valid')
442-
return response
459+
if response.url != feed_url:
460+
self.logger.info('remixsid is not valid')
461+
return False
443462

444-
self.logger.info('remixsid is not valid')
463+
self.logger.info('remixsid is valid')
464+
return True
445465

446466
def _api_login(self):
447467
""" Получение токена через Desktop приложение """
@@ -469,6 +489,51 @@ def _api_login(self):
469489

470490
if url:
471491
response = self.http.get(url)
492+
elif 'redirect_uri' in response.url:
493+
response = self.http.get(response.url)
494+
auth_json = json.loads(search_re(RE_AUTH_TOKEN_URL, response.text))
495+
return_auth_hash = auth_json['data']['hash']['return_auth']
496+
response = self.http.post(
497+
'https://login.vk.com/?act=connect_internal',
498+
{
499+
'uuid': '',
500+
'service_group': '',
501+
'return_auth_hash': return_auth_hash,
502+
'version': 1,
503+
'app_id': self.app_id,
504+
},
505+
headers={'Origin': 'https://id.vk.com'}
506+
)
507+
connect_data = response.json()
508+
if connect_data['type'] != 'okay':
509+
raise AuthError('Unknown API auth error')
510+
auth_token = connect_data['data']['access_token']
511+
response = self.http.post(
512+
'https://api.vk.com/method/auth.getOauthToken',
513+
{
514+
'hash': return_auth_hash,
515+
'app_id': self.app_id,
516+
'client_id': self.app_id,
517+
'scope': self.scope,
518+
'access_token': auth_token,
519+
'is_seamless_auth': 1,
520+
'v': '5.207'
521+
}
522+
)
523+
524+
self.token = response.json()['response']
525+
526+
self.storage.setdefault(
527+
'token', {}
528+
).setdefault(
529+
'app' + str(self.app_id), {}
530+
)['scope_' + str(self.scope)] = self.token
531+
532+
self.storage.save()
533+
534+
self.logger.info('Got access_token')
535+
return
536+
472537

473538
if 'access_token' in response.url:
474539
parsed_url = urllib.parse.urlparse(response.url)

0 commit comments

Comments
 (0)