-
-
Notifications
You must be signed in to change notification settings - Fork 158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Differentiate between sign up and sign in? #365
Comments
Hi, I was looking into this and didn't find a solution anywhere, so I came up with my own solution. Main thing is creating three endpoints that only save value to session and redirect to from flask import flash
from flask_security import current_user, login_user, url_for_security
from flask_dance.contrib.google import make_google_blueprint
from flask_dance.consumer import oauth_authorized, oauth_error
from flask_dance.consumer.storage.sqla import SQLAlchemyStorage
from flask import redirect, url_for, session
from app import db
from .models import OAuth
def create_module(application):
application.register_blueprint(blueprint, url_prefix="/oauth/")
application
blueprint = make_google_blueprint(
scope=["profile", "email"],
storage=SQLAlchemyStorage(OAuth, db.session, user=current_user),
)
@blueprint.route("/google/login")
def auth_google_login():
session["auth_type"] = "login"
return redirect(url_for("google.login"))
@blueprint.route("/google/register")
def auth_google_register():
session["auth_type"] = "register"
return redirect(url_for("google.login"))
@blueprint.route("/google/add")
def auth_google_add_to_account():
session["auth_type"] = "add"
return redirect(url_for("google.login"))
# create/login local user on successful OAuth login
@oauth_authorized.connect_via(blueprint)
def google_logged_in(blueprint, token):
auth_type = session.pop("auth_type", "login")
if not token:
flash("Failed to log in.", category="error")
return False
resp = blueprint.session.get("/oauth2/v1/userinfo")
if not resp.ok:
msg = "Failed to fetch user info."
flash(msg, category="error")
return False
info = resp.json()
email = info["email"]
user_id = info["id"]
name = info["name"]
oauth = OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id).first() # fmt: skip
if auth_type == "login":
if not oauth:
flash("not registered with Google, sorry")
return redirect(url_for_security("login"))
else:
login_user(oauth.user)
elif auth_type == "register":
if not oauth:
oauth = OAuth(
provider=blueprint.name,
provider_user_id=user_id,
token=token,
username=email,
)
# Create a new local user account for this user
from app.services import UserManager
user = UserManager.create_or_load_user(email=email, password="x", name=name)
# Associate the new local user account with the OAuth token
oauth.user = user
# Save and commit our database models
db.session.add_all([user, oauth])
db.session.commit()
# Log in the new local user account
login_user(user)
# flash("Successfully signed in.")
elif auth_type == "add":
if oauth and oauth.user == current_user:
flash("You already connected google account.", "error")
return redirect(url_for("MemberSettingView:index"))
elif oauth:
flash("You cannot use this google account.", "error")
return redirect(url_for("MemberSettingView:index"))
else:
oauth = OAuth(
provider=blueprint.name,
provider_user_id=user_id,
token=token,
username=email,
)
oauth.user = current_user
db.session.add(oauth)
db.session.commit()
flash("You can use Google to login to your account")
return redirect(url_for("MemberSettingView:index"))
# Disable Flask-Dance's default behavior for saving the OAuth token
return False
# notify on OAuth provider error
@oauth_error.connect_via(blueprint)
def google_error(blueprint, message, response):
msg = "OAuth error from {name}! message={message} response={response}".format(
name=blueprint.name, message=message, response=response
)
flash(msg, category="error") I can imagine this being implemented into blueprints directly - having three endpoints and three callbacks (or less based on config). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Probably an old issue but due to some legal aspects I might want to make a difference between sign up/register and sign in/log in.
Is there a way to e,g. pass a client or consumer reference in the request(s) to provider which later can be accessed in @oauth_authorized.connect_via() ? This to know if request was issued from sign up or a sign in. I want to avoid automatic creation of a new user in case sign in was requested from the client.
At the moment I trigger the process for both cases with the same URL with no parameters.
The text was updated successfully, but these errors were encountered: