Last active
October 29, 2017 09:36
-
-
Save singingwolfboy/eaea1fdc6c9a683a75feea4a27f7dc31 to your computer and use it in GitHub Desktop.
Creating local users on successful OAuth login with Flask-Dance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import flask | |
from flask import redirect, url_for, flash | |
from flask_security import current_user, login_user | |
from flask_dance.consumer import oauth_authorized, oauth_error | |
from flask_dance.consumer.backend.sqla import SQLAlchemyBackend | |
from flask_dance.contrib.github import make_github_blueprint | |
from sqlalchemy.orm.exc import NoResultFound | |
from myapp.models import db, OAuth, User | |
github_bp = make_github_blueprint( | |
scope=["repo"], | |
backend=SQLAlchemyBackend(OAuth, db.session, user=current_user) | |
) | |
# create/login local user on successful OAuth login | |
@oauth_authorized.connect_via(github_bp) | |
def github_logged_in(blueprint, token): | |
if not token: | |
flash("Failed to log in with GitHub.", category="error") | |
return | |
resp = blueprint.session.get("/user") | |
if not resp.ok: | |
msg = "Failed to fetch user info from GitHub." | |
flash(msg, category="error") | |
return | |
github_info = resp.json() | |
github_user_id = str(github_info["id"]) | |
# Find this OAuth token in the database, or create it | |
query = OAuth.query.filter_by( | |
provider=blueprint.name, | |
provider_user_id=github_user_id, | |
) | |
try: | |
oauth = query.one() | |
except NoResultFound: | |
github_user_login = str(github_info["login"]) | |
oauth = OAuth( | |
provider=blueprint.name, | |
provider_user_id=github_user_id, | |
provider_user_login=github_user_login, | |
token=token, | |
) | |
# Now, figure out what to do with this token. There are 2x2 options: | |
# user login state and token link state. | |
if current_user.is_anonymous: | |
if oauth.user: | |
# If the user is not logged in and the token is linked, | |
# log the user into the linked user account | |
login_user(oauth.user) | |
flash("Successfully signed in with GitHub.") | |
else: | |
# If the user is not logged in and the token is unlinked, | |
# create a new local user account and log that account in. | |
# This means that one person can make multiple accounts, but it's | |
# OK because they can merge those accounts later. | |
short_name = github_info["name"] or github_user_login | |
user = User( | |
# Remember that `email` can be None, if the user declines | |
# to publish their email on GitHub! | |
email=github_info["email"], | |
full_name=github_info["name"], | |
short_name=short_name, | |
) | |
oauth.user = user | |
db.session.add_all([user, oauth]) | |
db.session.commit() | |
login_user(user) | |
flash("Successfully signed in with GitHub.") | |
else: | |
if oauth.user: | |
# If the user is logged in and the token is linked, check if these | |
# accounts are the same! | |
if current_user != oauth.user: | |
# Account collision! Ask user if they want to merge accounts. | |
flask.session["oauth_id"] = oauth.id | |
url = url_for("oauth.merge", oauth_id=oauth.id) | |
return redirect(url) | |
else: | |
# If the user is logged in and the token is unlinked, | |
# link the token to the current user | |
oauth.user = current_user | |
db.session.add(oauth) | |
db.session.commit() | |
flash("Successfully linked GitHub account.") | |
# Indicate that the backend shouldn't manage creating the OAuth object | |
# in the database, since we've already done so! | |
return False | |
# notify on OAuth provider error | |
@oauth_error.connect_via(github_bp) | |
def github_error(blueprint, error, error_description=None, error_uri=None): | |
msg = ( | |
"OAuth error from GitHub! " | |
"error={error} description={description} uri={uri}" | |
).format( | |
error=error, | |
description=error_description, | |
uri=error_uri, | |
) | |
flash(msg, category="error") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment