I have successfully followed the examples in the documentation of Flask-Dance to add Oauth from GitHub, and manage the users with SQLAlchemy. However, I am unable to add more providers. I tried to simply add another blueprint for Twitter and registering it, but I get various errors when trying to login with Twitter. Also, I end up with lots of duplicated code, so this is not a good approach.
Is there a better way to add another provider?
import sys from flask import Flask, redirect, url_for, flash, render_template from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.exc import NoResultFound from flask_dance.contrib.github import make_github_blueprint, github from flask_dance.consumer.backend.sqla import OAuthConsumerMixin, SQLAlchemyBackend from flask_dance.consumer import oauth_authorized, oauth_error from flask_login import ( LoginManager, UserMixin, current_user, login_required, login_user, logout_user ) # setup Flask application app = Flask(__name__) app.secret_key = "supersekrit" blueprint = make_github_blueprint( client_id="my-key-here", client_secret="my-secret-here", ) app.register_blueprint(blueprint, url_prefix="/login") # setup database models app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///multi.db" db = SQLAlchemy() class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(256), unique=True) # ... other columns as needed class OAuth(db.Model, OAuthConsumerMixin): user_id = db.Column(db.Integer, db.ForeignKey(User.id)) user = db.relationship(User) # setup login manager login_manager = LoginManager() login_manager.login_view = 'github.login' @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 @oauth_authorized.connect_via(blueprint) def github_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("/user") if resp.ok: username = resp.json()["login"] query = User.query.filter_by(username=username) try: user = query.one() except NoResultFound: # create a user user = User(username=username) db.session.add(user) db.session.commit() login_user(user) flash("Successfully signed in with GitHub") else: msg = "Failed to fetch user info from {name}".format(name=blueprint.name) flash(msg, category="error") # notify on OAuth provider error @oauth_error.connect_via(blueprint) def github_error(blueprint, error, error_description=None, error_uri=None): msg = ( "OAuth error from {name}! " "error={error} description={description} uri={uri}" ).format( name=blueprint.name, error=error, description=error_description, uri=error_uri, ) flash(msg, category="error") @app.route("/logout") @login_required def logout(): logout_user() flash("You have logged out") return redirect(url_for("index")) @app.route("/") def index(): return render_template("home.html") # hook up extensions to app db.init_app(app) login_manager.init_app(app) if __name__ == "__main__": if "--setup" in sys.argv: with app.app_context(): db.create_all() db.session.commit() print("Database tables created") else: app.run(debug=True)
0 comments:
Post a Comment