Exemplo n.º 1
0
def login():
    handshaker = Handshaker("https://meta.wikimedia.org/w/index.php",
                            oauth_token)
    redirect_url, request_token = handshaker.initiate()
    session['request_token'] = request_token
    session['return_to_url'] = request.args.get('next', '/')
    return redirect(redirect_url)
Exemplo n.º 2
0
    def get(self):
        consumer_token = ConsumerToken(
            self.authenticator.client_id,
            self.authenticator.client_secret
        )

        handshaker = Handshaker(
            self.authenticator.mw_index_url, consumer_token
        )
        request_token = dejsonify(self.get_secure_cookie(AUTH_REQUEST_COOKIE_NAME))
        self.clear_cookie(AUTH_REQUEST_COOKIE_NAME)
        access_token = yield self.executor.submit(
            handshaker.complete, request_token, self.request.query
        )

        identity = handshaker.identify(access_token)
        if identity and 'username' in identity:
            # FIXME: Figure out total set of chars that can be present
            # in MW's usernames, and set of chars valid in jupyterhub
            # usernames, and do a proper mapping
            username = identity['username'].replace(' ', '_')
            user = self.find_user(username)
            if user is None:
                user = orm.User(name=username, id=identity['sub'])
                self.db.add(user)
                self.db.commit()
            self.set_login_cookie(user)
            self.redirect(url_path_join(self.hub.server.base_url, 'home'))
        else:
            # todo: custom error page?
            raise web.HTTPError(403)
Exemplo n.º 3
0
def authcallback():
    # Step 3: Complete -- obtain authorized key/secret for "resource owner"
    rediskey = request.cookies.get('rediskey')
    oauth_verifier = request.args.get('oauth_verifier', '')
    oauth_token = request.args.get('oauth_token', '')
    request_token = r.get(rediskey)
    if request_token == None:
        resp = make_response(render_template('redirect.html'), 302)
        resp.headers['Location'] = 'auth'
        return resp
    elif oauth_verifier == '':
        resp = make_response(render_template('redirect.html'), 302)
        resp.headers['Location'] = 'auth'
        return resp
    else:
        handshaker = Handshaker("https://en.wikipedia.org/w/index.php", consumer_token)
        serialrequest_token = r.get(rediskey)
        request_token = pickle.loads(serialrequest_token)
        response_qs = 'oauth_verifier=' + oauth_verifier + '&' + 'oauth_token=' + oauth_token
        #print(request_token)
        #print(response_qs)
        access_token = handshaker.complete(request_token,response_qs)
        #print(str(access_token))
        
        # Step 4: Identify -- (optional) get identifying information about the user
        identity = handshaker.identify(access_token)
        r.delete(rediskey)
        #return "Identified as {username}.".format(**identity)
        username = "******".format(**identity)
        resp = make_response(render_template('redirect.html'), 302)
        resp.headers['Location'] = 'https://kiwiirc.com/client/irc.freenode.net/wikipedia-en-help?nick=' + username
        return resp
Exemplo n.º 4
0
def oauth_callback():
    handshaker = Handshaker(
        "https://meta.wikimedia.org/w/index.php",
        oauth_token,
        user_agent=user_agent
    )
    access_token = handshaker.complete(session['request_token'], request.query_string)
    session['access_token'] = access_token
    identity = handshaker.identify(access_token)
    wiki_uid = identity['sub']
    user = g.conn.session.query(User).filter(User.wiki_uid == wiki_uid).first()
    if user is None:
        user = User(username=identity['username'], wiki_uid=wiki_uid)
        g.conn.session.add(user)
        g.conn.session.commit()
    elif user.username != identity['username']:
        user.username = identity['username']
        g.conn.session.add(user)
        try:
            g.conn.session.commit()
        except IntegrityError as e:
            if e[0] == 1062:  # Duplicate
                g.conn.session.rollback()
            else:
                raise

    session['user_id'] = user.id
    return_to_url = session.get('return_to_url')
    del session['request_token']
    del session['return_to_url']
    return redirect(return_to_url)
Exemplo n.º 5
0
    def get(self):
        consumer_token = ConsumerToken(self.authenticator.client_id,
                                       self.authenticator.client_secret)

        handshaker = Handshaker(self.authenticator.mw_index_url,
                                consumer_token)
        request_token = dejsonify(
            self.get_secure_cookie(AUTH_REQUEST_COOKIE_NAME))
        self.clear_cookie(AUTH_REQUEST_COOKIE_NAME)
        access_token = yield self.executor.submit(handshaker.complete,
                                                  request_token,
                                                  self.request.query)

        identity = handshaker.identify(access_token)
        if identity and 'username' in identity:
            # FIXME: Figure out total set of chars that can be present
            # in MW's usernames, and set of chars valid in jupyterhub
            # usernames, and do a proper mapping
            username = identity['username'].replace(' ', '_')
            user = self.find_user(username)
            if user is None:
                user = orm.User(name=username, id=identity['sub'])
                self.db.add(user)
                self.db.commit()
            self.set_login_cookie(user)
            self.redirect(url_path_join(self.hub.server.base_url, 'home'))
        else:
            # todo: custom error page?
            raise web.HTTPError(403)
Exemplo n.º 6
0
def complete_login(request, consumer_token, cookie, rdb_session, root_path, api_log):
    # TODO: Remove or standardize the DEBUG option
    if DEBUG:
        identity = {'sub': 6024474,
                    'username': '******'}
    else:
        handshaker = Handshaker(WIKI_OAUTH_URL, consumer_token)

        with api_log.debug('load_login_cookie') as act:
            try:
                rt_key = cookie['request_token_key']
                rt_secret = cookie['request_token_secret']
            except KeyError:
                # in some rare cases, stale cookies are left behind
                # and users have to click login again
                act.failure('clearing stale cookie, redirecting to {}', root_path)
                cookie.set_expires()
                return redirect(root_path)

        req_token = RequestToken(rt_key, rt_secret)

        access_token = handshaker.complete(req_token,
                                           request.query_string)
        identity = handshaker.identify(access_token)

    userid = identity['sub']
    username = identity['username']
    user = rdb_session.query(User).filter(User.id == userid).first()
    now = datetime.datetime.utcnow()
    if user is None:
        user = User(id=userid, username=username, last_active_date=now)
        rdb_session.add(user)
    else:
        user.last_active_date = now

    # These would be useful when we have oauth beyond simple ID, but
    # they should be stored in the database along with expiration times.
    # ID tokens only last 100 seconds or so
    # cookie['access_token_key'] = access_token.key
    # cookie['access_token_secret'] = access_token.secret

    # identity['confirmed_email'] = True/False might be interesting
    # for contactability through the username. Might want to assert
    # that it is True.

    cookie['userid'] = identity['sub']
    cookie['username'] = identity['username']

    return_to_url = cookie.get('return_to_url')
    # TODO: Clean up
    if not DEBUG:
        del cookie['request_token_key']
        del cookie['request_token_secret']
        del cookie['return_to_url']
    else:
        return_to_url = '/'
    return redirect(return_to_url)
Exemplo n.º 7
0
def wd_oauth_handshake_1():
    consumer_token = ConsumerToken(oauth_config.consumer_key, oauth_config.consumer_secret)

    # Construct handshaker with wiki URI and consumer
    handshaker = Handshaker("https://www.mediawiki.org/w/index.php", consumer_token)
    #
    # Step 1: Initialize -- ask MediaWiki for a temporary key/secret for user
    mw_redirect, request_token = handshaker.initiate()
    return mw_redirect
Exemplo n.º 8
0
def login():
    handshaker = Handshaker(
        "https://meta.wikimedia.org/w/index.php",
        oauth_token
    )
    redirect_url, request_token = handshaker.initiate()
    session['request_token'] = request_token
    session['return_to_url'] = request.args.get('next', '/')
    return redirect(redirect_url)
Exemplo n.º 9
0
def login(request, consumer_token, cookie, root_path):
    handshaker = Handshaker(WIKI_OAUTH_URL, consumer_token)

    redirect_url, request_token = handshaker.initiate()

    cookie['request_token_key'] = request_token.key
    cookie['request_token_secret'] = request_token.secret

    cookie['return_to_url'] = request.args.get('next', root_path)
    return redirect(redirect_url)
Exemplo n.º 10
0
class MWOauthHandshake(object):
    def __init__(self):
        self.consumer_token = ConsumerToken(oauth_config.consumer_key, oauth_config.consumer_secret)
        self.handshaker = Handshaker("https://www.mediawiki.org/w/index.php", self.consumer_token)
        self.request_token = ''
        self.response_qs = ''
        self.access_token = ''

    def redirection(self):
        mw_redirect, self.request_token = self.handshaker.initiate()
        return mw_redirect

    def get_access_token(self):
        self.access_token = self.handshaker.complete(self.request_token, self.response_qs)
Exemplo n.º 11
0
    async def authenticate(self, handler, data=None):
        consumer_token = ConsumerToken(
            self.client_id,
            self.client_secret,
        )

        handshaker = Handshaker(self.mw_index_url, consumer_token)
        request_token = dejsonify(
            handler.get_secure_cookie(AUTH_REQUEST_COOKIE_NAME))
        handler.clear_cookie(AUTH_REQUEST_COOKIE_NAME)
        access_token = await wrap_future(
            self.executor.submit(handshaker.complete, request_token,
                                 handler.request.query))

        identity = await wrap_future(
            self.executor.submit(handshaker.identify, access_token))
        if identity and 'username' in identity:
            # this shouldn't be necessary anymore,
            # but keep for backward-compatibility
            return {
                'name': identity['username'].replace(' ', '_'),
                'auth_state': {
                    'ACCESS_TOKEN_KEY': access_token.key,
                    'ACCESS_TOKEN_SECRET': access_token.secret,
                    'MEDIAWIKI_USER_IDENTITY': identity,
                },
            }
        else:
            self.log.error("No username found in %s", identity)
Exemplo n.º 12
0
    def authenticate(self, handler):
        code = handler.get_argument('code', False)
        if not code:
            raise web.HTTPError(400, "oauth callback made without a token")

        consumer_token = ConsumerToken(
            self.client_id,
            self.client_secret,
        )

        handshaker = Handshaker(self.mw_index_url, consumer_token)
        request_token = dejsonify(
            handler.get_secure_cookie(AUTH_REQUEST_COOKIE_NAME))
        handler.clear_cookie(AUTH_REQUEST_COOKIE_NAME)
        access_token = yield self.executor.submit(handshaker.complete,
                                                  request_token,
                                                  handler.request.query)

        identity = yield self.executor.submit(handshaker.identify,
                                              access_token)
        if identity and 'username' in identity:
            # this shouldn't be necessary anymore,
            # but keep for backward-compatibility
            return identity['username'].replace(' ', '_')
        else:
            self.log.error("No username found in %s", identity)
Exemplo n.º 13
0
def wd_oauth(request):
    if request.method == 'POST':
        body_unicode = request.body.decode('utf-8')
        body = json.loads(body_unicode)
        consumer_token = ConsumerToken(oauth_config.consumer_key,
                                       oauth_config.consumer_secret)
        print(consumer_token)
        mw_uri = "https://www.mediawiki.org/w/index.php"
        callbackURI = "http://54.166.140.4" + body[
            'current_path'] + '/authorized'
        print(callbackURI)
        handshaker = Handshaker(mw_uri=mw_uri,
                                consumer_token=consumer_token,
                                callback=callbackURI)
        mw_redirect, request_token = handshaker.initiate(callback=callbackURI)
        response_data = {'wikimediaURL': mw_redirect}
        return JsonResponse(response_data)
Exemplo n.º 14
0
def oauth_callback():
    handshaker = Handshaker(
        "https://meta.wikimedia.org/w/index.php",
        oauth_token
    )
    access_token = handshaker.complete(session['request_token'], request.query_string)
    session['acces_token'] = access_token
    identity = handshaker.identify(access_token)
    wiki_uid = identity['sub']
    user = User.get_by_wiki_uid(wiki_uid)
    if user is None:
        user = User(username=identity['username'], wiki_uid=wiki_uid)
        user.save_new()
    session['user_id'] = user.id
    return_to_url = session.get('return_to_url')
    del session['request_token']
    del session['return_to_url']
    return redirect(return_to_url)
Exemplo n.º 15
0
def oauth_callback():
    handshaker = Handshaker("https://meta.wikimedia.org/w/index.php",
                            oauth_token)
    access_token = handshaker.complete(session['request_token'],
                                       request.query_string)
    session['acces_token'] = access_token
    identity = handshaker.identify(access_token)
    wiki_uid = identity['sub']
    user = g.conn.session.query(User).filter(User.wiki_uid == wiki_uid).first()
    if user is None:
        user = User(username=identity['username'], wiki_uid=wiki_uid)
        g.conn.session.add(user)
        g.conn.session.commit()
    session['user_id'] = user.id
    return_to_url = session.get('return_to_url')
    del session['request_token']
    del session['return_to_url']
    return redirect(return_to_url)
Exemplo n.º 16
0
def auth():
    # Construct handshaker with wiki URI and consumer
    handshaker = Handshaker("https://en.wikipedia.org/w/index.php", consumer_token)
    
    # Step 1: Initialize -- ask MediaWiki for a temporary key/secret for user
    redirect, request_token = handshaker.initiate()
    
    # Make a response
    resp = make_response(render_template('redirect.html'), 302)
    resp.headers['Location'] = redirect
    # Generate a random key for redis
    rediskey = config.redisprefix + id_generator()
    # Pickle the request_token object and store it in redis
    serialrequest_token = pickle.dumps(request_token)
    r.set(rediskey, serialrequest_token)
    # Set a cookie containing the redis key
    resp.set_cookie('rediskey', rediskey)
    # Return the response
    return resp
Exemplo n.º 17
0
def get_MW_redirect(user):
    """Fetch redirect from mwoauth via consumer token for user
    :param user:    string, user
    :return:        string, redirect url for user
    """
    consumer_token = ConsumerToken(settings.MW_CLIENT_KEY,
                                   settings.MW_CLIENT_SECRET)

    # Construct handshaker with wiki URI and consumer
    handshaker = Handshaker(COMMONS_URL, consumer_token)

    # Step 1: Initialize -- ask MediaWiki for a temporary key/secret for user
    redirect, request_token = handshaker.initiate()

    # Pickle the handshaker & request token
    key = hmac(user)
    set_serialized(handshaker, settings.MWOAUTH_HANDSHAKER_PKL_KEY, key)
    set_serialized(request_token, settings.MWOAUTH_REQTOKEN_PKL_KEY, key)

    # Step 2: Authorize -- send user to MediaWiki to confirm authorization
    return redirect
Exemplo n.º 18
0
def complete_login(request, consumer_token, cookie):
    handshaker = Handshaker(WIKI_OAUTH_URL, consumer_token)

    req_token = RequestToken(cookie['request_token_key'],
                             cookie['request_token_secret'])

    access_token = handshaker.complete(req_token, request.query_string)

    identity = handshaker.identify(access_token)

    userid = identity['sub']
    username = identity['username']

    cookie['userid'] = userid
    cookie['username'] = username
    # Is this OK to put in a cookie?
    cookie['oauth_access_key'] = access_token.key
    cookie['oauth_access_secret'] = access_token.secret

    return_to_url = cookie.get('return_to_url', '/')

    return redirect(return_to_url)
Exemplo n.º 19
0
def complete_login(request, consumer_token, cookie, rdb_session):
    handshaker = Handshaker(WIKI_OAUTH_URL, consumer_token)

    req_token = RequestToken(cookie['request_token_key'],
                             cookie['request_token_secret'])

    access_token = handshaker.complete(req_token, request.query_string)
    identity = handshaker.identify(access_token)

    userid = identity['sub']
    username = identity['username']
    user = rdb_session.query(User).filter(User.id == userid).first()
    now = datetime.datetime.utcnow()
    if user is None:
        user = User(id=userid, username=username, last_login_date=now)
        rdb_session.add(user)
    else:
        user.last_login_date = now

    # These would be useful when we have oauth beyond simple ID, but
    # they should be stored in the database along with expiration times.
    # ID tokens only last 100 seconds or so
    # cookie['access_token_key'] = access_token.key
    # cookie['access_token_secret'] = access_token.secret

    # identity['confirmed_email'] = True/False might be interesting
    # for contactability through the username. Might want to assert
    # that it is True.

    cookie['userid'] = identity['sub']
    cookie['username'] = identity['username']

    return_to_url = cookie.get('return_to_url')
    del cookie['request_token_key']
    del cookie['request_token_secret']
    del cookie['return_to_url']
    return redirect(return_to_url)
Exemplo n.º 20
0
    async def get(self):
        consumer_token = ConsumerToken(
            self.authenticator.client_id,
            self.authenticator.client_secret,
        )

        handshaker = Handshaker(self.authenticator.mw_index_url,
                                consumer_token)

        redirect, request_token = await wrap_future(
            self.authenticator.executor.submit(handshaker.initiate))

        self.set_secure_cookie(AUTH_REQUEST_COOKIE_NAME,
                               jsonify(request_token),
                               expires_days=1,
                               path=url_path_join(self.base_url, 'hub',
                                                  'oauth_callback'),
                               httponly=True)
        self.log.info('oauth redirect: %r', redirect)

        self.redirect(redirect)
Exemplo n.º 21
0
def make_handshaker_mw():
    return Handshaker(
        app.config['META_MW_BASE_URL'] + app.config['META_MW_BASE_INDEX'],
        mw_oauth_token,
    )
Exemplo n.º 22
0
from mwoauth import ConsumerToken, Handshaker
import requests
from requests_oauthlib import OAuth1
from six.moves import input  # For compatibility between python 2 and 3

# Consruct a "consumer" from the key/secret provided by MediaWiki
import config  # You'll need to provide this

consumer_token = ConsumerToken(config.consumer_key, config.consumer_secret)

# Construct handshaker with wiki URI and consumer
handshaker = Handshaker("https://en.wikipedia.org/w/index.php",
                        consumer_token)

# Step 1: Initialize -- ask MediaWiki for a temporary key/secret for user
redirect, request_token = handshaker.initiate()

# Step 2: Authorize -- send user to MediaWiki to confirm authorization
print("Point your browser to: %s" % redirect)  #
response_qs = input("Response query string: ")

# Step 3: Complete -- obtain authorized key/secret for "resource owner"
access_token = handshaker.complete(request_token, response_qs)

# Construct an auth object with the consumer and access tokens
auth1 = OAuth1(consumer_token.key,
               client_secret=consumer_token.secret,
               resource_owner_key=access_token.key,
               resource_owner_secret=access_token.secret)

# Now, accessing the API on behalf of a user
Exemplo n.º 23
0
    def __init__(self,
                 user=None,
                 pwd=None,
                 mediawiki_api_url=None,
                 mediawiki_index_url=None,
                 mediawiki_rest_url=None,
                 token_renew_period=1800,
                 use_clientlogin=False,
                 consumer_key=None,
                 consumer_secret=None,
                 access_token=None,
                 access_secret=None,
                 client_id=None,
                 client_secret=None,
                 callback_url='oob',
                 user_agent=None,
                 debug=False):
        """
        This class handles several types of login procedures. Either use user and pwd authentication or OAuth.
        Wikidata clientlogin can also be used. If using one method, do NOT pass parameters for another method.
        :param user: the username which should be used for the login
        :type user: str
        :param pwd: the password which should be used for the login
        :type pwd: str
        :param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
        :type token_renew_period: int
        :param use_clientlogin: use authmanager based login method instead of standard login.
            For 3rd party data consumer, e.g. web clients
        :type use_clientlogin: bool
        :param consumer_key: The consumer key for OAuth
        :type consumer_key: str
        :param consumer_secret: The consumer secret for OAuth
        :type consumer_secret: str
        :param access_token: The access token for OAuth
        :type access_token: str
        :param access_secret: The access secret for OAuth
        :type access_secret: str
        :param callback_url: URL which should be used as the callback URL
        :type callback_url: str
        :param user_agent: UA string to use for API requests.
        :type user_agent: str
        :return: None
        """

        self.mediawiki_api_url = config[
            'MEDIAWIKI_API_URL'] if mediawiki_api_url is None else mediawiki_api_url
        self.mediawiki_index_url = config[
            'MEDIAWIKI_INDEX_URL'] if mediawiki_index_url is None else mediawiki_index_url
        self.mediawiki_rest_url = config[
            'MEDIAWIKI_REST_URL'] if mediawiki_rest_url is None else mediawiki_rest_url

        if debug:
            print(self.mediawiki_api_url)

        self.session = requests.Session()
        self.edit_token = ''
        self.instantiation_time = time.time()
        self.token_renew_period = token_renew_period

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.access_token = access_token
        self.access_secret = access_secret
        self.client_id = client_id
        self.client_secret = client_secret
        self.response_qs = None
        self.callback_url = callback_url

        if user_agent:
            self.user_agent = user_agent
        else:
            # if a user is given append " (User:USER)" to the UA string and update that value in CONFIG
            if user and user.casefold(
            ) not in config['USER_AGENT_DEFAULT'].casefold():
                config['USER_AGENT_DEFAULT'] += " (User:{})".format(user)
            self.user_agent = config['USER_AGENT_DEFAULT']
        self.session.headers.update({'User-Agent': self.user_agent})

        if self.consumer_key and self.consumer_secret:
            if self.access_token and self.access_secret:
                # OAuth procedure, based on https://www.mediawiki.org/wiki/OAuth/Owner-only_consumers#Python
                auth = OAuth1(self.consumer_key,
                              client_secret=self.consumer_secret,
                              resource_owner_key=self.access_token,
                              resource_owner_secret=self.access_secret)
                self.session.auth = auth
                self.generate_edit_credentials()
            else:
                # Oauth procedure, based on https://www.mediawiki.org/wiki/OAuth/For_Developers
                # Consruct a "consumer" from the key/secret provided by MediaWiki
                self.consumer_token = ConsumerToken(self.consumer_key,
                                                    self.consumer_secret)

                # Construct handshaker with wiki URI and consumer
                self.handshaker = Handshaker(self.mediawiki_index_url,
                                             self.consumer_token,
                                             callback=self.callback_url,
                                             user_agent=self.user_agent)

                # Step 1: Initialize -- ask MediaWiki for a temp key/secret for user
                # redirect -> authorization -> callback url
                self.redirect, self.request_token = self.handshaker.initiate(
                    callback=self.callback_url)
        elif self.client_id and self.client_secret:
            oauth = OAuth2Session(client=BackendApplicationClient(
                client_id=self.client_id))
            token = oauth.fetch_token(token_url=self.mediawiki_rest_url +
                                      '/oauth2/access_token',
                                      client_id=self.client_id,
                                      client_secret=self.client_secret)
            auth = OAuth2(token=token)
            self.session.auth = auth
            self.generate_edit_credentials()
        else:
            params_login = {
                'action': 'query',
                'meta': 'tokens',
                'type': 'login',
                'format': 'json'
            }

            # get login token
            login_token = self.session.post(
                self.mediawiki_api_url,
                data=params_login).json()['query']['tokens']['logintoken']

            if use_clientlogin:
                params = {
                    'action': 'clientlogin',
                    'username': user,
                    'password': pwd,
                    'logintoken': login_token,
                    'loginreturnurl': 'https://example.org/',
                    'format': 'json'
                }

                login_result = self.session.post(self.mediawiki_api_url,
                                                 data=params).json()

                if debug:
                    print(login_result)

                if 'clientlogin' in login_result:
                    if login_result['clientlogin']['status'] != 'PASS':
                        clientlogin = login_result['clientlogin']
                        raise LoginError(
                            "Login failed ({}). Message: '{}'".format(
                                clientlogin['messagecode'],
                                clientlogin['message']))
                    elif debug:
                        print("Successfully logged in as",
                              login_result['clientlogin']['username'])
                else:
                    error = login_result['error']
                    raise LoginError("Login failed ({}). Message: '{}'".format(
                        error['code'], error['info']))

            else:
                params = {
                    'action': 'login',
                    'lgname': user,
                    'lgpassword': pwd,
                    'lgtoken': login_token,
                    'format': 'json'
                }

                login_result = self.session.post(self.mediawiki_api_url,
                                                 data=params).json()

                if debug:
                    print(login_result)

                if login_result['login']['result'] != 'Success':
                    raise LoginError("Login failed. Reason: '{}'".format(
                        login_result['login']['result']))
                elif debug:
                    print("Successfully logged in as",
                          login_result['login']['lgusername'])

                if 'warnings' in login_result:
                    print("MediaWiki login warnings messages:")
                    for message in login_result['warnings']:
                        print("* {}: {}".format(
                            message, login_result['warnings'][message]['*']))

            self.generate_edit_credentials()
Exemplo n.º 24
0
class WDLogin(object):
    """
    A class which handles the login to Wikidata and the generation of edit-tokens
    """

    @wdi_backoff()
    def __init__(self, user=None, pwd=None, mediawiki_api_url='https://www.wikidata.org/w/api.php',
                 token_renew_period=1800, use_clientlogin=False,
                 consumer_key=None, consumer_secret=None, callback_url='oob', user_agent=None):
        """
        This class handles several types of login procedures. Either use user and pwd authentication or OAuth.
        Wikidata clientlogin can also be used. If using one method, do NOT pass parameters for another method.
        :param user: the username which should be used for the login
        :param pwd: the password which should be used for the login
        :param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
        :type token_renew_period: int
        :param use_clientlogin: use authmanager based login method instead of standard login.
            For 3rd party data consumer, e.g. web clients
        :type use_clientlogin: bool
        :param consumer_key: The consumer key for OAuth
        :type consumer_key: str
        :param consumer_secret: The consumer secret for OAuth
        :type consumer_secret: str
        :param callback_url: URL which should be used as the callback URL
        :type callback_url: str
        :param user_agent: UA string to use for API requests.
        :type user_agent: str
        :return: None
        """
        self.base_url = mediawiki_api_url
        print(self.base_url)
        self.s = requests.Session()
        self.edit_token = ''
        self.instantiation_time = time.time()
        self.token_renew_period = token_renew_period

        self.mw_url = "https://www.mediawiki.org/w/index.php"
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.response_qs = None
        self.callback_url = callback_url

        if user_agent:
            self.user_agent = user_agent
        else:
            # if a user is given append " (User:USER)" to the UA string and update that value in CONFIG
            if user and user.lower() not in config['USER_AGENT_DEFAULT'].lower():
                config['USER_AGENT_DEFAULT'] += " (User:{})".format(user)
            self.user_agent = config['USER_AGENT_DEFAULT']
        self.s.headers.update({
            'User-Agent': self.user_agent
        })

        if self.consumer_key and self.consumer_secret:
            # Oauth procedure, based on https://www.mediawiki.org/wiki/OAuth/For_Developers

            # Consruct a "consumer" from the key/secret provided by MediaWiki
            self.consumer_token = ConsumerToken(self.consumer_key, self.consumer_secret)

            # Construct handshaker with wiki URI and consumer
            self.handshaker = Handshaker(self.mw_url, self.consumer_token, callback=self.callback_url,
                                         user_agent=self.user_agent)

            # Step 1: Initialize -- ask MediaWiki for a temp key/secret for user
            # redirect -> authorization -> callback url
            self.redirect, self.request_token = self.handshaker.initiate(callback=self.callback_url)

        elif use_clientlogin:
            params = {
                'action': 'query',
                'format': 'json',
                'meta': 'authmanagerinfo',
                'amisecuritysensitiveoperation': '',
                'amirequestsfor': 'login'
            }

            self.s.get(self.base_url, params=params)

            params2 = {
                'action': 'query',
                'format': 'json',
                'meta': 'tokens',
                'type': 'login'
            }
            login_token = self.s.get(self.base_url, params=params2).json()['query']['tokens']['logintoken']

            data = {
                'action': 'clientlogin',
                'format': 'json',
                'username': user,
                'password': pwd,
                'logintoken': login_token,
                'loginreturnurl': 'http://example.org/'
            }

            login_result = self.s.post(self.base_url, data=data).json()
            print(login_result)

            if login_result['clientlogin']['status'] == 'FAIL':
                raise ValueError('Login FAILED')

            self.generate_edit_credentials()
        else:
            params = {
                'action': 'login',
                'lgname': user,
                'lgpassword': pwd,
                'format': 'json'
            }

            # get login token
            login_token = self.s.post(self.base_url, data=params).json()['login']['token']

            # do the login using the login token
            params.update({'lgtoken': login_token})
            r = self.s.post(self.base_url, data=params).json()

            if r['login']['result'] != 'Success':
                print('login failed:', r['login']['reason'])
                raise ValueError('login FAILED!!')
            else:
                print('Successfully logged in as', r['login']['lgusername'])

            self.generate_edit_credentials()

    def generate_edit_credentials(self):
        """
        request an edit token and update the cookie_jar in order to add the session cookie
        :return: Returns a json with all relevant cookies, aka cookie jar
        """
        params = {
            'action': 'query',
            'meta': 'tokens',
            'format': 'json'
        }
        response = self.s.get(self.base_url, params=params)
        self.edit_token = response.json()['query']['tokens']['csrftoken']

        return self.s.cookies

    def get_edit_cookie(self):
        """
        Can be called in order to retrieve the cookies from an instance of WDLogin
        :return: Returns a json with all relevant cookies, aka cookie jar
        """
        if (time.time() - self.instantiation_time) > self.token_renew_period:
            self.generate_edit_credentials()
            self.instantiation_time = time.time()

        return self.s.cookies

    def get_edit_token(self):
        """
        Can be called in order to retrieve the edit token from an instance of WDLogin
        :return: returns the edit token
        """
        if not self.edit_token or (time.time() - self.instantiation_time) > self.token_renew_period:
            self.generate_edit_credentials()
            self.instantiation_time = time.time()

        return self.edit_token

    def get_session(self):
        """
        returns the requests session object used for the login.
        :return: Object of type requests.Session()
        """
        return self.s

    def continue_oauth(self, oauth_callback_data=None):
        """
        Continuation of OAuth procedure. Method must be explicitly called in order to complete OAuth. This allows
        external entities, e.g. websites, to provide tokens through callback URLs directly.
        :param oauth_callback_data: The callback URL received to a Web app
        :type oauth_callback_data: bytes
        :return:
        """
        self.response_qs = oauth_callback_data

        if not self.response_qs:
            webbrowser.open(self.redirect)
            self.response_qs = input("Callback URL: ")

        # input the url from redirect after authorization
        response_qs = self.response_qs.split(b'?')[-1]

        # Step 3: Complete -- obtain authorized key/secret for "resource owner"
        access_token = self.handshaker.complete(self.request_token, response_qs)

        # input the access token to return a csrf (edit) token
        auth1 = OAuth1(self.consumer_token.key,
                       client_secret=self.consumer_token.secret,
                       resource_owner_key=access_token.key,
                       resource_owner_secret=access_token.secret)

        self.s.auth = auth1
        self.generate_edit_credentials()
Exemplo n.º 25
0
 def __init__(self):
     self.consumer_token = ConsumerToken(oauth_config.consumer_key, oauth_config.consumer_secret)
     self.handshaker = Handshaker("https://www.mediawiki.org/w/index.php", self.consumer_token)
     self.request_token = ''
     self.response_qs = ''
     self.access_token = ''
Exemplo n.º 26
0
    def __init__(self, user=None, pwd=None, mediawiki_api_url='https://www.wikidata.org/w/api.php',
                 token_renew_period=1800, use_clientlogin=False,
                 consumer_key=None, consumer_secret=None, callback_url='oob', user_agent=None):
        """
        This class handles several types of login procedures. Either use user and pwd authentication or OAuth.
        Wikidata clientlogin can also be used. If using one method, do NOT pass parameters for another method.
        :param user: the username which should be used for the login
        :param pwd: the password which should be used for the login
        :param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
        :type token_renew_period: int
        :param use_clientlogin: use authmanager based login method instead of standard login.
            For 3rd party data consumer, e.g. web clients
        :type use_clientlogin: bool
        :param consumer_key: The consumer key for OAuth
        :type consumer_key: str
        :param consumer_secret: The consumer secret for OAuth
        :type consumer_secret: str
        :param callback_url: URL which should be used as the callback URL
        :type callback_url: str
        :param user_agent: UA string to use for API requests.
        :type user_agent: str
        :return: None
        """
        self.base_url = mediawiki_api_url
        print(self.base_url)
        self.s = requests.Session()
        self.edit_token = ''
        self.instantiation_time = time.time()
        self.token_renew_period = token_renew_period

        self.mw_url = "https://www.mediawiki.org/w/index.php"
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.response_qs = None
        self.callback_url = callback_url

        if user_agent:
            self.user_agent = user_agent
        else:
            # if a user is given append " (User:USER)" to the UA string and update that value in CONFIG
            if user and user.lower() not in config['USER_AGENT_DEFAULT'].lower():
                config['USER_AGENT_DEFAULT'] += " (User:{})".format(user)
            self.user_agent = config['USER_AGENT_DEFAULT']
        self.s.headers.update({
            'User-Agent': self.user_agent
        })

        if self.consumer_key and self.consumer_secret:
            # Oauth procedure, based on https://www.mediawiki.org/wiki/OAuth/For_Developers

            # Consruct a "consumer" from the key/secret provided by MediaWiki
            self.consumer_token = ConsumerToken(self.consumer_key, self.consumer_secret)

            # Construct handshaker with wiki URI and consumer
            self.handshaker = Handshaker(self.mw_url, self.consumer_token, callback=self.callback_url,
                                         user_agent=self.user_agent)

            # Step 1: Initialize -- ask MediaWiki for a temp key/secret for user
            # redirect -> authorization -> callback url
            self.redirect, self.request_token = self.handshaker.initiate(callback=self.callback_url)

        elif use_clientlogin:
            params = {
                'action': 'query',
                'format': 'json',
                'meta': 'authmanagerinfo',
                'amisecuritysensitiveoperation': '',
                'amirequestsfor': 'login'
            }

            self.s.get(self.base_url, params=params)

            params2 = {
                'action': 'query',
                'format': 'json',
                'meta': 'tokens',
                'type': 'login'
            }
            login_token = self.s.get(self.base_url, params=params2).json()['query']['tokens']['logintoken']

            data = {
                'action': 'clientlogin',
                'format': 'json',
                'username': user,
                'password': pwd,
                'logintoken': login_token,
                'loginreturnurl': 'http://example.org/'
            }

            login_result = self.s.post(self.base_url, data=data).json()
            print(login_result)

            if login_result['clientlogin']['status'] == 'FAIL':
                raise ValueError('Login FAILED')

            self.generate_edit_credentials()
        else:
            params = {
                'action': 'login',
                'lgname': user,
                'lgpassword': pwd,
                'format': 'json'
            }

            # get login token
            login_token = self.s.post(self.base_url, data=params).json()['login']['token']

            # do the login using the login token
            params.update({'lgtoken': login_token})
            r = self.s.post(self.base_url, data=params).json()

            if r['login']['result'] != 'Success':
                print('login failed:', r['login']['reason'])
                raise ValueError('login FAILED!!')
            else:
                print('Successfully logged in as', r['login']['lgusername'])

            self.generate_edit_credentials()
Exemplo n.º 27
0
def requests_handshaker():
    consumer_key = config.OAUTH_CONSUMER_KEY
    consumer_secret = config.OAUTH_CONSUMER_SECRET
    consumer_token = ConsumerToken(consumer_key, consumer_secret)
    return Handshaker("https://meta.wikimedia.org/w/index.php", consumer_token)
Exemplo n.º 28
0
def _get_handshaker():
    consumer_token = ConsumerToken(settings.TWLIGHT_OAUTH_CONSUMER_KEY,
                                   settings.TWLIGHT_OAUTH_CONSUMER_SECRET)
    handshaker = Handshaker(settings.TWLIGHT_OAUTH_PROVIDER_URL,
                            consumer_token)
    return handshaker
Exemplo n.º 29
0
class Login(object):
    """
    A class which handles the login to Wikidata and the generation of edit-tokens
    """
    @wbi_backoff()
    def __init__(self,
                 user=None,
                 pwd=None,
                 mediawiki_api_url=None,
                 mediawiki_index_url=None,
                 mediawiki_rest_url=None,
                 token_renew_period=1800,
                 use_clientlogin=False,
                 consumer_key=None,
                 consumer_secret=None,
                 access_token=None,
                 access_secret=None,
                 client_id=None,
                 client_secret=None,
                 callback_url='oob',
                 user_agent=None,
                 debug=False):
        """
        This class handles several types of login procedures. Either use user and pwd authentication or OAuth.
        Wikidata clientlogin can also be used. If using one method, do NOT pass parameters for another method.
        :param user: the username which should be used for the login
        :type user: str
        :param pwd: the password which should be used for the login
        :type pwd: str
        :param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
        :type token_renew_period: int
        :param use_clientlogin: use authmanager based login method instead of standard login.
            For 3rd party data consumer, e.g. web clients
        :type use_clientlogin: bool
        :param consumer_key: The consumer key for OAuth
        :type consumer_key: str
        :param consumer_secret: The consumer secret for OAuth
        :type consumer_secret: str
        :param access_token: The access token for OAuth
        :type access_token: str
        :param access_secret: The access secret for OAuth
        :type access_secret: str
        :param callback_url: URL which should be used as the callback URL
        :type callback_url: str
        :param user_agent: UA string to use for API requests.
        :type user_agent: str
        :return: None
        """

        self.mediawiki_api_url = config[
            'MEDIAWIKI_API_URL'] if mediawiki_api_url is None else mediawiki_api_url
        self.mediawiki_index_url = config[
            'MEDIAWIKI_INDEX_URL'] if mediawiki_index_url is None else mediawiki_index_url
        self.mediawiki_rest_url = config[
            'MEDIAWIKI_REST_URL'] if mediawiki_rest_url is None else mediawiki_rest_url

        if debug:
            print(self.mediawiki_api_url)

        self.session = requests.Session()
        self.edit_token = ''
        self.instantiation_time = time.time()
        self.token_renew_period = token_renew_period

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.access_token = access_token
        self.access_secret = access_secret
        self.client_id = client_id
        self.client_secret = client_secret
        self.response_qs = None
        self.callback_url = callback_url

        if user_agent:
            self.user_agent = user_agent
        else:
            # if a user is given append " (User:USER)" to the UA string and update that value in CONFIG
            if user and user.casefold(
            ) not in config['USER_AGENT_DEFAULT'].casefold():
                config['USER_AGENT_DEFAULT'] += " (User:{})".format(user)
            self.user_agent = config['USER_AGENT_DEFAULT']
        self.session.headers.update({'User-Agent': self.user_agent})

        if self.consumer_key and self.consumer_secret:
            if self.access_token and self.access_secret:
                # OAuth procedure, based on https://www.mediawiki.org/wiki/OAuth/Owner-only_consumers#Python
                auth = OAuth1(self.consumer_key,
                              client_secret=self.consumer_secret,
                              resource_owner_key=self.access_token,
                              resource_owner_secret=self.access_secret)
                self.session.auth = auth
                self.generate_edit_credentials()
            else:
                # Oauth procedure, based on https://www.mediawiki.org/wiki/OAuth/For_Developers
                # Consruct a "consumer" from the key/secret provided by MediaWiki
                self.consumer_token = ConsumerToken(self.consumer_key,
                                                    self.consumer_secret)

                # Construct handshaker with wiki URI and consumer
                self.handshaker = Handshaker(self.mediawiki_index_url,
                                             self.consumer_token,
                                             callback=self.callback_url,
                                             user_agent=self.user_agent)

                # Step 1: Initialize -- ask MediaWiki for a temp key/secret for user
                # redirect -> authorization -> callback url
                self.redirect, self.request_token = self.handshaker.initiate(
                    callback=self.callback_url)
        elif self.client_id and self.client_secret:
            oauth = OAuth2Session(client=BackendApplicationClient(
                client_id=self.client_id))
            token = oauth.fetch_token(token_url=self.mediawiki_rest_url +
                                      '/oauth2/access_token',
                                      client_id=self.client_id,
                                      client_secret=self.client_secret)
            auth = OAuth2(token=token)
            self.session.auth = auth
            self.generate_edit_credentials()
        else:
            params_login = {
                'action': 'query',
                'meta': 'tokens',
                'type': 'login',
                'format': 'json'
            }

            # get login token
            login_token = self.session.post(
                self.mediawiki_api_url,
                data=params_login).json()['query']['tokens']['logintoken']

            if use_clientlogin:
                params = {
                    'action': 'clientlogin',
                    'username': user,
                    'password': pwd,
                    'logintoken': login_token,
                    'loginreturnurl': 'https://example.org/',
                    'format': 'json'
                }

                login_result = self.session.post(self.mediawiki_api_url,
                                                 data=params).json()

                if debug:
                    print(login_result)

                if 'clientlogin' in login_result:
                    if login_result['clientlogin']['status'] != 'PASS':
                        clientlogin = login_result['clientlogin']
                        raise LoginError(
                            "Login failed ({}). Message: '{}'".format(
                                clientlogin['messagecode'],
                                clientlogin['message']))
                    elif debug:
                        print("Successfully logged in as",
                              login_result['clientlogin']['username'])
                else:
                    error = login_result['error']
                    raise LoginError("Login failed ({}). Message: '{}'".format(
                        error['code'], error['info']))

            else:
                params = {
                    'action': 'login',
                    'lgname': user,
                    'lgpassword': pwd,
                    'lgtoken': login_token,
                    'format': 'json'
                }

                login_result = self.session.post(self.mediawiki_api_url,
                                                 data=params).json()

                if debug:
                    print(login_result)

                if login_result['login']['result'] != 'Success':
                    raise LoginError("Login failed. Reason: '{}'".format(
                        login_result['login']['result']))
                elif debug:
                    print("Successfully logged in as",
                          login_result['login']['lgusername'])

                if 'warnings' in login_result:
                    print("MediaWiki login warnings messages:")
                    for message in login_result['warnings']:
                        print("* {}: {}".format(
                            message, login_result['warnings'][message]['*']))

            self.generate_edit_credentials()

    def generate_edit_credentials(self):
        """
        request an edit token and update the cookie_jar in order to add the session cookie
        :return: Returns a json with all relevant cookies, aka cookie jar
        """
        params = {
            'action': 'query',
            'meta': 'tokens',
            'type': 'csrf',
            'format': 'json'
        }
        response = self.session.get(self.mediawiki_api_url, params=params)
        self.edit_token = response.json()['query']['tokens']['csrftoken']

        return self.session.cookies

    def get_edit_cookie(self):
        """
        Can be called in order to retrieve the cookies from an instance of wbi_login.Login
        :return: Returns a json with all relevant cookies, aka cookie jar
        """
        if (time.time() - self.instantiation_time) > self.token_renew_period:
            self.generate_edit_credentials()
            self.instantiation_time = time.time()

        return self.session.cookies

    def get_edit_token(self):
        """
        Can be called in order to retrieve the edit token from an instance of wbi_login.Login
        :return: returns the edit token
        """
        if not self.edit_token or (time.time() - self.instantiation_time
                                   ) > self.token_renew_period:
            self.generate_edit_credentials()
            self.instantiation_time = time.time()

        return self.edit_token

    def get_session(self):
        """
        returns the requests session object used for the login.
        :return: Object of type requests.Session()
        """
        return self.session

    def continue_oauth(self, oauth_callback_data=None):
        """
        Continuation of OAuth procedure. Method must be explicitly called in order to complete OAuth. This allows
        external entities, e.g. websites, to provide tokens through callback URLs directly.
        :param oauth_callback_data: The callback URL received to a Web app
        :type oauth_callback_data: bytes
        :return:
        """
        self.response_qs = oauth_callback_data

        if not self.response_qs:
            webbrowser.open(self.redirect)
            self.response_qs = input("Callback URL: ")

        # input the url from redirect after authorization
        response_qs = self.response_qs.split(b'?')[-1]

        # Step 3: Complete -- obtain authorized key/secret for "resource owner"
        access_token = self.handshaker.complete(self.request_token,
                                                response_qs)

        # input the access token to return a csrf (edit) token
        auth = OAuth1(self.consumer_token.key,
                      client_secret=self.consumer_token.secret,
                      resource_owner_key=access_token.key,
                      resource_owner_secret=access_token.secret)
        self.session.auth = auth
        self.generate_edit_credentials()
Exemplo n.º 30
0
from requests_oauthlib import OAuth1
from config import consumer_key, consumer_secret, api_url, redis_pw, redis_host
from redis import Redis
from celery.result import AsyncResult
import youtube_dl
import guess_language

from redisession import RedisSessionInterface

sys.path.append(
    os.path.dirname(os.path.realpath(__file__)) + "/../../../backend/")

import worker  # NOQA

consumer_token = ConsumerToken(consumer_key, consumer_secret)
handshaker = Handshaker(api_url, consumer_token)

redisconnection = Redis(host=redis_host, db=3, password=redis_pw)

app = Flask(__name__)

app.session_interface = RedisSessionInterface(redisconnection)


@app.errorhandler(Exception)
def all_exception_handler(error):
    """Handle an exception and show the traceback to error page."""
    return 'Please notify [[commons:User:Zhuyifei1999]]: ' + \
        traceback.format_exc(), 500