Пример #1
0
def zoom_auth():
    '''Do the Zoom OAuth 2.0 dance.
    
    Zoom requires that the authz and oauth callback handlers have the
    same redirect uri.'''
    code = flask.request.args.get('code', None)
    if not code:
        oauth = requests_oauthlib.OAuth2Session(ZOOM_CLIENT_ID,
                                                redirect_uri=flask.url_for(
                                                    'zoom_auth',
                                                    _external=True))
        authorization_url, state = oauth.authorization_url(
            ZOOM_AUTHORIZATION_URL)
        flask.session['zoom_state'] = state
        flask.session.modified = True
        app.logger.info(f'zoom authz url {authorization_url}')
        app.logger.info(f'zoom_state {state}')
        return flask.redirect(authorization_url)

    else:
        app.logger.info(f'zoom auth code: mark 0')
        oauth = requests_oauthlib.OAuth2Session(
            ZOOM_CLIENT_ID,
            state=flask.session['zoom_state'],
            redirect_uri=flask.url_for('zoom_auth', _external=True))
        app.logger.info(f'zoom auth code: mark 10')
        token = oauth.fetch_token(ZOOM_TOKEN_URL,
                                  client_secret=ZOOM_CLIENT_SECRET,
                                  authorization_response=flask.request.url)
        app.logger.info(f'zoom_token {token}')
        flask.session['zoom_token'] = token
        flask.session.modified = True
        return flask.redirect(flask.url_for('main_view'))
Пример #2
0
def get_client():
    if token_store.get_token() is None:
        username = getpass.getuser()
        password = getpass.getpass()
        initial_oauth_client = requests_oauthlib.OAuth2Session(
            client=oauthlib.oauth2.LegacyApplicationClient(
                client_id=CLIENT_ID,
                client_secret=CLIENT_SECRET,
            ))
        token = initial_oauth_client.fetch_token(
            'https://oncat.ornl.gov/oauth/token',
            username=username,
            password=password,
            client_id=CLIENT_ID,
            client_secret=CLIENT_SECRET,
        )
        token_store.set_token(token)

    auto_refresh_client = requests_oauthlib.OAuth2Session(
        CLIENT_ID,
        token=token_store.get_token(),
        auto_refresh_url='https://oncat.ornl.gov/oauth/token',
        auto_refresh_kwargs={
            'client_id': CLIENT_ID,
        },
        token_updater=token_store.set_token)

    return auto_refresh_client
Пример #3
0
def authentication_session():
    # if the token has never been saved, assign it to None
    try:
        token = get_token_from_cache()
    except FileNotFoundError:
        token = None
    # if token was cached and hasn't expired
    if token:
        if not has_token_expired(token['timestamp']):
            oauth2inst = requests_oauthlib.OAuth2Session(CLIENT_ID,
                                                         token=token)
            return oauth2inst
    # If token either doesn't exist or has expired
    print('Getting token...')
    oauth2inst = requests_oauthlib.OAuth2Session(CLIENT_ID,
                                                 redirect_uri=REDIRECT_URI)
    authorization_url, state = oauth2inst.authorization_url(AUTHORIZATION_URL)
    webbrowser.open(authorization_url)
    authorization_response = input(
        'Authenticate and then enter the full callback URL: ').strip()
    token = oauth2inst.fetch_token(
        TOKEN_URL,
        authorization_response=authorization_response,
        client_secret=CLIENT_SECRET)
    save_token(token)
    return oauth2inst
Пример #4
0
def initialize_oauth():
    # If token already exists, then just load it
    if os.path.exists('_token.pkl'):
        token = unpickle_object('_token')
        oauth = requests_oauthlib.OAuth2Session(client_id,
                                                redirect_uri=redirect_url,
                                                scope=scope,
                                                token=token)

    else:
        # Construct a new token after OAuth2 flow
        # Initialize a OAuth2 session
        oauth = requests_oauthlib.OAuth2Session(client_id,
                                                redirect_uri=redirect_url,
                                                scope=scope)

        authorization_url, state = oauth.authorization_url(auth_url)
        print(
            f"Visit below website and paste access token below : \n\n{authorization_url}\n"
        )

        authorization_response = input(
            "Paste authorization response code here :\n")

        token = oauth.fetch_token(
            token_url,
            authorization_response=authorization_response,
            code=authorization_response,
            client_secret=api_key,
        )

        # Save the token generated
        pickle_object(token, '_token')

    return oauth, token
    def get_session(self):
        """
        Generate the authenticated OAuth2 session.

        :Returns:
            - An authenticated :class:`requests_oauthlib.OAuth2Session`

        :Raises:
            - :class:`.AuthenticationException` if the token is invalid
              or expired.
        """
        resource = _https(self.auth['resource'])  #DEP
        countdown = float(self.token['expires_at']) - time.time()

        self.token['expires_in'] = countdown
        self._log.debug("Token expires in: {0}".format(countdown))

        try:
            if 'refresh_token' in self.token:

                refresh = _https(self.auth['root'], self.auth['tenant'],
                                 self.auth['token_uri'])

                new_session = requests_oauthlib.OAuth2Session(
                    self._id,
                    token=self.token,
                    auto_refresh_url=refresh,
                    auto_refresh_kwargs={
                        'client_id': self._id,
                        'resource': resource
                    },
                    token_updater=self.store_auth)

            else:
                new_session = requests_oauthlib.OAuth2Session(self._id,
                                                              token=self.token)

        except oauth2.rfc6749.errors.TokenExpiredError as excp:
            self._log.info(
                "Token is no longer able to be refreshed, please log in.")

            raise AuthenticationException("Token expired: {0}".format(
                excp.description))

        else:
            new_session.verify = VERIFY
            if CA_CERT and VERIFY is True:
                new_session.verify = CA_CERT
            return new_session
Пример #6
0
def get_google_auth(state=None, token=None):
    """Helper function to create OAuth2Session object."""

    if token:
        return requests_oauthlib.OAuth2Session(Auth.CLIENT_ID, token=token)

    if state:
        return requests_oauthlib.OAuth2Session(Auth.CLIENT_ID,
                                               state=state,
                                               redirect_uri=Auth.REDIRECT_URI)

    oauth = requests_oauthlib.OAuth2Session(Auth.CLIENT_ID,
                                            redirect_uri=Auth.REDIRECT_URI,
                                            scope=Auth.SCOPES)
    return oauth
Пример #7
0
def callback():
    req_state = request.args.get('state', default=None, type=None)

    if req_state != session['AUTH_STATE_KEY']:
        response = make_response('Invalid state parameter', 401)
        return response

    decathlon = requests_oauthlib.OAuth2Session(
        client_id=current_app.config['DECATHLON_CLIENT_ID'],
        redirect_uri=current_app.config['DECATHLON_REDIRECT_URI'],
        scope=current_app.config['DECATHLON_SCOPE'])
    auth = HTTPBasicAuth(current_app.config['DECATHLON_CLIENT_ID'],
                         current_app.config['DECATHLON_CLIENT_SECRET'])
    authorization_response = request.url
    oauth2_token = decathlon.fetch_token(
        current_app.config['DECATHLON_ACCESS_TOKEN_URL'],
        authorization_response=authorization_response,
        auth=auth,
        scope=current_app.config['DECATHLON_SCOPE'])
    session['AUTH_TOKEN'] = oauth2_token

    # info = decathlon.token
    # return f"""
    #     {info}
    #     <a href="/">Home</a>
    #     """
    return redirect(url_for('main_bp.index'))
Пример #8
0
def init():
    log.debug("@@@ UPLOAD ROOT ROUTE")
    log.debug("FLASK HEADERS")
    log.debug(flask.request.headers)
    log.debug("FLASK SESSION")
    log.debug(flask.session)
    log.debug("FLASK REQUEST")
    log.debug(flask.request.url_root)
    # to be set by request in future
    provider = flask.request.args.get('provider', PROVIDER)
    flask.session['oauth_provider'] = provider

    oauth_session = complinify(
        requests_oauthlib.OAuth2Session(client_id[provider],
                                        scope=scope[provider],
                                        redirect_uri=redirect_uri(
                                            flask.request.url_root)))

    authorization_url, state = oauth_session.authorization_url(
        authorization_base_url[provider])
    flask.session['oauth_state'] = state

    log.debug("UPLOAD ROOT SESSION")
    log.debug(flask.session)

    return flask.jsonify({
        'message': 'Please login first',
        'location': authorization_url,
    })
Пример #9
0
    def fetch_token(self,
                    authorization_response_url,
                    redirect_uri=None,
                    scope=None):
        """
        :param authorization_response_url:  The full return url received after redirecting to
        the return value of get_auth_url().
        e.g. "https://app.local:8080/private?state=salt&code=secretAuthCode&scope=profileinfo%20friendslist"
        :param redirect_uri: string; the redirect_uri again. Reason unknown.
        :param scope: string; the scope again. Reason unknown.
        :return: dict; Authorization token (token_type, access_token, refresh_token, expires_at, scope)
        """
        redirect_uri = redirect_uri or self.default_redirect_uri
        scope = scope or self.default_scope

        oauth = requests_oauthlib.OAuth2Session(self.client_id,
                                                redirect_uri=redirect_uri,
                                                scope=scope)

        token = oauth.fetch_token(
            self.token_url,
            authorization_response=authorization_response_url,
            client_secret=self.client_secret,
            verify=True)

        self.save_token(token)
def spotify_make_request_and_cache(baseurl, params):
    unique_ident = params_unique_combination(baseurl, params)

    if unique_ident in CACHE_DICTION:
        print("Getting cached data...")
        return CACHE_DICTION[unique_ident]

    else:
        print("Making a request for new data...")
        oauth2inst = requests_oauthlib.OAuth2Session(CLIENT_ID,
                                                     redirect_uri=redirect_URI)
        auth_url, state = oauth2inst.authorization_url(authorization_url)

        webbrowser.open(auth_url)
        auth_response = input(
            'Confirm authentication and enter the full URL').strip()

        auth_token = oauth2inst.fetch_token(
            TOKEN_URL,
            authorization_response=auth_response,
            client_secret=CLIENT_SECRET)

        r = oauth2inst.get(unique_ident)

        CACHE_DICTION[unique_ident] = json.loads(r.text)
        with open(CACHE_FNAME, "w") as outfile:
            json.dump(CACHE_DICTION, outfile, indent=4)

        spotify_results = json.loads(r.text)
        JSON_FILE = "spotify_results.json"
        with open(JSON_FILE, "w") as outfile1:
            json.dump(spotify_results, outfile1, indent=4)

        return CACHE_DICTION[unique_ident]
Пример #11
0
 def _create_auth_client(self):
     initial_oauth_client = requests_oauthlib.OAuth2Session(
         client=oauthlib.oauth2.LegacyApplicationClient(
             client_id=CLIENT_ID,
             client_secret=CLIENT_SECRET,
         ))
     return initial_oauth_client
Пример #12
0
def create_session():
    client_id = os.environ.get('SH_CLIENT_ID')
    client_secret = os.environ.get('SH_CLIENT_SECRET')

    client = oauthlib.oauth2.BackendApplicationClient(client_id=client_id)
    session = requests_oauthlib.OAuth2Session(client=client)
    return session, client_id, client_secret
Пример #13
0
def gettoken(client_id=CLIENT_ID,
             client_secret=CLIENT_SECRET,
             redirect_uri=REDIRECT_URI):
    scope = ['https://www.googleapis.com/auth/calendar']
    oauth = requests_oauthlib.OAuth2Session(client_id,
                                            redirect_uri=redirect_uri,
                                            scope=scope)

    authorization_url, state = oauth.authorization_url(
        'https://accounts.google.com/o/oauth2/auth',
        # access_type and prompt are Google specific extra
        # parameters.
        access_type="offline",
        prompt="select_account")
    print('Please go to %s and authorize access.' % authorization_url)

    # Get the authorization verifier code from the callback url
    authorization_response = input('Enter the full callback URL')

    token = oauth.fetch_token(
        'https://accounts.google.com/o/oauth2/token',
        authorization_response=authorization_response,
        # Google specific extra parameter used for client
        # authentication
        client_secret=client_secret)
    #saves token to disk
    tokensaver(token)
Пример #14
0
def _get_oauth_session():
    return requests_oauthlib.OAuth2Session(
        settings_loader.settings["OAUTH_APP_ID"],
        state=_pop_state(),
        token=get_token(),
        scope="User.Read Files.Read",
        redirect_uri=settings_loader.settings["OAUTH_CALLBACK"])
Пример #15
0
def login():
    simplelogin = requests_oauthlib.OAuth2Session(
        CLIENT_ID, redirect_uri="http://localhost:5000/callback"
    )
    authorization_url, _ = simplelogin.authorization_url(AUTHORIZATION_BASE_URL)

    return flask.redirect(authorization_url)
Пример #16
0
    def _get_oauth_token(self,
                         client_id=None,
                         client_secret=None,
                         oauth_url=None):
        """
        Get a (new) auth token

        :param client_id: client id passed to OAuth
        :param client_secret: client secret passed to OAuth
        :param oauth_url: url of OAuth server
        :return: access token

        TODO: handle refresh to avoid getting new token each time.
        """
        try:
            client = oauthlib.oauth2.BackendApplicationClient(
                client_id=client_id)
            oauth = requests_oauthlib.OAuth2Session(client=client)
            token = oauth.fetch_token(token_url=oauth_url or self._auth_url,
                                      client_id=client_id or self._client_id,
                                      client_secret=client_secret
                                      or self._client_secret,
                                      verify=False)
            access_token = token['access_token']
        except Exception:
            self.logger.error("Failed retrieving access token from url %s",
                              oauth_url)
            raise
        return access_token
Пример #17
0
def fb_login():
    facebook = r_oauth.OAuth2Session(FB_APP_CLIENTID,
                                     scope=['email'],
                                     redirect_uri=URL + "callback/")
    authorize_url, _ = facebook.authorization_url(FB_AUTHORIZATION_BASE_URL)
    print(authorize_url, _)
    return redirect(authorize_url)
Пример #18
0
        def wrapper(request, *args, user=None, **kwargs):
            """Redirect user."""
            if oauth_condition(request) is False:
                return view_function(request, *args, user=user, **kwargs)

            consumer_key = request.params["oauth_consumer_key"]

            application_instance = find_by_oauth_consumer_key(request.db, consumer_key)

            client_id = application_instance.developer_key

            if application_instance is None:
                raise exc.HTTPInternalServerError()

            authorization_base_url = build_auth_base_url(
                application_instance.lms_url, authorization_base_endpoint
            )

            redirect_uri = build_redirect_uri(request.url, redirect_endpoint)

            oauth_session = requests_oauthlib.OAuth2Session(
                client_id, redirect_uri=redirect_uri
            )
            authorization_url, state_guid = oauth_session.authorization_url(
                authorization_base_url
            )

            oauth_state = find_or_create_from_user(
                request.db, state_guid, user, request.params
            )
            if oauth_state is None:
                raise exc.HTTPInternalServerError()
            return exc.HTTPFound(location=authorization_url)
Пример #19
0
def get_session(company):

    name, token_string = frappe.db.sql(
        """
				select name, oauth_token from `tabHMRC Authorisations` a
				where 
					a.company = %s and
					a.authorisation_status = "Authorised"
				""", company)[0]
    token = json.loads(token_string)

    client_id = frappe.db.get_single_value("HMRC API Settings", "client_id")
    client_secret = frappe.db.get_single_value("HMRC API Settings",
                                               "client_secret")
    api_base = frappe.db.get_single_value("HMRC API Settings", "api_base")
    auth_base = frappe.db.get_single_value("HMRC API Settings", "auth_base")
    extra = {
        'client_id': client_id,
        'client_secret': client_secret,
    }

    def token_updater(token):
        frappe.db.set_value("HMRC Authorisations", name, "oauth_token",
                            json.dumps(token))
        frappe.db.commit()

    return ro.OAuth2Session(client_id,
                            token=token,
                            auto_refresh_kwargs=extra,
                            auto_refresh_url=api_base + '/oauth/token',
                            token_updater=token_updater)
Пример #20
0
    def callback(self, request_url):
        if self.is_auth or self.state is None:
            return None

        try:
            oauth = requests_oauthlib.OAuth2Session(github_oauth_client_id,
                                                    state=self.state)
            self.state = None  # single use, forget now

            oauth.fetch_token(
                "https://github.com/login/oauth/access_token",
                client_secret=github_oauth_client_secret,
                authorization_response=request_url,
            )
            if oauth.authorized:
                info = oauth.get("https://api.github.com/user").json()

                self.name = info[
                    "login"]  # can be changed, and reassigned to someone else
                self.userid = int(info["id"])  # persistent

                # All necessary data is available, now the user is considered authorized
                self.is_auth = True
                self.teams = request_teams(self.name)

                return self.redirect
        except AccessDeniedError:
            # The user denied access to our application; that is fine, just
            # don't log the user in and show him an error (which is exactly
            # what happens if we do absolutely nothing)
            pass
        except Exception:
            log.exception("Failed to get user information")

        return None
Пример #21
0
    def callback(self, request_url):
        if self.is_auth or self.state is None:
            return None

        try:
            oauth = requests_oauthlib.OAuth2Session(github_oauth_client_id, state=self.state)
            self.state = None  # single use, forget now

            oauth.fetch_token(
                "https://github.com/login/oauth/access_token",
                client_secret=github_oauth_client_secret,
                authorization_response=request_url,
            )
            if oauth.authorized:
                info = oauth.get("https://api.github.com/user").json()

                self.name = info["login"]  # can be changed, and reassigned to someone else
                self.userid = int(info["id"])  # persistent

                # All necessary data is available, now the user is considered authorized
                self.is_auth = True
                self.teams = request_teams(self.name)

                return self.redirect

        except Exception:
            log.exception("Failed to get user information")

        return None
Пример #22
0
def callback():
    URL = request.url_root.strip("/")
    print(URL)
    facebook = requests_oauthlib.OAuth2Session(FB_CLIENT_ID,
                                               scope=FB_SCOPE,
                                               redirect_uri=URL +
                                               "/fb-callback")

    facebook = facebook_compliance_fix(facebook)

    facebook.fetch_token(
        FB_TOKEN_URL,
        client_secret=FB_CLIENT_SECRET,
        authorization_response=flask.request.url,
    )

    facebook_user_data = facebook.get(
        "https://graph.facebook.com/me?fields=id,name,email,picture{url}"
    ).json()

    email = facebook_user_data["email"]
    name = facebook_user_data["name"]
    picture_url = facebook_user_data.get("picture", {}).get("data",
                                                            {}).get("url")
    result = get_products()
    session["USERNAME"] = email
    return render_template('index.html', data=result, user_data=email)
Пример #23
0
    def signed_session(self):
        """Create requests session with any required auth headers
        applied.

        :rtype: requests.Session.
        """
        return oauth.OAuth2Session(self.id, token=self.token)
Пример #24
0
 def test_oauth2_web_authentication(self):
     oauth = requests_oauthlib.OAuth2Session(self.oauth2_web_client_key,
                                             redirect_uri=self.callback_url)
     authorization_url, state = oauth.authorization_url(
         self.oauth2_authorization_url)
     self.assertTrue(authorization_url and state)
     self.assertTrue(self.url_open(authorization_url))
     data = {
         'client_id': self.oauth2_web_client_key,
         'login': self.login,
         'password': self.password,
         'response_type': 'code',
         'state': state,
         'redirect_uri': self.callback_url,
         'scopes': ['dummy']
     }
     authorization_url = self.url_prepare(self.oauth2_authorization_url)
     response = self.opener.post(authorization_url,
                                 data=data,
                                 timeout=10,
                                 allow_redirects=False)
     token = oauth.fetch_token(
         self.oauth2_access_token_url,
         authorization_response=response.headers['Location'])
     self.assertTrue(token)
     self.assertTrue(oauth.get(self.test_authentication_url))
Пример #25
0
    def dispatch(self, request, path_info, token):
        api_url = urljoin(self.api_url, path_info) + '?' + request.META.get(
            'QUERY_STRING', '')
        headers = {}
        for k, v in request.META.items():
            if not k.startswith('HTTP_'):
                continue
            k = k[5:].lower().replace('_', '-')
            if k not in self.discard_request_headers:
                headers[k] = v

        usa = UserSocialAuth.objects.get(user=token.user,
                                         provider=self.provider)
        token = usa.extra_data

        session = requests_oauthlib.OAuth2Session(client_id=self.client_id,
                                                  token=token)

        upstream_response = session.request(request.method,
                                            api_url,
                                            headers=headers)
        response = HttpResponse(upstream_response.content,
                                status=upstream_response.status_code)
        for k, v in upstream_response.headers.items():
            if k.lower() not in self.discard_response_headers:
                response[k] = v
        return response
Пример #26
0
 def test_oauth2_mobile_authentication(self):
     client = oauthlib.oauth2.MobileApplicationClient(
         client_id=self.oauth2_mobile_client_key)
     oauth = requests_oauthlib.OAuth2Session(client=client)
     authorization_url, state = oauth.authorization_url(
         self.oauth2_authorization_url)
     self.assertTrue(authorization_url and state)
     self.assertTrue(self.url_open(authorization_url))
     data = {
         'client_id': self.oauth2_mobile_client_key,
         'login': self.login,
         'password': self.password,
         'response_type': 'token',
         'state': state,
         'redirect_uri': self.callback_url,
         'scopes': ['dummy']
     }
     authorization_url = self.url_prepare(self.oauth2_authorization_url)
     response = self.opener.post(authorization_url,
                                 data=data,
                                 timeout=10,
                                 allow_redirects=False)
     token = oauth.token_from_fragment(response.headers['Location'])
     self.assertTrue(token)
     self.assertTrue(oauth.get(self.test_authentication_url))
Пример #27
0
def authenticate(fname_api='twitter_api.yml'):
    """Generate a requests.Session object authorized via OAuth-2.

    Twitter API urls:
     - url_api = 'https://api.twitter.com'
     - url_request_oauth1_token = url_api + '/oauth/request_token'
     - url_request_oauth2_token = url_api + '/oauth2/token'
     - url_authorize = url_api + '/oauth/authorize'
     - url_access_token = url_api + '/oauth/access_token'
    """
    # Load application's Twitter API details.
    info_twitter = yaml_io.read(fname_api)

    client_key = info_twitter['consumer_key']
    # client_secret = info_twitter['consumer_secret']
    access_token = info_twitter['access_token']

    # Backend client / desktop client application workflow.
    client = oauthlib.oauth2.BackendApplicationClient(client_key)
    token = {'access_token': access_token, 'token_type': 'Bearer'}

    # Generate requests.Session object.
    session = requests_oauthlib.OAuth2Session(client, token=token)

    return session
Пример #28
0
    def respond(self, user, server, auth_response):
        user_obj = get_user(user, server.server_name)

        oauth = requests_oauthlib.OAuth2Session(server.config["google_id"],
                                                redirect_uri=self.redirect_uri,
                                                scope=self.scope)
        #        try:
        token = oauth.fetch_token('https://accounts.google.com/o/oauth2/token',
                                  code=auth_response,
                                  client_secret=server.config["google_secret"])
        r = oauth.get('https://www.googleapis.com/oauth2/v1/userinfo')
        info = json.loads(r.content)

        try:
            backend = AuthBackend.get(
                AuthBackend.identifier == info["id"],
                AuthBackend.auth_service == "GoogleOAuth")
            merge_accounts(user_obj.acct, backend.acct)
            msg = "Successfully updated authentication information to %s"
        except AuthBackend.DoesNotExist:
            backend = AuthBackend(identifier=info["id"],
                                  auth_service="GoogleOAuth",
                                  acct=user_obj.acct)
            backend.save()

            msg = "Successfully authenticated as %s"
        user_obj.acct.name = info["name"]

        msg = msg % user_obj.acct.name

        return (True, msg)
Пример #29
0
def fb_callback():
    facebook = requests_oauthlib.OAuth2Session(FB_CLIENT_ID,
                                               scope=FB_SCOPE,
                                               redirect_uri=URL +
                                               "/fb-callback")
    print(facebook)
    # we need to apply a fix for Facebook here
    facebook = facebook_compliance_fix(facebook)

    facebook.fetch_token(
        FB_TOKEN_URL,
        client_secret=FB_CLIENT_SECRET,
        authorization_response=flask.request.url,
    )

    # Fetch a protected resource, i.e. user profile, via Graph API

    facebook_user_data = facebook.get(
        "https://graph.facebook.com/me?fields=id,name,email,picture{url}"
    ).json()

    email = facebook_user_data["email"]
    name = facebook_user_data["name"]
    picture_url = facebook_user_data.get("picture", {}).get("data",
                                                            {}).get("url")

    return f"""
Пример #30
0
 def _session(
         self,
         token: OfflineToken = None) -> requests_oauthlib.OAuth2Session:
     return requests_oauthlib.OAuth2Session(client_id=self.client_id,
                                            scope=self.scope,
                                            redirect_uri=self.redirect_url,
                                            token=token)