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)
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)
def create_app(): static_app = StaticApplication(STATIC_PATH) routes = [ StaticFileRoute('/', STATIC_PATH + '/index.html'), ('/', static_app), ('/home', home, render_basic), ('/login', login), ('/logout', logout), ('/complete_login', complete_login), ('/api', send_to_wd_api, render_basic), ('/meta', MetaApplication()) ] config_file_name = 'config.local.yaml' config_file_path = os.path.join(os.path.dirname(CUR_PATH), config_file_name) config = yaml.load(open(config_file_path)) cookie_secret = config['cookie_secret'] root_path = config.get('root_path', '/') scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, path=root_path) scm_mw.data_expiry = NEVER consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path } app = Application(routes, resources, middlewares=[scm_mw]) return app
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)
def _rehydrate_token(token): """ Convert the stored dict back into a request token that we can use for getting an access grant. """ request_token = ConsumerToken(token["key"], token["secret"]) return request_token
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
def create_app(): static_app = StaticApplication(STATIC_PATH) def fe_app_route(path, ignore_trailing=True): # added to support the removal of the '#' in Angular URLs target = STATIC_PATH + '\\index.html' if ignore_trailing: path = path + '/<_ignored*>' return StaticFileRoute(path, target) routes = [ fe_app_route('/', ignore_trailing=False), # TODO: necessary? ('/', static_app), ('/home', home, render_basic), ('/login', login), ('/logout', logout), ('/complete_login', complete_login), ('/api', send_to_wiki_api, render_basic), ('/commons', send_to_commons_api, render_basic), ('/wikidata', send_to_wikidata_api, render_basic), ('/test', send_to_test_api, render_basic), ('/meta', MetaApplication()), fe_app_route('/list'), fe_app_route('/map'), fe_app_route('/object'), fe_app_route('/games'), ] config_file_name = 'config.local.yaml' config_file_path = os.path.join(CUR_PATH, config_file_name) config = yaml.load(open(config_file_path)) cookie_secret = config['cookie_secret'] root_path = config.get('root_path', '/') scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, path=root_path) scm_mw.data_expiry = NEVER consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path } app = Application(routes, resources, middlewares=[scm_mw]) return app
def create_app(env_name='prod'): routes = [ ('/', home, render_basic), ('/admin', admin_landing, render_json), ('/admin/campaign', admin_landing, render_json), ('/admin/campaign/<campaign_id>', admin_camp_redirect, render_json), ('/admin/campaign/<campaign_id>/<camp_name>', admin_camp_dashboard, render_json), ('/admin/round', admin_landing, render_json), ('/admin/round/<round_id>', admin_round_redirect, render_json), ('/admin/round/<round_id>/<round_name>', admin_round_dashboard, render_json), ('/campaign', juror_landing, render_basic), ('/campaign/<campaign_id>', juror_camp_redirect, render_basic), ('/campaign/<campaign_id>/<camp_name>', juror_camp_dashboard, render_basic), ('/round', juror_landing, render_basic), ('/round/<round_id>', juror_round_redirect, render_basic), ('/round/<round_id>/<round_name>', juror_round_dashboard, render_basic), ('/login', login, render_basic), ('/logout', logout, render_basic), ('/complete_login', complete_login, render_basic) ] config_file_name = 'config.%s.yaml' % env_name config = yaml.load(open(config_file_name)) engine = create_engine(config.get('db_url', DEFAULT_DB_URL), echo=config.get('db_echo', False)) session_type = sessionmaker() session_type.configure(bind=engine) cookie_secret = config['cookie_secret'] assert cookie_secret root_path = config.get('root_path', '/') scm_secure = env_name == 'prod' # https only in prod scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, path=root_path, http_only=True, secure=scm_secure) middlewares = [scm_mw, DBSessionMiddleware(session_type), UserMiddleware()] consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path } app = Application(routes, resources, middlewares=middlewares) return app
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)
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)
def from_config(config): uri = "%s://%s%s%s" % (config.mediawiki['protocol'], config.mediawiki['domain'], config.mediawiki['path']['scripts'], config.mediawiki['file']['api']) oauth_config = yaml.load( open( os.path.join(configuration.snuggle['root_directory'], configuration.snuggle['oauth_config']))) consumer_token = ConsumerToken(oauth_config['consumer_key'], oauth_config['consumer_secret']) headers = config.mediawiki['requests'].get('headers', {}) comment_suffix = config.mediawiki['comment_suffix'] return API(uri, consumer_token, headers=headers, comment_suffix=comment_suffix)
def create_app(): static_app = StaticApplication(STATIC_PATH) def fe_app_route(path, ignore_trailing=True): # added to support the removal of the '#' in Angular URLs target = STATIC_PATH + '/index.html' if ignore_trailing: path = path + '/<_ignored*>' return StaticFileRoute(path, target) routes = [ fe_app_route('/', ignore_trailing=False), # TODO: necessary? ('/', static_app), ('/home', home, render_basic), ('/login', login), ('/logout', logout), ('/complete_login', complete_login), ('/api', send_to_wiki_api, render_basic), ('/commons', send_to_commons_api, render_basic), ('/wikidata', send_to_wikidata_api, render_basic), ('/test', send_to_test_api, render_basic), ('/meta', MetaApplication()), fe_app_route('/list'), fe_app_route('/map'), fe_app_route('/object'), fe_app_route('/games'), fe_app_route('/ireland'), fe_app_route('/poland'), fe_app_route('/germany'), fe_app_route('/uk'), fe_app_route('/sweden'), fe_app_route('/france'), fe_app_route('/us'), ] config_file_name = 'config.hatnote.yaml' config_file_path = os.path.join(PROJ_PATH, config_file_name) config = yaml.load(open(config_file_path)) cookie_secret = config['cookie_secret'] root_path = config.get('root_path', '/') # secure=True means cookie is HTTPS only # http_only=True means cookie is not accessible to javascript # TODO: make http_only contingent on whether or not we're in prod # (local doesn't do https) scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, secure=True, http_only=True, path=root_path) scm_mw.data_expiry = NEVER consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path } app = Application(routes, resources, middlewares=[scm_mw]) return app
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
def create_app(env_name='prod'): # rendering is handled by MessageMiddleware ui_routes = (PUBLIC_UI_ROUTES + JUROR_UI_ROUTES + ADMIN_UI_ROUTES + META_UI_ROUTES) api_routes = (PUBLIC_API_ROUTES + JUROR_API_ROUTES + ADMIN_API_ROUTES + META_API_ROUTES) print '== creating WSGI app using env name: %s' % (env_name, ) config_file_name = 'config.%s.yaml' % env_name config_file_path = os.path.join(PROJ_PATH, config_file_name) print '== loading config file: %s' % (config_file_path, ) config = yaml.load(open(config_file_path)) logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.WARN) engine = create_engine(config.get('db_url', DEFAULT_DB_URL), pool_recycle=60) session_type = sessionmaker() session_type.configure(bind=engine) tmp_rdb_session = session_type() schema_errors = get_schema_errors(Base, tmp_rdb_session) if not schema_errors: print '++ schema validated ok' else: for err in schema_errors: print '!! ', err print '!! recreate the database and update the code, then try again' sys.exit(2) # create maintainer users if they don't exist yet musers = bootstrap_maintainers(tmp_rdb_session) if musers: print '++ created new users for maintainers: %r' % (musers, ) new_series = ensure_series(tmp_rdb_session) if new_series: print '++ created new series: %r' % new_series tmp_rdb_session.commit() engine.echo = config.get('db_echo', False) if not config.get('db_disable_ping'): event.listen(engine, 'engine_connect', ping_connection) renderer = AshesRenderFactory(TEMPLATES_PATH) cookie_secret = config['cookie_secret'] assert cookie_secret root_path = config.get('root_path', '/') scm_secure = env_name == 'prod' # https only in prod scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, path=root_path, http_only=True, secure=scm_secure) if not scm_secure: scm_mw.data_expiry = NEVER def get_engine(): engine = create_engine(config.get('db_url', DEFAULT_DB_URL), pool_recycle=60) engine.echo = config.get('db_echo', False) if not config.get('db_disable_ping'): event.listen(engine, 'engine_connect', ping_connection) return engine blank_session_type = sessionmaker() middlewares = [ TimingMiddleware(), scm_mw, DBSessionMiddleware(blank_session_type, get_engine), UserMiddleware() ] api_log_path = config.get('api_log_path') if api_log_path: log_mw = LoggingMiddleware(api_log_path) middlewares.insert(0, log_mw) # hack config['api_exc_log_path'] = getattr(log_mw, 'exc_log_path', None) replay_log_path = config.get('replay_log_path') if replay_log_path: replay_log_mw = ReplayLogMiddleware(replay_log_path) middlewares.append(replay_log_mw) consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path, 'ashes_renderer': renderer } api_app = Application(api_routes, resources, middlewares=[MessageMiddleware()] + middlewares, render_factory=render_basic) ui_app = Application(ui_routes, resources, middlewares=[MessageMiddleware(use_ashes=True)] + middlewares, render_factory=renderer) static_app = StaticApplication(STATIC_PATH) root_app = Application([ StaticFileRoute('/', STATIC_PATH + '/index.html'), ('/', static_app), ('/', ui_app), ('/v1/', api_app), ('/meta', MetaApplication()) ]) return root_app
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 create_app(env_name='prod', config=None): # rendering is handled by MessageMiddleware ui_routes = (PUBLIC_UI_ROUTES + JUROR_UI_ROUTES + ADMIN_UI_ROUTES + META_UI_ROUTES) api_routes = (PUBLIC_API_ROUTES + JUROR_API_ROUTES + ADMIN_API_ROUTES + META_API_ROUTES) print '== creating WSGI app using env name: %s' % (env_name, ) logging.basicConfig() logging.getLogger('sqlalchemy.engine').setLevel(logging.WARN) if config is None: config = load_env_config(env_name=env_name) print '== loaded config file: %s' % (config['__file__'], ) engine = create_engine(config.get('db_url', DEFAULT_DB_URL), pool_recycle=60) session_type = sessionmaker() session_type.configure(bind=engine) tmp_rdb_session = session_type() schema_errors = get_schema_errors(Base, tmp_rdb_session) if not schema_errors: print '++ schema validated ok' else: for err in schema_errors: print '!! ', err print '!! recreate the database and update the code, then try again' sys.exit(2) # create maintainer users if they don't exist yet musers = bootstrap_maintainers(tmp_rdb_session) if musers: print '++ created new users for maintainers: %r' % (musers, ) new_series = ensure_series(tmp_rdb_session) if new_series: print '++ created new series: %r' % new_series tmp_rdb_session.commit() engine.echo = config.get('db_echo', False) if not config.get('db_disable_ping'): event.listen(engine, 'engine_connect', ping_connection) renderer = AshesRenderFactory(TEMPLATES_PATH) cookie_secret = config['cookie_secret'] assert cookie_secret root_path = config.get('root_path', '/') scm_secure = env_name == 'prod' # https only in prod scm_mw = SignedCookieMiddleware(secret_key=cookie_secret, path=root_path, http_only=True, secure=scm_secure) if not scm_secure: scm_mw.data_expiry = NEVER def get_engine(): engine = create_engine(config.get('db_url', DEFAULT_DB_URL), pool_recycle=60) engine.echo = config.get('db_echo', False) if not config.get('db_disable_ping'): event.listen(engine, 'engine_connect', ping_connection) return engine blank_session_type = sessionmaker() middlewares = [ TimingMiddleware(), UserIPMiddleware(), scm_mw, DBSessionMiddleware(blank_session_type, get_engine), UserMiddleware() ] api_log_path = config.get('api_log_path', 'montage_api.log') if api_log_path: log_mw = LoggingMiddleware(api_log_path) middlewares.insert(0, log_mw) # hack config['api_exc_log_path'] = getattr(log_mw, 'exc_log_path', None) replay_log_path = config.get('replay_log_path') if replay_log_path: replay_log_mw = ReplayLogMiddleware(replay_log_path) middlewares.append(replay_log_mw) consumer_token = ConsumerToken(config['oauth_consumer_token'], config['oauth_secret_token']) resources = { 'config': config, 'consumer_token': consumer_token, 'root_path': root_path, 'ashes_renderer': renderer } debug_errors = bool(os.getenv('MONTAGE_PDB', False)) or config['__env__'] == 'devtest' api_app = Application( api_routes, resources, middlewares=[MessageMiddleware(debug_errors=debug_errors)] + middlewares, render_factory=render_basic) ui_app = Application( ui_routes, resources, middlewares=[ MessageMiddleware(debug_errors=debug_errors, use_ashes=True) ] + middlewares, render_factory=renderer) static_app = StaticApplication(STATIC_PATH) root_mws = [HTTPCacheMiddleware(use_etags=True)] if not debug_errors: # don't need sentry if you've got pdb, etc. sentry_sdk.init( environment=config['__env__'], request_bodies='medium', dsn="https://[email protected]/3532775") root_mws.append(SentryMiddleware()) root_app = Application([ StaticFileRoute('/', STATIC_PATH + '/index.html'), StaticFileRoute('/a/', STATIC_PATH + '/a/index.html'), ('/', static_app), ('/', ui_app), ('/v1/', api_app), ('/meta', MetaApplication()) ], resources={'config': config}, middlewares=root_mws) return root_app
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)
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
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()
import jsonpickle from mwoauth import ( ConsumerToken, AccessToken, identify, ) from wikidataintegrator.wdi_login import WDLogin from wikidp.config import APP from wikidp.const import ConfKey MEDIAWIKI_API_URL = APP.config[ConfKey.MEDIAWIKI_API_URL] OAUTH_MEDIAWIKI_URL = APP.config[ConfKey.OAUTH_MEDIAWIKI_URL] WIKIDP_CONSUMER_KEY = APP.config[ConfKey.WIKIDP_CONSUMER_KEY] WIKIDP_CONSUMER_SECRET = APP.config[ConfKey.WIKIDP_CONSUMER_SECRET] WIKIDP_CONSUMER_TOKEN = ConsumerToken(WIKIDP_CONSUMER_KEY, WIKIDP_CONSUMER_SECRET) USER_AGENT = APP.config[ConfKey.USER_AGENT] def identify_user(): """Return the user identity object obtained from the session WDI login.""" # Get the WDI login object wdi_login_obj = get_wdi_login() access_token = AccessToken( wdi_login_obj.s.auth.client.resource_owner_key, wdi_login_obj.s.auth.client.resource_owner_secret ) return identify(OAUTH_MEDIAWIKI_URL, WIKIDP_CONSUMER_TOKEN, access_token) def is_authenticated():
def config_web(args): from flask import Flask, request, json from flask.ext.login import LoginManager from flask.ext.oauth import ( OAuth, OAuthRemoteApp, OAuthException, get_etree ) from werkzeug import url_decode, parse_options_header import flask.ext.oauth as nasty_patch_to_oauth global app app = Flask('wikimetrics') # note absolute_path does not change on the life of the application app.absolute_path_to_app_root = get_absolute_path() # TODO do we need this config to be created like an object instead of a dictionary? web_config = create_object_from_text_config_file(args.web_config) # if args.override_config: # override_config = create_object_from_text_config_file(args.override_config) # TODO override one obj with other, can we use dict? app.config.from_object(web_config) version, latest = get_wikimetrics_version() app.config['WIKIMETRICS_LATEST'] = latest app.config['WIKIMETRICS_VERSION'] = version # configure logging if not app.config['DEBUG']: import logging import sys app.logger.addHandler(logging.StreamHandler(stream=sys.stderr)) global login_manager login_manager = LoginManager() login_manager.init_app(app) # TODO, this does not need to be a # global, could be stored in flask application context global google oauth = OAuth() google = oauth.remote_app( 'google', base_url=app.config['GOOGLE_BASE_URL'], authorize_url=app.config['GOOGLE_AUTH_URI'], request_token_url=None, request_token_params={ 'scope': app.config['GOOGLE_AUTH_SCOPE'], 'response_type': 'code', }, access_token_url=app.config['GOOGLE_TOKEN_URI'], access_token_method='POST', access_token_params={ 'grant_type': 'authorization_code' }, consumer_key=app.config['GOOGLE_CLIENT_ID'], consumer_secret=app.config['GOOGLE_CLIENT_SECRET'], ) global mw_oauth_token mw_oauth_token = ConsumerToken( app.config['META_MW_CONSUMER_KEY'], app.config['META_MW_CLIENT_SECRET'], )
def record_oauth_token(state): global oauth_token oauth_token = ConsumerToken(state.app.config['OAUTH_CONSUMER_TOKEN'], state.app.config['OAUTH_SECRET_TOKEN'])
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 = ''