#!/usr/bin/python3 """ This is the flask script for Tweelyser. """ from flask import Flask, url_for, session, jsonify, request, \ flash, render_template, redirect from flask_oauthlib.contrib.client import OAuth from flask_oauthlib.contrib.client.exceptions import AccessTokenNotFound app = Flask(__name__) app.config.from_pyfile('client-secret.cfg', silent=True) oauth = OAuth(app) twitter = oauth.remote_app( name='twitter', version='1', endpoint_url='https://api.twitter.com/1.1/', request_token_url='https://api.twitter.com/oauth/request_token', access_token_url='https://api.twitter.com/oauth/access_token', authorization_url='https://api.twitter.com/oauth/authorize') @app.route('/') def index(): """ The index page """ if oauth_twitter_token(): return redirect(url_for('results')) else: return render_template("index.html")
# configure main flask application app = Flask(__name__) app.config.from_object("default_settings") app.config.from_pyfile("config.py", silent=True) if app.config["ENV"] != "production": # allow oauth2 loop to run over http (used for local testing only) os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" # configure persistent session cache Session(app) # configure flask-oauthlib application # TODO fetch config from https://identity.xero.com/.well-known/openid-configuration #1 oauth = OAuth(app) xero = oauth.remote_app( name="xero", version="2", client_id=app.config["CLIENT_ID"], client_secret=app.config["CLIENT_SECRET"], endpoint_url="https://api.xero.com/", authorization_url="https://login.xero.com/identity/connect/authorize", access_token_url="https://identity.xero.com/connect/token", refresh_token_url="https://identity.xero.com/connect/token", scope="offline_access openid profile email accounting.transactions " "accounting.reports.read accounting.journals.read accounting.settings " "accounting.contacts accounting.attachments assets projects", ) # type: OAuth2Application # configure xero-python sdk client
TRAKTV_CLIENT_ID = os.environ["TRAKTV_CLIENT_ID"] TRAKTV_CLIENT_SECRET = os.environ["TRAKTV_CLIENT_SECRET"] PEBBLE_TIMELINE_API_KEY = os.environ["PEBBLE_TIMELINE_API_KEY"] MONGODB_URL = os.environ["MONGODB_URL"] app = Flask(__name__) app.secret_key = os.environ["APP_SECRET"] sslify = SSLify(app, permanent=True, skips=['api/getLaunchData/', 'convert2png64']) Bower(app) pin_db = PinDatabase(MONGODB_URL) oauth = OAuth() trakttv = oauth.remote_app( 'trakttv', base_url='https://trakt.tv/', access_token_url='https://trakt.tv/oauth/token', authorization_url='https://trakt.tv/oauth/authorize', client_id=TRAKTV_CLIENT_ID, client_secret=TRAKTV_CLIENT_SECRET ) def scheme(request): return request.headers.get('X-Forwarded-Proto', 'http') def json_error(message, status=500):
TRAKTV_CLIENT_ID = os.environ["TRAKTV_CLIENT_ID"] TRAKTV_CLIENT_SECRET = os.environ["TRAKTV_CLIENT_SECRET"] PEBBLE_TIMELINE_API_KEY = os.environ["PEBBLE_TIMELINE_API_KEY"] MONGODB_URL = os.environ["MONGODB_URL"] app = Flask(__name__) app.secret_key = os.environ["APP_SECRET"] sslify = SSLify(app, permanent=True, skips=['api/getLaunchData/', 'convert2png64']) Bower(app) pin_db = PinDatabase(MONGODB_URL) oauth = OAuth() trakttv = oauth.remote_app( 'trakttv', base_url='https://trakt.tv/', access_token_url='https://trakt.tv/oauth/token', authorization_url='https://trakt.tv/oauth/authorize', client_id=TRAKTV_CLIENT_ID, client_secret=TRAKTV_CLIENT_SECRET) def scheme(request): return request.headers.get('X-Forwarded-Proto', 'http') def json_error(message, status=500): message = {
from contextlib import contextmanager from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import LoginManager from flask_oauthlib.contrib.client import OAuth from raven.contrib.flask import Sentry __all__ = ['db', 'login_manager', 'oauth', 'sentry', 'capture_exception'] db = SQLAlchemy() migrate = Migrate() login_manager = LoginManager() oauth = OAuth() sentry = Sentry() oauth.remote_app( name='douban', version='2', endpoint_url='https://api.douban.com/', access_token_url='https://www.douban.com/service/auth2/token', refresh_token_url='https://www.douban.com/service/auth2/token', authorization_url='https://www.douban.com/service/auth2/auth', scope=['douban_basic_common', 'shuo_basic_r', 'shuo_basic_w'], compliance_fixes='.douban:douban_compliance_fix') @contextmanager def capture_exception(*exceptions, **kwargs):
def create_app(): # OAUTHLIB_INSECURE_TRANSPORT needed in order to use HTTP-endpoints os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = 'true' app = Flask(__name__) app.config.update(CONSUMER_CREDENTIALS) app.secret_key = 'development' oauth = OAuth(app) # OAuth2 Provider configuration of invenio-oauth2server example app. remote = oauth.remote_app( name='invenio_example_consumer', # client_id='', # client_secret='', # scope=['test:scope', 'email'], version='2', endpoint_url='http://127.0.0.1:5000/', access_token_url='http://127.0.0.1:5000/oauth/token', refresh_token_url='http://127.0.0.1:5000/oauth/token', authorization_url='http://127.0.0.1:5000/oauth/authorize' ) def oauth_token_required(f): """ Decorator that checks if consumer already has access_token Only checks the availability, not validity of the token. """ @wraps(f) def decorated_function(*args, **kwargs): if get_oauth_token() is None: # return redirect(url_for('.index')) return '<br>' \ '<h2>T_T You don\'t have a token yet</h2>' \ '<a href="{}"> Get one from here</a>' \ .format(url_for('index')) return f(*args, **kwargs) return decorated_function @app.before_first_request def _run_on_start(): print("Client_ID is {}".format(remote.client_id)) print("Client_Secret is {}".format(remote.client_secret)) print("Redirect url is {}".format(url_for('authorized', _external=True))) print("Requested scopes: {}".format(remote.scope)) @app.route('/', methods=['GET']) def index(): """ Mainpage. Display info about token and an action menu. """ if get_oauth_token(): return """ <h1>^_^ Congratulations, you (already?) have an OAuth 2 token!</h1> <h2>What would you like to do next?</h2> <ul> <li><a href="/auto_refresh"> Implicitly refresh access token</a></li> <li><a href="/manual_refresh"> Explicitly refresh access token</a></li> <li><a href="/validate"> Validate the current token</a></li> <li><a href="/login"> Authorize the consumer again</a></li> <li><a href="/logout"> Delete current token, i.e Logout</a></li> </ul> <br> Current token information: <br> <pre>{}</pre> """.format(pformat(get_oauth_token(), indent=4)) # noqa return """ <h1>OAuth2 consumer application</h1> <h2>Please click the link to start OAuth authorization flow</h2> <ul> <li><a href="/login"> Start authorization flow</a></li> </ul> """ @app.route('/login', methods=['GET']) def login(): """ Prepare an authorization request and redirect client to Provider Prepare an authorization request and redirect client / browser to Provider for authentication and to answer the authorization request. Example of key-values sent to Provider in query part URI - response_type: 'code' for authz flow, 'token' for implicit flow - client_id: 'identifier of consumer generated by provider' - redirect_uri: 'where client should be redirected after authorization' - scope: [list of scopes consumer requesting authorization for] - state: used to protect against CSRF """ return remote.authorize(callback_uri=url_for('authorized', _external=True)) @app.route('/authorized', methods=['GET', 'POST']) def authorized(): """Endpoint where client is redirected after an authorization attempt. OAuth2 Provider will redirect client / browser to this endpoint after an authorization attempt has been made. If authorization was granted redirect request contains 'code'-parameter in querystring. Consumer automatically requests an access token using this 'code'-parameter form Provider's access_token_url Example of key values sent in access token request: - code: 'value of code parameter obtained previously' - client_id: 'identifier of consumer generated by provider' - client_secret: 'secret of consumer generated by provider' - grant_type: 'authorization code' as code - redirect_url: used only to verify client is Example of response received from Provider - access_token: 2YotnFZFEjr1zCsicMWpAA - token_type: Bearer - expires_in: 3600 - refresh_token: tGzv3JOkF0XG5Qx2TlKWIA - scopes: [list of scopes consumer is authorized to] Possible errors in authorization process are returned in querystring. """ response = remote.authorized_response() if response is None: return '<br>' \ '<h2>T_T Access denied</h2>' \ '<br>' \ '<pre>error={error}</pre>'\ '<br><a href="{link}"> Try again</a>' \ .format(link=url_for('index'), error=request.args['error']) if isinstance(response, dict) and 'access_token' in response: store_oauth_token(response) return redirect(url_for('.index')) return str(response) @app.route("/auto_refresh", methods=['GET']) @oauth_token_required def auto_refresh(): """Obtaining a new access token automatically using a refresh token. By making a call to this endpoint the consumer set token to expired state and upon making a new request for protected resource, consumer first request a new access token using refresh token. Note that all requests and updates related to tokens happen behind the scenes. """ # We force expiration of the token by setting expired_at value # of the token to a past moment. # This will trigger an automatic refresh next time we interact with # Invenio API. token = get_oauth_token() token['expires_at'] = time() - 10 resp = remote.get('oauth/info') # prefixed with remote.endpoint_url return redirect(url_for('.index')) @app.route("/manual_refresh", methods=['GET']) @oauth_token_required def manual_refresh(): """Obtaining a new access token manually using a refresh token. Request for new access token can be sent even if the old access token has not yet expired. Unfortunately flask-oauthlib OAuthApplication doesn't provide manual refreshing of tokens out-of-the-box, so internal OAuth2Session needs to be used. When using OAuth2Session to refresh, client_id and client_secret must be provided as extra arguments. When doing implicit / automatic refresh with flask-oauthlib these values are automatically included in the request. Note that obtained new access token must be stored manually. """ extra = { 'client_id': remote.client_id, 'client_secret': remote.client_secret, } oauthsession = OAuth2Session(remote.client_id, token=get_oauth_token()) resp = oauthsession.refresh_token(remote.refresh_token_url, **extra) store_oauth_token(resp) # Alternative way # # Build OAuth2Session # oauthsession = remote.make_oauth_session(token=get_oauth_token()) # # # Use the built OAuth2Session to execute refresh token request # # even though authorization token is still valid. # store_oauth_token(oauthsession.refresh_token( # remote.refresh_token_url)) return redirect(url_for('.index')) @app.route("/validate", methods=['GET']) @oauth_token_required def validate(): """ Endpoint used to check validity of access token. Basically consumer tries to access a resource in Provider and if the request succeeds the token is considered to be valid. """ resp = remote.get('oauth/info') # prefixed with remote.endpoint_url return """Endpoint '/oauth/info' returned following information: <pre>{}</pre> <br> <a href="/"> Return</a> """.format(pformat(resp.json(), indent=4)) @app.route('/logout', methods=['GET']) def logout(): """ Endpoint to logout from the consumer. Consumer will delete access and refresh tokens it has stored, losing access to resources at Provider. """ session.pop('oauth_token', None) return redirect(url_for('index')) @remote.tokengetter def get_oauth_token(): """ Returns the saved OAuth token object. Returned object contains all the information Provider sent regarding to access token. Example of OAuth token object: { "access_token": "6J3JyHLoP0K9HzL21V8y3Pj73zQDVf", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "RxFZ1CSkjJF9PeFqDCaKTWYB6V5N4w", "scope": "test:scope" } """ return session.get('oauth_token') @remote.tokensaver def store_oauth_token(resp): """ Saves the OAuth token and it's metadata obtained from Provider """ # request-oauthlib expects a dictionary containing at least # access_token and token_type values. Successful access token response # must always contain those values, so we can store the whole response. session['oauth_token'] = resp return app
from werkzeug.exceptions import BadRequest, Unauthorized from indicomobile import app from indicomobile.views.errors import generic_error_handler class CertOAuth2Application(OAuth2Application): def make_oauth_session(self, **kwargs): oauth = super(CertOAuth2Application, self).make_oauth_session(**kwargs) oauth.verify = app.config.get('CERT_FILE', True) return oauth oauth_blueprint = _bp = Blueprint('oauth_blueprint', __name__, template_folder='templates') oauth = OAuth(app) indico = oauth.add_remote_app(CertOAuth2Application('indico'), name='indico', version='2', endpoint_url=app.config['INDICO_URL'], access_token_url=app.config['ACCESS_TOKEN_URL'], authorization_url=app.config['AUTHORIZE_URL'], client_id=app.config['CLIENT_ID'], client_secret=app.config['CLIENT_SECRET'], scope=['read:user read:legacy_api']) @indico.tokensaver def store_oauth_indico_token(token): session['indico_mobile_oauthtok'] = token