Saturday, April 15, 2017

flask-dance: multiple auth-providers

Leave a Comment

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 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment