def load_flask_dance_authorization(app): facebook_bp = load_google_authentication(app) google_bp = load_facebook_authentication(app) # setup login manager login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = "security.login" # @login_manager.user_loader # def load_user(user_id): # return User.query.get(int(user_id)) @login_manager.user_loader def load_user(user_id): """ This will be used many times like on using current_user :param user_id: username :return: user or none """ # http://librelist.com/browser/flask/2012/4/7/current-blueprint/#44814417e8289f5f5bb9683d416ee1ee blueprint = current_app.blueprints[request.blueprint] return User.query.get(int(user_id)) # setup SQLAlchemy backend facebook_bp.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) google_bp.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
def test_sqla_delete_token(app, db, blueprint, request): class OAuth(db.Model, OAuthConsumerMixin): pass blueprint.backend = SQLAlchemyBackend(OAuth, db.session) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # Create an existing OAuth token for the service existing = OAuth( provider="test-service", token={ "access_token": "something", "token_type": "bearer", "scope": ["blah"], }, ) db.session.add(existing) db.session.commit() assert len(OAuth.query.all()) == 1 assert blueprint.token == { "access_token": "something", "token_type": "bearer", "scope": ["blah"], } del blueprint.token assert blueprint.token == None assert len(OAuth.query.all()) == 0
def test_sqla_cache(app, db, blueprint, request): cache = Cache(app) class OAuth(db.Model, OAuthConsumerMixin): pass blueprint.backend = SQLAlchemyBackend(OAuth, db.session, cache=cache) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) with record_queries(db.engine) as queries: with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 2 expected_token = { "access_token": "foobar", "token_type": "bearer", "scope": [""], } # check the database authorizations = OAuth.query.all() assert len(authorizations) == 1 oauth = authorizations[0] assert oauth.provider == "test-service" assert isinstance(oauth.token, dict) assert oauth.token == expected_token # cache should be invalidated assert cache.get("flask_dance_token|test-service|None") is None # first reference to the token should generate SQL queries with record_queries(db.engine) as queries: assert blueprint.token == expected_token assert len(queries) == 1 # should now be in the cache assert cache.get("flask_dance_token|test-service|None") == expected_token # subsequent references should not generate SQL queries with record_queries(db.engine) as queries: assert blueprint.token == expected_token assert len(queries) == 0
def test_sqla_backend(app, db, blueprint, request): class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(OAuthConsumerMixin, db.Model): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # for now, we'll assume that Alice is the only user alice = User(name="Alice") db.session.add(alice) db.session.commit() # load alice's ID -- this issues a database query alice.id blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=alice) with record_queries(db.engine) as queries: with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 3 # check the database alice = User.query.first() authorizations = OAuth.query.all() assert len(authorizations) == 1 oauth = authorizations[0] assert oauth.user_id == alice.id assert oauth.provider == "test-service" assert isinstance(oauth.token, dict) assert oauth.token == { "access_token": "foobar", "token_type": "bearer", "scope": [""], }
def test_sqla_overwrite_token(app, db, blueprint, request): class OAuth(OAuthConsumerMixin, db.Model): pass blueprint.backend = SQLAlchemyBackend(OAuth, db.session) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # Create an existing OAuth token for the service existing = OAuth( provider="test-service", token={ "access_token": "something", "token_type": "bearer", "scope": ["blah"], }, ) db.session.add(existing) db.session.commit() assert len(OAuth.query.all()) == 1 with record_queries(db.engine) as queries: with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 2 # check that the database record was overwritten authorizations = OAuth.query.all() assert len(authorizations) == 1 oauth = authorizations[0] assert oauth.provider == "test-service" assert isinstance(oauth.token, dict) assert oauth.token == { "access_token": "foobar", "token_type": "bearer", "scope": [""], }
def test_sqla_flask_login_misconfigured(app, db, blueprint, request): login_manager = LoginManager(app) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(OAuthConsumerMixin, db.Model): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # configure login manager @login_manager.user_loader def load_user(userid): return User.query.get(userid) calls = [] def callback(*args, **kwargs): calls.append((args, kwargs)) oauth_error.connect(callback) request.addfinalizer(lambda: oauth_error.disconnect(callback)) with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(calls) == 1 assert calls[0][0] == (blueprint, ) error = calls[0][1]['error'] assert isinstance(error, ValueError) assert str(error) == 'Cannot set OAuth token without an associated user'
def create_app(): ''' Initialise the application with necessary extensions ''' app = Flask(__name__) app.config.from_object(Config) app.app_context().push() bootstrap.init_app(app) db.init_app(app) login_manager.init_app(app) app.register_blueprint(main) app.register_blueprint(auth) app.register_blueprint(jinja_templates) app.register_blueprint(errors) github_blueprint = make_github_blueprint( client_id=Config.client_id, client_secret=Config.client_secret) github_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False) app.register_blueprint(github_blueprint, url_prefix='/login') @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) @oauth_authorized.connect_via(github_blueprint) def github_logged_in(blueprint, token): account_info = blueprint.session.get('/user') if account_info.ok: account_info_json = account_info.json() username = account_info_json['login'] query = User.query.filter_by(username=username) try: user = query.one() except NoResultFound: user = User(username=username) db.session.add(user) db.session.commit() login_user(user) flash("Successfully signed in with GitHub.", 'success') return app
def test_sqla_flask_login_no_user_required(app, db, blueprint, request): # need a URL to hit, so that tokens will be loaded, but result is irrelevant responses.add( responses.GET, "https://example.com/noop", ) login_manager = LoginManager(app) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(OAuthConsumerMixin, db.Model): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) blueprint.backend = SQLAlchemyBackend( OAuth, db.session, user=current_user, user_required=False, ) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # configure login manager @login_manager.user_loader def load_user(userid): return User.query.get(userid) # create a simple view @app.route("/") def index(): return "success" with app.test_request_context("/"): # no one is logged in -- this is an anonymous user logout_user() # this should *not* raise an error blueprint.session.get("/noop") assert blueprint.session.token == None
def register_facebook_blueprint(app): # Facebook client_id = app.config.get('OAUTH_CONFIG')['FACEBOOK']['client_id'] client_secret = app.config.get('OAUTH_CONFIG')['FACEBOOK']['client_secret'] facebook_blueprint = make_facebook_blueprint( client_id=client_id, client_secret=client_secret, scope=["public_profile", "email"]) facebook_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) app_token = get_facebook_app_token(app) if app_token: app.register_blueprint(facebook_blueprint, url_prefix="/login") else: print( "Facebook app token not found in config. Facebook blueprint not configured." ) # create/login local user on successful OAuth login @oauth_authorized.connect_via(facebook_blueprint) def facebook_logged_in(blueprint, token): if not token: flash("Failed to log in with {name}".format(name=blueprint.name)) return # figure out who the user is resp = blueprint.session.get("/me?fields=email,name") if resp.ok: print(f"Response from facebook: {resp.json()}") username = resp.json()["email"] query = User.query.filter_by(username=username) try: user = query.one() except NoResultFound: # create a user user = User() user.username = username user.save() login_user(user) flash("Successfully signed in with Facebook", "success") else: print(resp.text) msg = "Failed to fetch user info from {name}".format( name=blueprint.name) flash(msg, category="error")
def create_app(config_class=Config): app = Flask(__name__) app.config.from_object(Config) db.init_app(app) login_manager.init_app(app) login_manager.login_view = 'main.login' app.register_blueprint(google_auth_bp, url_prefix='/auth') from app.main import bp as main_blueprint app.register_blueprint(main_blueprint) # Setup SQLAlchemy flask-dance backend google_auth_bp.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user) return app
def register_google_blueprint(app): # Google """ Registers the google blueprint implemented by flask dance. :param app: :return: """ client_id = app.config.get('OAUTH_CONFIG')['GOOGLE']['client_id'] client_secret = app.config.get('OAUTH_CONFIG')['GOOGLE']['client_secret'] google_blueprint = make_google_blueprint( client_id=client_id, client_secret=client_secret, scope=["openid", "profile", "email"]) google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) app.register_blueprint(google_blueprint, url_prefix="/login") # create/login local user on successful OAuth login @oauth_authorized.connect_via(google_blueprint) def google_logged_in(blueprint, token): if not token: flash("Failed to log in with {name}".format(name=blueprint.name)) return # figure out who the user is resp = blueprint.session.get("/oauth2/v2/userinfo") if resp.ok: username = resp.json()["email"] query = User.query.filter_by(username=username) try: user = query.one() except NoResultFound: # create a user user = User() user.username = username user.save() login_user(user) flash("Successfully signed in with Google", "success") else: msg = "Failed to fetch user info from {name}".format( name=blueprint.name) flash(msg, category="error")
def instantiate(cls, app): """Instantiate shared data""" cls.db = SQLAlchemy() importlib.import_module('src.models.Action') importlib.import_module('src.models.Answer') importlib.import_module('src.models.Application') OAuth = importlib.import_module('src.models.OAuth').OAuth importlib.import_module('src.models.Question') importlib.import_module('src.models.Settings') importlib.import_module('src.models.User') cls.db.init_app(app) with app.app_context(): cls.db.create_all() cls.google = make_google_blueprint(client_id=app.config.get('GOOGLE_CLIENT_ID'), client_secret=app.config.get('GOOGLE_CLIENT_SECRET'), scope=app.config.get('GOOGLE_SCOPES')) cls.google.backend = SQLAlchemyBackend(OAuth, cls.db.session, user=current_user) app.register_blueprint(cls.google) cls.login_manager = LoginManager() cls.login_manager.init_app(app) cls.login_manager.login_view = 'google.login' cls.login_manager.session_protection = 'strong'
def google_auth(app): """ Hook up google oauth authentication """ app.register_blueprint(blueprint, url_prefix='/login') blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
def authinit(app): userauth = Blueprint('userauth', __name__) google_blueprint = make_google_blueprint( client_id=app.config['globalConfig'].Config.get( "OAuth", "GOOGLE_CLIENT_ID"), client_secret=app.config['globalConfig'].Config.get( "OAuth", "GOOGLE_CLIENT_SECRET"), scope=[ #"https://www.googleapis.com/auth/plus.me", "https://www.googleapis.com/auth/userinfo.email" ], offline=True) google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=True) user_manager = UserManager(app, db, Member) user_manager.USER_ENABLE_AUTH0 = True user_manager.unauthenticated_view = our_login login_manager = LoginManager() login_manager.login_view = "google.login" login_manager.init_app(app) login_manager.anonymous_user = AnonymousMember @login_manager.user_loader def load_user(user_id): if not user_id.lower().endswith("@makeitlabs.com"): logger.error("User {0} invalid for login".format(user_id)) return None mid = user_id.split("@")[0] mr = Member.query.filter(Member.member == mid).one_or_none() if not mr: logger.error("User {0} Found no member record".format(user_id)) logger.debug("User {0} loaded".format(user_id)) return mr #return Member.get(user_id) @userauth.route("/google_login") def google_login(): if not google.authorized: logger.debug("Not google authorized") session['next_url'] = request.args.get('next') return redirect(url_for("google.login")) resp = google.get(SCOPE) assert resp.ok, resp.text return resp.text @oauth_authorized.connect_via(google_blueprint) def google_logged_in(blueprint, token): resp = google.get("/oauth2/v2/userinfo") #print "RESP",dir(resp) #print "HEADERS",resp.headers #print "REASON",resp.reason #print "TEXT",resp.text #print "NEXT",resp.next #print "LINKS",resp.links #print "URL",resp.url #print "IS_REDIRECT",resp.is_redirect if resp.ok: account_info_json = resp.json() email = account_info_json['email'] member = email.split("@")[0] logger.debug("Google auth RESP for {0} {1}".format(email, member)) if not email.endswith("@makeitlabs.com"): flash( "Not a MakeIt Labs account - You must log in with your @makeitlabs.com email address", 'warning') logger.error("Not a MakeIt Labs account " + str(email)) return redirect(url_for('empty')) #query = Member.query.filter_by(Member.member.ilike(member)) #if not query: query = Member.query.filter(Member.email.ilike(email)) try: user = query.all() if len(user) > 1: flash( "Error - Multiple accounts with same email - please seek assistance", 'warning') logger.error("%s has multiple account (GUI Login)" % email) return redirect(url_for('empty')) if len(user) == 0: flash("Error - No account found - please seek assistance", 'warning') logger.error("No account matching %s for GUI login" % email) return redirect(url_for('empty')) user = user[0] sub = quickSubscriptionCheck(member_id=user.id) #print "UserID %s SUB IS %s" % (user.id,sub) if sub == "Active" or sub == "Grace Period": if (UserRoles.query.filter( UserRoles.member_id == user.id).count() >= 1): login_user(user, remember=True) flash("Welcome!") return redirect(url_for('index')) logintype = app.config['globalConfig'].Config.get( 'General', 'Logins') if logintype == "resource": if (AccessByMember.query.filter( AccessByMember.member_id == user.id, AccessByMember.level >= AccessByMember.LEVEL_TRAINER).count() == 0): flash("Only resource managers may log in") logger.error("Only resource managers may log in " + str(email)) else: login_user(user, remember=True) else: flash("Welcome!") login_user(user, remember=True) return redirect(url_for('index')) else: flash("Login Denied - " + str(sub), 'danger') logger.error("Login Denied - " + str(email) + " is " + str(sub)) return redirect(url_for('empty')) except NoResultFound: flash( "Email adddress " + str(email) + " not found in member database", "warning") logger.error("Email adddress " + str(email) + " not found in member database") return redirect(url_for('empty')) else: logger.error("Google auth RESP is NOT okay") @userauth.route('/google_logout') def google_logout(): """Revokes token and empties session.""" if google.authorized: try: google.get( 'https://accounts.google.com/o/oauth2/revoke', params={'token': google.token['access_token']}, ) except InvalidClientIdError: # token expiration del google.token flash("OAuth error: Invalid Client ID", 'danger') redirect(url_for('main.index')) session.clear() logout_user() return redirect(url_for('main.index')) app.register_blueprint(google_blueprint, url_prefix="/google_login")
**kwargs) self.last_response = resp if resp.status_code == 403 and resp.headers.get( "X-RateLimit-Remaining"): rl_remaining = int(resp.headers["X-RateLimit-Remaining"]) if rl_remaining < 1: raise RateLimited(response=resp) return resp github_bp = make_github_blueprint( scope="admin:repo_hook", redirect_to="ui.index", session_class=GithubSession, ) github_bp.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) @oauth_authorized.connect_via(github_bp) def github_logged_in(blueprint, token): if not token: flash("Failed to log in with Github") if "error_reason" in token: msg = "Access denied. Reason={reason} error={error}".format( reason=request.args["error_reason"], error=request.args["error_description"], ) flash(msg) else: # figure out who the user is try:
user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) class UserSchema(ma.ModelSchema): class Meta: model = User class TodoSchema(ma.ModelSchema): class Meta: model = Todo twitter_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False) @app.route('/twitter') def twitter_login(): if not twitter.authorized: print('\x1b[6;30;42m' + 'sdsdsds' + '\x1b[0m') return redirect(url_for('twitter.login')) account_info = twitter.get('account/settings.json') account_info_json = account_info.json() return '<h1>Your Twitter name is @{}'.format( account_info_json['screen_name'])
from flask_dance.contrib.jira import make_jira_blueprint from flask_dance.consumer import oauth_authorized, oauth_error from flask_dance.consumer.backend.sqla import SQLAlchemyBackend from openedx_webhooks import db from openedx_webhooks.models import OAuth ## JIRA ## jira_bp = make_jira_blueprint( # this *should* pick up the client_key and rsa_key from app.config, # but it doesn't seem to be doing so... :( consumer_key=os.environ.get("JIRA_OAUTH_CONSUMER_KEY"), rsa_key=os.environ.get("JIRA_OAUTH_RSA_KEY"), # these are actually necessary base_url="https://openedx.atlassian.net", backend=SQLAlchemyBackend(OAuth, db.session), ) @oauth_authorized.connect_via(jira_bp) def jira_logged_in(blueprint, token): if token: flash("Successfully signed in with JIRA") else: flash("You denied the request to sign in with JIRA") @oauth_error.connect_via(jira_bp) def jira_error(blueprint, message, response=None): flash(message, category="error")
def test_sqla_flask_login(app, db, blueprint, request): login_manager = LoginManager(app) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(db.Model, OAuthConsumerMixin): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # create some users u1 = User(name="Alice") u2 = User(name="Bob") u3 = User(name="Chuck") db.session.add_all([u1, u2, u3]) db.session.commit() # configure login manager @login_manager.user_loader def load_user(userid): return User.query.get(userid) with record_queries(db.engine) as queries: with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # set alice as the logged in user sess["user_id"] = u1.id # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 4 # lets do it again, with Bob as the logged in user -- he gets a different token responses.reset() responses.add( responses.POST, "https://example.com/oauth/access_token", body='{"access_token":"abcdef","token_type":"bearer","scope":"bob"}', ) with record_queries(db.engine) as queries: with app.test_client() as client: # reset the session before the request with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # set bob as the logged in user sess["user_id"] = u2.id # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 4 # check the database authorizations = OAuth.query.all() assert len(authorizations) == 2 u1_oauth = OAuth.query.filter_by(user=u1).one() assert u1_oauth.provider == "test-service" assert u1_oauth.token == { "access_token": "foobar", "token_type": "bearer", "scope": [""], } u2_oauth = OAuth.query.filter_by(user=u2).one() assert u2_oauth.provider == "test-service" assert u2_oauth.token == { "access_token": "abcdef", "token_type": "bearer", "scope": ["bob"], } u3_oauth = OAuth.query.filter_by(user=u3).all() assert len(u3_oauth) == 0
# ----------------------------------------------------------------------------------------------- # # -------------------------------------- Database setup ----------------------------------------- # db = SQLAlchemy(app) class User(UserMixin, db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(250), unique=True) class OAuth(OAuthConsumerMixin, db.Model): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) GITHUB_BLUEPRINT.backend = SQLAlchemyBackend( OAuth, db.session, user=current_user, user_required=False) ##in_production # GITHUB_BLUEPRINT.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) # ----------------------------------------------------------------------------------------------- # # ----------------------------------------------------------------------------------------------- # # --------------------------------- Setting up login manager ------------------------------------ # login_manager = LoginManager(app) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # ----------------------------------------------------------------------------------------------- #
def test_sqla_flask_login_anon_to_authed(app, db, blueprint, request): login_manager = LoginManager(app) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(db.Model, OAuthConsumerMixin): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # configure login manager @login_manager.user_loader def load_user(userid): return User.query.get(userid) # create a user object when OAuth succeeds def logged_in(sender, token): assert token assert blueprint == sender resp = sender.session.get("/user") user = User(name=resp.json()["name"]) login_user(user) db.session.add(user) db.session.commit() flask.flash("Signed in successfully") oauth_authorized.connect(logged_in, blueprint) request.addfinalizer(lambda: oauth_authorized.disconnect(logged_in, blueprint)) # mock out the `/user` API call responses.add( responses.GET, "https://example.com/user", body='{"name":"josephine"}', ) with record_queries(db.engine) as queries: with app.test_client() as client: with client.session_transaction() as sess: sess["test-service_oauth_state"] = "random-string" # make the request resp = client.get( "/login/test-service/authorized?code=secret-code&state=random-string", base_url="https://a.b.c", ) # check that we redirected the client assert resp.status_code == 302 assert resp.headers["Location"] == "https://a.b.c/oauth_done" assert len(queries) == 5 # check the database users = User.query.all() assert len(users) == 1 user = users[0] assert user.name == "josephine" authorizations = OAuth.query.all() assert len(authorizations) == 1 oauth = authorizations[0] assert oauth.provider == "test-service" assert oauth.token == { "access_token": "foobar", "token_type": "bearer", "scope": [""], } assert oauth.user_id == user.id
def test_sqla_flask_login_preload_logged_in_user(app, db, blueprint, request): # need a URL to hit, so that tokens will be loaded, but result is irrelevant responses.add( responses.GET, "https://example.com/noop", ) login_manager = LoginManager(app) class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) class OAuth(db.Model, OAuthConsumerMixin): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) db.create_all() def done(): db.session.remove() db.drop_all() request.addfinalizer(done) # create some users, and tokens for some of them alice = User(name="Alice") alice_token = {"access_token": "alice123", "token_type": "bearer"} alice_oauth = OAuth(user=alice, token=alice_token, provider="test-service") bob = User(name="Bob") bob_token = {"access_token": "bob456", "token_type": "bearer"} bob_oauth = OAuth(user=bob, token=bob_token, provider="test-service") chuck = User(name="Chuck") # chuck doesn't get a token db.session.add_all([alice, alice_oauth, bob, bob_oauth, chuck]) db.session.commit() # configure login manager @login_manager.user_loader def load_user(userid): return User.query.get(userid) # create a simple view @app.route("/") def index(): return "success" with app.test_request_context("/"): login_user(alice) # hit /noop to load tokens blueprint.session.get("/noop") # now the flask-dance session should have Alice's token loaded assert blueprint.session.token == alice_token with app.test_request_context("/"): # set bob as the logged in user login_user(bob) # hit /noop to load tokens blueprint.session.get("/noop") # now the flask-dance session should have Bob's token loaded assert blueprint.session.token == bob_token with app.test_request_context("/"): # now let's try chuck login_user(chuck) blueprint.session.get("/noop") assert blueprint.session.token == None with app.test_request_context("/"): # no one is logged in -- this is an anonymous user logout_user() blueprint.session.get("/noop") assert blueprint.session.token == None
from config import Config from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_dance.consumer.backend.sqla import SQLAlchemyBackend from flask_dance.contrib.github import make_github_blueprint from flask_login import LoginManager from werkzeug.contrib.fixers import ProxyFix app = Flask(__name__) app.wsgi_app = ProxyFix(app.wsgi_app) app.config.from_object(Config) db = SQLAlchemy(app) migrate = Migrate(app, db) github_blueprint = make_github_blueprint( client_id="674925257692ed46a38b", client_secret="319fb87ac542c68085927440429a968f0bf55dbf", ) app.register_blueprint(github_blueprint, url_prefix="/login") login_manager = LoginManager() login_manager.init_app(app) from app import routes, models github_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session)
submit = SubmitField('Update') # setup login manager login_manager = LoginManager(app) login_manager.login_view = 'github.login' login_manager.login_message_category = 'info' @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) # setup SQLAlchemy backend blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) # create/login local user on successful OAuth login # the following 2 functions are taken from # the homepage of flask-dance extention # with some edits to fit the project @oauth_authorized.connect_via(blueprint) def github_logged_in(blueprint, token): if not token: flash("Failed to log in with GitHub.", category="error") return False resp = blueprint.session.get("/user") if not resp.ok: msg = "Failed to fetch user info from GitHub."
google_blueprint = make_google_blueprint( client_id=app.config.get('GOOGLE_ID'), client_secret=app.config.get('GOOGLE_SECRET'), scope=["profile", "email"]) twitter_blueprint = make_twitter_blueprint( api_key=app.config.get('TWITTER_API_KEY'), api_secret=app.config.get('TWITTER_API_SECRET')) facebook_blueprint = make_facebook_blueprint( client_id=app.config.get('FACEBOOK_APP_ID'), client_secret=app.config.get('FACEBOOK_APP_SECRET')) # setup SQLAlchemy backend github_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user) google_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user) twitter_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user, user_required=False) facebook_blueprint.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user) # create/login local user on successful OAuth login @oauth_authorized.connect_via(github_blueprint)
return render_template('user_posts.html', posts=posts, user=user) userauth = Blueprint('userauth', __name__) app.secret_key = app.config['GOOGLE_OAUTH_CLIENT_SECRET'] google_blueprint = make_google_blueprint( client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'], client_secret=app.secret_key, scope=app.config['GOOGLE_OAUTH_CLIENT_SCOPE'], offline=True ) google_blueprint.backend = SQLAlchemyBackend(UserAuth, db.session, user=current_user, user_required=False) app.register_blueprint(google_blueprint, url_prefix="/google_login") @userauth.route("/google_login") def google_login(): """redirect to Google to initiate oAuth2.0 dance""" if not google.authorized: return redirect(url_for("google.login")) resp = google.get("/oauth2/v2/userinfo") assert resp.ok, resp.text return resp.text
def create_app(config_name): from app.models import BlogPost, User, Role, OAuth from app.resources import Post, PostList, UserResource, UserList, Like app = Flask(__name__, instance_relative_config=True) app.config.from_object(app_config[config_name]) app.config.from_pyfile("config.py") app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["SECRET_KEY"] = "super-secret" db.init_app(app) # Setup Flask Migration migrate = Migrate(app, db) # Setup Flask restful API api = Api(app) api.add_resource(Post, "/posts/<int:post_id>") api.add_resource(PostList, "/posts") api.add_resource(UserResource, "/users/<int:user_id>") api.add_resource(UserList, "/users") api.add_resource(Like, "/posts/<int:post_id>/like") # Setup Flask-Security user_datastore = SQLAlchemyUserDatastore(db, User, Role) security = Security(app, user_datastore) login_manager = LoginManager(app) login_manager.login_view = "my_login" @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) google_blueprint = make_google_blueprint( client_id=app.config['GOOGLE_API_CLIENT_ID'], client_secret=app.config['GOOGLE_API_CLIENT_ID'], scope=["profile", "email"] ) google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) google_blueprint.backend.user_required = False app.register_blueprint(google_blueprint, url_prefix="/google_login") @app.route("/google") def google_login(): if not google.authorized: return redirect(url_for("google.login")) account_info = google.get("/oauth2/v2/userinfo") account_info_json = account_info.json() app.logger.info("User with email %s logged in successfully" % account_info_json['email']) user = current_user response = jsonify({ "status": "ok", "message": "User %s has been logged in successfully" % account_info_json['email'], "data": { "user": { "id": user.id, "email": user.email, "registration_completed": user.registration_completed(), "type": user.type.code, "phone": user.phone, "name": user.name, "occupation": user.occupation } } }) response.status_code = 200 return response @oauth_authorized.connect_via(google_blueprint) def google_logged_in(blueprint, token): if not token: app.logger.error("Failed to log in with Google.") return False account_info = blueprint.session.get("/oauth2/v2/userinfo") if not account_info.ok: app.logger.error("Failed to fetch user info from Google.") return False else: account_info_json = account_info.json() email = account_info_json["email"] query = User.query.filter_by(email=email) try: user = query.one() # If user is google user we log him in, if not we return False and redirect him to Facebook login page. if user.type == "facebook": app.logger.info("User with email %s trying to sign in using Google account" % (email)) response = jsonify({ "status": "error", "message": "The user with the same email has been registered with a Facebook account." " Please use Facebook to login!", "data": { "facebook_login_url": url_for("facebook_login"), "google_login_url": url_for("google_login"), } }) response.status_code = 200 return response except NoResultFound: # If no user with existing email found, we create new user, mark him as Google user user = User(email=email, type="google", active=True) db.session.add(user) db.session.commit() login_user(user) app.logger.info("User with email %s logged in successfully" % account_info_json['email']) user = current_user response = jsonify({ "status": "ok", "message": "User %s has been logged in successfully" % account_info_json['email'], "data": { "user": { "id": user.id, "email": user.email, "registration_completed": user.registration_completed(), "type": user.type.code, "phone": user.phone, "name": user.name, "occupation": user.occupation } } }) response.status_code = 200 return response facebook_blueprint = make_facebook_blueprint( client_id=app.config['FACEBOOK_API_CLIENT_ID'], client_secret=app.config['FACEBOOK_API_CLIENT_SECRETE'], scope=["public_profile", "email"] ) facebook_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) facebook_blueprint.backend.user_required = False app.register_blueprint(facebook_blueprint, url_prefix="/facebook_login") @app.route("/facebook") def facebook_login(): if not facebook.authorized: return redirect(url_for("facebook.login")) account_info = facebook.get("/me?fields=id,name,email") account_info_json = account_info.json() app.logger.info("User with email %s logged in successfully" % account_info_json['email']) user = current_user response = jsonify({ "status": "ok", "message": "User %s has been logged in successfully" % account_info_json['email'], "data": { "user": { "id": user.id, "email": user.email, "registration_completed": user.registration_completed(), "type": user.type.code, "phone": user.phone, "name": user.name, "occupation": user.occupation } } }) response.status_code = 200 return response @oauth_authorized.connect_via(facebook_blueprint) def facebook_logged_in(blueprint, token): if not token: app.logger.error("Failed to log in with Facebook.") return False account_info = blueprint.session.get("/me?fields=id,name,email") if not account_info.ok: app.logger.error("Failed to fetch user info from Facebook.") return False else: account_info_json = account_info.json() email = account_info_json["email"] query = User.query.filter_by(email=email) try: user = query.one() # If user is facebook user we log him in, if not we return False and return error response. if user.type == "google": app.logger.info("User with email %s trying to sign in using Facebook account" % (email)) response = jsonify({ "status": "error", "message": "The user with the same email has been registered with a Google account." " Please use Google to login!", "data": { "facebook_login_url": url_for("facebook_login"), "google_login_url": url_for("google_login"), } }) response.status_code = 200 return response except NoResultFound: # If no user with existing email found, we create new user, mark him as Facebook user user = User(email=email, type="facebook", active=True) db.session.add(user) db.session.commit() login_user(user) app.logger.info("User with email %s logged in successfully" % account_info_json['email']) user = current_user response = jsonify({ "status": "ok", "message": "User %s has been logged in successfully" % account_info_json['email'], "data": { "user": { "id": user.id, "email": user.email, "registration_completed": user.registration_completed(), "type": user.type.code, "phone": user.phone, "name": user.name, "occupation": user.occupation } } }) response.status_code = 200 return response # Views @app.route("/") @login_required def home(): posts = BlogPost.get_all() results = [] for post in posts: obj = { "id": post.id, "title": post.title, "content": post.content, "date_created": post.date_created, "date_modified": post.date_modified } results.append(obj) response = jsonify(results) response.status_code = 200 return response @app.route("/my_login") def my_login(): response = jsonify({ "status": "error", "message": "Login Required", "data": { "facebook_login_url": url_for("facebook_login"), "google_login_url": url_for("google_login"), } }) response.status_code = 403 return response @app.route("/logout") @login_required def logout(): logout_user() return redirect(url_for("home")) return app
from instance.settings import TWITTER_API_KEY, TWITTER_API_SECRET from winejournal.data_models.oauth import Oauth from winejournal.data_models.tastingnotes import TastingNote from winejournal.data_models.users import User from winejournal.data_models.wines import Wine from winejournal.extensions import db from winejournal.extensions import login_manager staticPages = Blueprint('static_pages', __name__, template_folder='templates') twitter_blueprint = make_twitter_blueprint( api_key=TWITTER_API_KEY, api_secret=TWITTER_API_SECRET) twitter_blueprint.backend = SQLAlchemyBackend( Oauth, db.session, user=current_user, user_required=False) google_blueprint = make_google_blueprint( client_id=GOOGLE_CLIENT_ID, client_secret=GOOGLE_CLIENT_SECRETS, scope=['profile', 'email']) google_blueprint.backend = SQLAlchemyBackend( Oauth, db.session, user=current_user, user_required=False) facebook_blueprint = make_facebook_blueprint( client_id=FACEBOOK_OAUTH_CLIENT_ID, client_secret=FACEBOOK_OAUTH_CLIENT_SECRET,
# Initialize Flask-Dance blueprints google_blueprint = make_google_blueprint( client_id=app.config.get('GOOGLE_CLIENT_ID'), client_secret=app.config.get('GOOGLE_CLIENT_SECRET'), scope=["profile", "email"], redirect_url="/token/google") facebook_blueprint = make_facebook_blueprint( client_id=app.config.get('FACEBOOK_APP_ID'), client_secret=app.config.get('FACEBOOK_APP_SECRET'), scope=["public_profile", "email"], redirect_url="/token/facebook") # Setup sqlalchemy backend for blueprints google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) facebook_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user) @oauth_authorized.connect_via(google_blueprint) def google_logged_in(blueprint, token): """Log in user on successful Google authorization.""" # If user doesn't have valid oauth token, flash error if not token: flash("Failed to log in {name}".format(name=blueprint.name)) return
from flask_dance.consumer import oauth_authorized, oauth_error from flask_dance.consumer.backend.sqla import SQLAlchemyBackend from flask_dance.contrib.facebook import make_facebook_blueprint from flask_dance.contrib.github import make_github_blueprint from flask_dance.contrib.twitter import make_twitter_blueprint from flask_login import current_user from project.utils.login import general_logged_in, general_error from project.models import OAuth, db facebook_blueprint = make_facebook_blueprint( backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False) ) twitter_blueprint = make_twitter_blueprint( backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False) ) github_blueprint = make_github_blueprint( backend=SQLAlchemyBackend(OAuth, db.session, user=current_user, user_required=False) ) @oauth_authorized.connect_via(twitter_blueprint) def twitter_logged_in(blueprint, token): return general_logged_in(blueprint, token, 'account/settings.json') @oauth_error.connect_via(twitter_blueprint) def twitter_error(blueprint, error, error_description=None, error_uri=None):
'binarne', 'soli', 'baze', 'kisline', 'kh', 'hs', 'vislice', } login_manager = LoginManager(app) login_manager.init_app(app) login_manager.login_view = 'login' login_manager.login_message = u"Za dostop do te strani se morate prijaviti!" login_manager.login_message_category = "error" fb.backend = SQLAlchemyBackend(models.OAuth, db.session, user=current_user) @login_manager.user_loader def load_user(user_id): return models.User.query.get(int(user_id)) @app.context_processor def utility_processor(): def its_type(obj): return type(obj) return dict(type=its_type)