def __init__(self, account, scope, verify=True, verify_fingerprint=None, auth_cert=None, access_token=None, collection=None): from oauthlib.oauth2 import MobileApplicationClient from requests_oauthlib import OAuth2Session self.user, self.host = account.split('@') self._settings = {'cert': prepare_client_cert(auth_cert)} self._settings.update(prepare_verify(verify, verify_fingerprint)) self.scope = scope + ':rw' self._session = OAuth2Session( CLIENT_ID, client=MobileApplicationClient(CLIENT_ID), scope=self.scope, redirect_uri=REDIRECT_URI, token={'access_token': access_token}, ) subpath = scope if collection: subpath = urljoin(_ensure_slash(scope), _ensure_slash(urlquote(collection))) self._discover_endpoints(subpath) if not access_token: self._get_access_token()
def connect(): global connected global kickflip_session global KICKFLIP_CLIENT_ID global KICKFLIP_CLIENT_SECRET global KICKFLIP_API_URL if not connected: endpoint = KICKFLIP_BASE_URL + '/o/token/' payload = ({ 'client_secret': KICKFLIP_CLIENT_SECRET, 'grant_type': 'client_credentials', 'client_id': KICKFLIP_CLIENT_ID, }) response = requests.post(endpoint, payload) if response.status_code != 200: raise Exception("Error: Couldn't connect to Kickflip...") token = response.json() client = MobileApplicationClient(KICKFLIP_CLIENT_ID) kickflip_session = OAuth2Session(KICKFLIP_CLIENT_ID, client=client, token=token) connected = True print "CONNECTED" return connected
def setUp(self): self.token = { 'token_type': 'Bearer', 'access_token': 'asdfoiw37850234lkjsdfsdf', 'refresh_token': 'sldvafkjw34509s8dfsdf', 'expires_in': 3600, 'expires_at': fake_time + 3600, } # use someclientid:someclientsecret to easily differentiate between client and user credentials # these are the values used in oauthlib tests self.client_id = 'someclientid' self.client_secret = 'someclientsecret' self.user_username = '******' self.user_password = '******' self.client_WebApplication = WebApplicationClient(self.client_id, code='asdf345xdf') self.client_LegacyApplication = LegacyApplicationClient(self.client_id) self.client_BackendApplication = BackendApplicationClient( self.client_id) self.client_MobileApplication = MobileApplicationClient(self.client_id) self.clients = [ self.client_WebApplication, self.client_LegacyApplication, self.client_BackendApplication, ] self.all_clients = self.clients + [ self.client_MobileApplication, ]
def __init__(self,cid,oauthPageUrl,receivePort): """ Args: cid (string): The client id from Authorization provider oauthPageUrl (string): The authorization Page url receivedPort (string): The port number to receive request """ self.result=None self.clientId = cid self.oauthPageUrl = oauthPageUrl self.port = receivePort #generate CSRF token self.token = str(uuid.uuid4()) #generate request URL self.oauth = MobileApplicationClient(self.clientId) self.url, headers, body = self.oauth.prepare_authorization_request( self.oauthPageUrl, redirect_url="http://localhost:%s" % self.port, state=self.token ) #start local web server self.wsgi_app = _RedirectWSGIApp( self.port, self.oauth, self._registToken, self._failedRequest ) self.localServer = wsgiref.simple_server.make_server("localhost", self.port, self.wsgi_app, handler_class=_WSGIRequestHandler) thread = threading.Thread(target=self._localServerThread,args=(self.localServer,)) thread.start()
def setUp(self): self.token = { "token_type": "Bearer", "access_token": "asdfoiw37850234lkjsdfsdf", "refresh_token": "sldvafkjw34509s8dfsdf", "expires_in": 3600, "expires_at": fake_time + 3600, } # use someclientid:someclientsecret to easily differentiate between client and user credentials # these are the values used in oauthlib tests self.client_id = "someclientid" self.client_secret = "someclientsecret" self.user_username = "******" self.user_password = "******" self.client_WebApplication = WebApplicationClient(self.client_id, code=CODE) self.client_LegacyApplication = LegacyApplicationClient(self.client_id) self.client_BackendApplication = BackendApplicationClient( self.client_id) self.client_MobileApplication = MobileApplicationClient(self.client_id) self.clients = [ self.client_WebApplication, self.client_LegacyApplication, self.client_BackendApplication, ] self.all_clients = self.clients + [self.client_MobileApplication]
def get_token(discard_token): """ Establishes an OAuth2 session to retrieve a token for further API requests. Saves retrieved token to a file unless a command line argument "--discard_token" is given. @return: Dictionary of authorization parameters """ print( f"{B}Authorization required!\nAllow 'Netology Project 1 by Roman Vlasenko' access " f"to your VK account\nand copy the contents of the address bar from the opened tab{END}\n" ) sleep(7) with OAuth2Session(client=MobileApplicationClient(client_id=CLIENT_ID), redirect_uri=REDIRECT_URI, scope="friends, groups") as vk: authorization_url, state = vk.authorization_url(AUTHORIZE_URL) webbrowser.open_new_tab(authorization_url) vk_response = input( f"{B}Paste the contents of the address bar here:{END}\n").rstrip() vk.token_from_fragment(vk_response) if not discard_token: with open("token.dat", "wb") as f: pickle.dump(vk.access_token, f) return {"v": 5.103, "access_token": vk.access_token}
def main(): client_id = "2288TW" code = "6b01dd23c0ff08ea7c67ad4c7b607a8f" # Full scope scope = ["activity", "heartrate", "location", "nutrition", "profile", "settings", "sleep", "social", "weight"] scope = ["heartrate"] # Initialize client client = MobileApplicationClient(client_id) fitbit = OAuth2Session(client_id, client=client, scope=scope) authorization_url = "https://www.fitbit.com/oauth2/authorize" # Grab the URL for Fitbit's authorization page. auth_url, state = fitbit.authorization_url(authorization_url) # print(auth_url, state) print("Visit this page in your browser: {}".format(auth_url)) """After authenticating, Fitbit will redirect you to the URL you specified in your application settings. It contains the access token.""" callback_url = input("Paste URL you get back here: ") # Now we extract the token from the URL to make use of it. strip_access_token = fitbit.token_from_fragment(callback_url) # print(strip_access_token) access_token = strip_access_token['access_token'] # print(access_token) # At this point, assuming nothing blew up, we can make calls to the API as normal, for example: user = json.loads( fitbit.get( 'https://api.fitbit.com/1/user/-/profile.json?2288TW=6b01dd23c0ff08ea7c67ad4c7b607a8f' ).content.decode('utf-8')) # print(user_json['user']['age']) #start_date = '2015/01/27' start_date = '2017-04-18' hr_url = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/{1}/{2}.json'.format( start_date, 'today', '1min') print(hr_url) #test_url = 'https://api.fitbit.com/1/user/-/activities/heart/date/today/1d/1sec/time/00:00/00:01.json' test_url = 'https://api.fitbit.com/1/user/-/activities/heart/date/{0}/1d/1min.json'.format( start_date) print(test_url) # works! #test_url = 'https://api.fitbit.com/1/user/-/activities/heart/date/today/1d/1sec.json' #dict_data_heart_rate = json.loads(fitbit.get(test_url).content.decode('utf-8')) json_data_heart_rate = fitbit.get(test_url).content.decode('utf-8') es = elasticsearch.Elasticsearch() es.index(index='heartrate', doc_type='fitbit_heartrate', id=start_date, body=json_data_heart_rate)
def __init__(self, client_id, redirect_uri, scope=None, **kwargs): session = OAuth2Session( client=MobileApplicationClient(client_id=client_id), redirect_uri=redirect_uri, scope=scope, **kwargs) super().__init__(session)
def get_oauth_session(self): known_state = session.get(AUTH_STATE_KEY) redirect_url = urljoin(request.url_root, self.redirect_path) if self.grant_type and self.grant_type == CLIENT_CREDENTIALS_GRANT_TYPE: client = BackendApplicationClient(client_id=self.client_id) oauth_session = OAuth2Session(client=client, token=session.get(AUTH_TOKEN_KEY)) elif self.grant_type and self.grant_type == IMPLICIT_GRANT_TYPE: client = MobileApplicationClient(self.client_id) client.response_type = self.config.get(RESPONSE_TYPE_CONFIG) oauth_session = OAuth2Session( client_id=self.client_id, state=known_state, scope=self.config.get(SCOPE_CONFIG).split(), redirect_uri=redirect_url, client=client, token=session.get(AUTH_TOKEN_KEY)) else: client = WebApplicationClient(self.client_id) oauth_session = OAuth2Session( client_id=self.client_id, state=known_state, scope=self.config.get(SCOPE_CONFIG).split(), redirect_uri=redirect_url, client=client, token=session.get(AUTH_TOKEN_KEY)) return oauth_session
def handle_mobile(self, *args, **options): client_id = settings.FACEBOOK_APP_ID authorization_base_url = 'https://www.facebook.com/v6.0/dialog/oauth' redirect_uri = 'https://1413d4c3.ngrok.io' # Should match Site URL oauth = OAuth2Session( client=MobileApplicationClient(client_id=client_id), redirect_uri=redirect_uri) authorization_url, state = oauth.authorization_url( authorization_base_url) logger.debug(authorization_url) logger.debug(state) self.stdout.write(authorization_url) redirect_response = input('Paste the full redirect URL here:') logger.debug(oauth.token_from_fragment(redirect_response)) r = oauth.get('https://graph.facebook.com/me?') # p = r.prepared() # logger.debug(p.url) # logger.debug(p.headers) # resp = p.send() logger.debug(r.request.url) logger.debug(r.request.headers)
def __init__(self, *, name="anon", url, client_id, scope, redirect_uri=None, auth_url, auth_handler=None, **auth_args): oauth = OAuth2Session( client=MobileApplicationClient(client_id=client_id), scope=scope, redirect_uri=redirect_uri, ) super().__init__(name=name, session=oauth, url=url) auth_url, state = oauth.authorization_url(auth_url) token = None if auth_handler is None: token = oauth.token_from_fragment(auth_url) else: token = auth_handler(self, auth_url, **auth_args) self._set_oauth_token(token)
def test_parse_token_response(self): client = MobileApplicationClient(self.client_id) # Parse code and state response = client.parse_request_uri_response(self.response_uri, scope=self.scope) self.assertEqual(response, self.token) self.assertEqual(client.access_token, response.get("access_token")) self.assertEqual(client.refresh_token, response.get("refresh_token")) self.assertEqual(client.token_type, response.get("token_type")) # Mismatching scope self.assertRaises(Warning, client.parse_request_uri_response, self.response_uri, scope="invalid") os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '4' token = client.parse_request_uri_response(self.response_uri, scope='invalid') self.assertTrue(token.scope_changed) scope_changes_recorded = [] def record_scope_change(sender, message, old, new): scope_changes_recorded.append((message, old, new)) signals.scope_changed.connect(record_scope_change) try: client.parse_request_uri_response(self.response_uri, scope="invalid") self.assertEqual(len(scope_changes_recorded), 1) message, old, new = scope_changes_recorded[0] self.assertEqual(message, 'Scope has changed from "invalid" to "/profile".') self.assertEqual(old, ['invalid']) self.assertEqual(new, ['/profile']) finally: signals.scope_changed.disconnect(record_scope_change) del os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE']
def __init__(self, *args, **kwargs): self.__config = {} super(OpenshiftHttp, self).__init__(client=MobileApplicationClient(client_id='openshift-challenging-client'), *args, **kwargs) self.headers.update({'Accept': 'application/json', 'Content-Type': 'application/json', 'User-Agent': 'David Alexander: "Too lazy... Just script it..."'})
def login(): """ Based off of: https://flask-login.readthedocs.io/en/latest/#login-example If using LDAP, see ldap_login(). If using SAML/OAuth, check for the presence of an access token in the session, which is used to fetch user information for processing. If no token exists, send the user to the authorization url (first leg of the OAuth 2 workflow). * NOTE * Since we are using OAuth Mobile Application Flow to fetch the information normally retrieved in a SAML Assertion, the url resulting from authorization is in the format 'redirect_uri#access_token=123guid=ABC...'. Notice the fragment identifier ('#') in place of what would normally be the '?' separator. Since Flask drops everything after the identifier, we must extract these values client-side in order to forward them to the server. Therefore, the redirect uri we are using is our home page (main.index, along with the 'next' url if present) which contains a script that detects the presence of an access token and redirects to the intended OAuth callback (auth.authorize). https://tools.ietf.org/html/rfc3986#section-3.5 """ next_url = request.args.get('next') if current_app.config['USE_LDAP']: return redirect(url_for('auth.ldap_login', next=next_url)) elif current_app.config['USE_OAUTH']: if session.get('token') is not None: status, user_json = fetch_user_json() if status == 200: return handle_user_data( user_json['id'], user_json['userType'], user_json['email'], user_json.get('firstName'), user_json.get('middleInitial'), user_json.get('lastName'), user_json.get('termsOfUse'), user_json.get('validated'), next_url) redirect_uri = urljoin(request.host_url, url_for('main.index', next=next_url)) oauth = OAuth2Session( client=MobileApplicationClient(client_id=current_app.config['NYC_ID_USERNAME']), redirect_uri=redirect_uri ) auth_url, _ = oauth.authorization_url( urljoin(current_app.config['WEB_SERVICES_URL'], AUTH_ENDPOINT) ) return redirect(auth_url) return abort(404)
def test_populate_attributes(self): client = MobileApplicationClient(self.client_id) response_uri = (self.response_uri + "&code=EVIL-CODE") client.parse_request_uri_response(response_uri, scope=self.scope) # We must not accidentally pick up any further security # credentials at this point. self.assertIsNone(client.code)
def setCustomKey(self): """ scopes possible values: read_inbox - access a user's global inbox no_expiry - access_token's with this scope do not expire write_access - perform write operations as a user private_info - access full history of a user's private actions on the site """ client_id = 20013 scopes = "read_inbox" authorization_url = "https://stackoverflow.com/oauth/dialog" redirect_uri = "https://stackexchange.com/oauth/login_success" # Create an OAuth session and open the auth_url in a browser # for the user to authenticate stackApps = OAuth2Session( client=MobileApplicationClient(client_id=client_id), scope=scopes, redirect_uri=redirect_uri, ) auth_url, state = stackApps.authorization_url(authorization_url) driver = get_browser_driver() # Open auth_url in one of the supported browsers driver.get(auth_url) # Close the window after 20s # (Assuming that the user logs in within 30 seconds) time.sleep(30) # Close the windows as soon as authorization is done try: WebDriverWait(driver, 1).until( EC.presence_of_element_located((By.TAG_NAME, "h2"))) callback_url = driver.current_url finally: driver.quit() # Extract access token data from callback_url accessTokenData = stackApps.token_from_fragment(callback_url) # Store the access token data in a dictionary jsonDict = { "access_token": accessTokenData["access_token"], "expires": accessTokenData["expires"], "state": state, } with open("access_token.json", "w") as jsonFile: json.dump(jsonDict, jsonFile)
def setUp(self): self.token = { "token_type": "Bearer", "access_token": "asdfoiw37850234lkjsdfsdf", "expires_in": "3600", } self.client_id = "foo" self.clients = [ WebApplicationClient(self.client_id), MobileApplicationClient(self.client_id), LegacyApplicationClient(self.client_id), BackendApplicationClient(self.client_id), ]
def setUp(self): self.token = { 'token_type': 'Bearer', 'access_token': 'asdfoiw37850234lkjsdfsdf', 'expires_in': '3600' } self.client_id = 'foo' self.clients = [ WebApplicationClient(self.client_id), MobileApplicationClient(self.client_id), LegacyApplicationClient(self.client_id), BackendApplicationClient(self.client_id), ]
def auth_smashrun( config ): """ Authenticate client with Smashrun """ if config.get('smashrun', 'type') == 'code': client = Smashrun(client_id=config.get('smashrun', 'client_id'), client_secret=config.get('smashrun', 'client_secret')) client.refresh_token(refresh_token=config.get('smashrun', 'refresh_token')) else: mobile = MobileApplicationClient('client') # implicit flow client = Smashrun(client_id='client', client=mobile, token={'access_token':config.get('smashrun', 'token'),'token_type':'Bearer'}) return client
def get_token(): client = MobileApplicationClient(client_id) api = OAuth2Session(client=client, redirect_uri=redirect_uri) authorization_url, state = api.authorization_url(authorization_base_url) print 'Please go here and authorize,', authorization_url redirect_response = raw_input('Paste the full redirect URL here:') token = api.token_from_fragment(redirect_response) with open(token_file, 'w') as f: f.write(json.dumps(token, indent=2)) return api
def setup_smashrun( options, config ): """ Setup Smashrun API implicit user level authentication """ mobile = MobileApplicationClient('client') # implicit flow client = Smashrun(client_id='client',client=mobile,client_secret='my_secret',redirect_uri='https://httpbin.org/get') auth_url = client.get_auth_url() print("Go to '%s' and log into Smashrun. After redirection, copy the access_token from the url." % auth_url[0]) print("Example url: https://httpbin.org/get#access_token=____01234-abcdefghijklmnopABCDEFGHIJLMNOP01234567890&token_type=[...]") print("Example access_token: ____01234-abcdefghijklmnopABCDEFGHIJLMNOP01234567890") token = input("Please enter your access token: " ) if not config.has_section('smashrun'): config.add_section('smashrun') config.set('smashrun', 'token', urllib.parse.unquote(token)) config.set('smashrun', 'type', 'implicit')
def authorize(client_id, client_secret=None): """ :param client_id: :param client_secret: :return: """ # The HTTP request handler stores the credentials in a module-global # variable, make sure it is clean. global credentials credentials = None # Create a temporary class that extends the handler class above. This will add the # client-ID and client secret as static members to OAuth2CallbackHandler. server = HTTPServer(('localhost', 0), MakeHandlerClass(client_id, client_secret)) port = server.socket.getsockname()[1] client = MobileApplicationClient( client_id=client_id) # client_secret=client_secret) podio = OAuth2Session(client=client, scope=['global:all'], redirect_uri='http://localhost:%d/' % port) # Try the client-side flow authorization_url, state = podio.authorization_url(AUTHORIZATION_BASE_URL) click.echo('Opening authorization flow in the ') click.launch(authorization_url) try: # Getting a valid POST request from the logged in user will set KEEP_RUNNING to False # which will stop this while-loop. while keep_running(): server.handle_request() except KeyboardInterrupt: server.server_close() raise CouldNotAcquireToken() server.server_close() # Check the credentials if credentials is None: raise CouldNotAcquireToken() # Transform the credentials a little bit. token = { 'client_id': client_id, 'access_token': credentials['access_token'][0], 'refresh_token': credentials['refresh_token'][0], 'token_type': credentials['token_type'][0], 'expires_in': credentials['expires_in'][0], } return token
def auth(self) -> None: if self.session is not None: return client = MobileApplicationClient(client_id="22DGXL") self.session = OAuth2Session(client=client, scope=["sleep"]) try: self.session.token = json.load(open("../secrets/fitbit-token")) except IOError: auth_base = "https://www.fitbit.com/oauth2/authorize" expiry = "31536000" auth_url = self.session.authorization_url(auth_base, expires_in=expiry)[0] print(f"Visit this page in your browser: \n{auth_url}") callback_url = input("Paste URL you get back here: ") self.session.token_from_fragment(callback_url) json.dump(self.session.token, open("../secrets/fitbit-token", "w"))
def test_parse_token_response(self): client = MobileApplicationClient(self.client_id) # Parse code and state response = client.parse_request_uri_response(self.response_uri, scope=self.scope) self.assertEqual(response, self.token) self.assertEqual(client.access_token, response.get("access_token")) self.assertEqual(client.refresh_token, response.get("refresh_token")) self.assertEqual(client.token_type, response.get("token_type")) # Mismatching scope self.assertRaises(Warning, client.parse_request_uri_response, self.response_uri, scope="invalid")
def test_authorization_url(self): url = 'https://example.com/authorize?foo=bar' web = WebApplicationClient(self.client_id) s = OAuth2Session(client=web) auth_url, state = s.authorization_url(url) self.assertIn(state, auth_url) self.assertIn(self.client_id, auth_url) self.assertIn('response_type=code', auth_url) mobile = MobileApplicationClient(self.client_id) s = OAuth2Session(client=mobile) auth_url, state = s.authorization_url(url) self.assertIn(state, auth_url) self.assertIn(self.client_id, auth_url) self.assertIn('response_type=token', auth_url)
def session(): session = requests.session() oauth = OAuth2Session( client=MobileApplicationClient(client_id=OAUTH_CLIENT_ID), scope=OAUTH_SCOPES) authorization_url, state = oauth.authorization_url(LOGIN_URL + "/oauth/authorize") result = session.get(authorization_url) page = html.fromstring(result.text) csrf_token = _get_input_value(page, 'csrf_token') next = list(set(page.xpath("//input[@name='next_redirect']/@value")))[0] payload = { 'username': USERNAME, 'password': PASSWORD, 'next_redirect': next, 'csrf_token': csrf_token } result = session.post(LOGIN_URL, data=payload, headers={'referer': result.url}) assert result.status_code == 200 page = html.fromstring(result.text) authorize_xpath = page.xpath("//form[@id='authorizeForm']") if authorize_xpath: csrf_token = _get_input_value(page, 'csrf_token') payload = {'csrf_token': csrf_token, 'confirm': 'y'} result = session.post(result.url, data=payload, headers={'Referer': result.url}) token = _get_token_from_url(result.url) session.headers.update({'Authorization': 'Bearer {}'.format(token)}) assert result.status_code == 200 session.headers.update({'Accept': 'application/ld+json'}) return session
def setUp(self): # For python 2.6 if not hasattr(self, 'assertIn'): self.assertIn = lambda a, b: self.assertTrue(a in b) self.token = { 'token_type': 'Bearer', 'access_token': 'asdfoiw37850234lkjsdfsdf', 'refresh_token': 'sldvafkjw34509s8dfsdf', 'expires_in': '3600', 'expires_at': fake_time + 3600, } self.client_id = 'foo' self.clients = [ WebApplicationClient(self.client_id, code='asdf345xdf'), LegacyApplicationClient(self.client_id), BackendApplicationClient(self.client_id), ] self.all_clients = self.clients + [MobileApplicationClient(self.client_id)]
def do_implicit(self): """ Implicit grant """ self.oauth_client = MobileApplicationClient(self.client_id) (token_url, headers, body) = self.oauth_client.prepare_authorization_request( self.oauth_endpoints['authorization_endpoint'], redirect_url=self.redirect_url, scope=self.scopes, ) # For openid scope, have to add id_token response_type and supply a nonce: # https://www.pingidentity.com/content/developer/en/resources/openid-connect-developers-guide/implicit-client # -profile.html # "Note: To mitigate replay attacks, a nonce value must be included to associate a client session with an # id_token. The client must generate a random value associated with the current session and pass this # along with the request. This nonce value will be returned with the id_token and must be verified to be # the same as the value provided in the initial request." # # oauthlib `lacks client features<https://github.com/oauthlib/oauthlib/issues/615>`_ for OIDC. if 'openid' in self.scopes: self.nonce = uuid.uuid4().hex # TODO: fix this to something more robust or extend oauthlib token_url = token_url.replace( 'response_type=token', 'response_type=token+id_token&nonce={}'.format(self.nonce)) # for the implicit grant type, the parameters are provided to the browser as #fragments rather than # ?query-parameters so they are never available to the redirect server. The user must copy the # browser self._redirect_server( self.redirect_url, token_url, message= "Copy this URL to the clipboard and hit enter on the console. " "Then you can close this window.") input("\n\nCopy URL to clipboard and then hit enter:") token_response_url = pyperclip.paste() self.oauth_tokens = self.oauth_client.parse_request_uri_response( token_response_url) self.set_tokens()
def test_implicit_token_uri(self): client = MobileApplicationClient(self.client_id) # Basic, no extra arguments uri = client.prepare_request_uri(self.uri) self.assertURLEqual(uri, self.uri_id) # With redirection uri uri = client.prepare_request_uri(self.uri, redirect_uri=self.redirect_uri) self.assertURLEqual(uri, self.uri_redirect) # With scope uri = client.prepare_request_uri(self.uri, scope=self.scope) self.assertURLEqual(uri, self.uri_scope) # With state uri = client.prepare_request_uri(self.uri, state=self.state) self.assertURLEqual(uri, self.uri_state) # With extra parameters through kwargs uri = client.prepare_request_uri(self.uri, **self.kwargs) self.assertURLEqual(uri, self.uri_kwargs)
def authorize(): """ Establishes an OAuth2 session to get a token for further API requests :return: Dictionary of authorization parameters (token and version) """ print( "Для работы программы необходимо авторизоваться!\nВ открывшейся вкладке браузера " "разрешите приложению Netology Lesson 3.3 by Roman Vlasenko доступ к вашему\n" "аккаунту ВКонтакте и скопируйте содержимое адресной строки\n") sleep(8) with OAuth2Session(client=MobileApplicationClient(client_id=CLIENT_ID), redirect_uri=REDIRECT_URI, scope="friends") as vk: authorization_url, state = vk.authorization_url(AUTHORIZE_URL, display="page") webbrowser.open_new_tab(authorization_url) vk_response = input( "Вставьте сюда содержимое адресной строки браузера:\n").rstrip() vk.token_from_fragment(vk_response) params = {"v": 5.103, "access_token": vk.access_token} # блок ниже делает тестовый запрос и проверяет, # чтобы API возвращал валидные данные, иначе # вероятнее всего, авторизация не удалась authtest = requests.get(API_URL + "/users.get", params).json() try: assert "response" in authtest print(f"\nДобро пожаловать, {authtest['response'][0]['first_name']}") return params, True except AssertionError: print( f"Тестовый запрос вернул ошибку: {authtest['error']['error_msg']}\n" "Повторная попытка авторизации через 5 с") sleep(5) return main()