From 0e9f0b0682d43be79416d61dfc7a44bf477a33ec Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Wed, 8 Nov 2023 21:12:55 +0300 Subject: [PATCH] Feature/google oauth (#106) google oauth --------- Co-authored-by: Igor Lobanov --- auth/identity.py | 15 +++------------ auth/oauth.py | 21 ++++++++++++++++----- main.py | 3 --- requirements.txt | 2 +- resolvers/auth.py | 24 ++---------------------- settings.py | 2 +- 6 files changed, 23 insertions(+), 44 deletions(-) diff --git a/auth/identity.py b/auth/identity.py index 7f704eff..c82e0b7a 100644 --- a/auth/identity.py +++ b/auth/identity.py @@ -3,7 +3,6 @@ from hashlib import sha256 from jwt import DecodeError, ExpiredSignatureError from passlib.hash import bcrypt -from sqlalchemy import or_ from auth.jwtcodec import JWTCodec from auth.tokenstorage import TokenStorage @@ -11,7 +10,6 @@ from auth.tokenstorage import TokenStorage # from base.exceptions import InvalidPassword, InvalidToken from base.orm import local_session from orm import User -from validations.auth import AuthInput class Password: @@ -65,20 +63,13 @@ class Identity: return user @staticmethod - def oauth(inp: AuthInput) -> User: + def oauth(inp) -> User: with local_session() as session: - user = ( - session.query(User) - .filter(or_(User.oauth == inp["oauth"], User.email == inp["email"])) - .first() - ) + user = session.query(User).filter(User.email == inp["email"]).first() if not user: - user = User.create(**inp) - if not user.oauth: - user.oauth = inp["oauth"] + user = User.create(**inp, emailConfirmed=True) session.commit() - user = User(**user.dict()) return user @staticmethod diff --git a/auth/oauth.py b/auth/oauth.py index 02f56ff5..c85e22b7 100644 --- a/auth/oauth.py +++ b/auth/oauth.py @@ -33,16 +33,25 @@ oauth.register( oauth.register( name="google", - client_id=OAUTH_CLIENTS["GOOGLE"]["id"], - client_secret=OAUTH_CLIENTS["GOOGLE"]["key"], + # client_id=OAUTH_CLIENTS["GOOGLE"]["id"], + # client_secret=OAUTH_CLIENTS["GOOGLE"]["key"], + client_id="648983473866-2hd6v2eqqk6hhqabfhuqq2slb2fkfvve.apps.googleusercontent.com", + client_secret="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", server_metadata_url="https://accounts.google.com/.well-known/openid-configuration", client_kwargs={"scope": "openid email profile"}, + authorize_state="test", ) async def google_profile(client, request, token): - profile = await client.parse_id_token(request, token) - profile["id"] = profile["sub"] + userinfo = token["userinfo"] + + profile = {"name": userinfo["name"], "email": userinfo["email"], "id": userinfo["sub"]} + + if userinfo["picture"]: + userpic = userinfo["picture"].replace("=s96", "=s600") + profile["userpic"] = userpic + return profile @@ -67,7 +76,8 @@ async def oauth_login(request): provider = request.path_params["provider"] request.session["provider"] = provider client = oauth.create_client(provider) - redirect_uri = "https://v2.discours.io/oauth-authorize" + # redirect_uri = "http://v2.discours.io/oauth-authorize" + redirect_uri = "http://localhost:8080/oauth-authorize" return await client.authorize_redirect(request, redirect_uri) @@ -82,6 +92,7 @@ async def oauth_authorize(request): "oauth": user_oauth_info, "email": profile["email"], "username": profile["name"], + "userpic": profile["userpic"], } user = Identity.oauth(user_input) session_token = await TokenStorage.create_session(user) diff --git a/main.py b/main.py index eb21b15c..27cac2cc 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,6 @@ from auth.oauth import oauth_authorize, oauth_login from base.redis import redis from base.resolvers import resolvers from orm import init_tables -from resolvers.auth import confirm_email_handler from resolvers.upload import upload_handler from services.main import storages_init from services.notifications.notification_service import notification_service @@ -71,10 +70,8 @@ async def shutdown(): routes = [ - # Route("/messages", endpoint=sse_messages), Route("/oauth/{provider}", endpoint=oauth_login), Route("/oauth-authorize", endpoint=oauth_authorize), - Route("/confirm/{token}", endpoint=confirm_email_handler), Route("/upload", endpoint=upload_handler, methods=["POST"]), Route("/subscribe/{user_id}", endpoint=sse_subscribe_handler), ] diff --git a/requirements.txt b/requirements.txt index af3eee5f..6ab7bcef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ aioredis~=2.0.1 alembic==1.11.3 ariadne>=0.17.0 asyncio~=3.4.3 -authlib>=1.1.0 +authlib==1.2.1 bcrypt>=4.0.0 beautifulsoup4~=4.11.1 boto3~=1.28.2 diff --git a/resolvers/auth.py b/resolvers/auth.py index 4900e6c0..ed754044 100644 --- a/resolvers/auth.py +++ b/resolvers/auth.py @@ -5,7 +5,6 @@ from datetime import datetime, timezone from urllib.parse import quote_plus from graphql.type import GraphQLResolveInfo -from starlette.responses import RedirectResponse from transliterate import translit from auth.authenticate import login_required @@ -14,17 +13,11 @@ from auth.email import send_auth_email from auth.identity import Identity, Password from auth.jwtcodec import JWTCodec from auth.tokenstorage import TokenStorage -from base.exceptions import ( - BaseHttpException, - InvalidPassword, - InvalidToken, - ObjectNotExist, - Unauthorized, -) +from base.exceptions import InvalidPassword, InvalidToken, ObjectNotExist, Unauthorized from base.orm import local_session from base.resolvers import mutation, query from orm import Role, User -from settings import FRONTEND_URL, SESSION_TOKEN_HEADER +from settings import SESSION_TOKEN_HEADER @mutation.field("getSession") @@ -64,19 +57,6 @@ async def confirm_email(_, info, token): return {"error": "email is not confirmed"} -async def confirm_email_handler(request): - token = request.path_params["token"] # one time - request.session["token"] = token - res = await confirm_email(None, {}, token) - print("[resolvers.auth] confirm_email request: %r" % request) - if "error" in res: - raise BaseHttpException(res["error"]) - else: - response = RedirectResponse(url=FRONTEND_URL) - response.set_cookie("token", res["token"]) # session token - return response - - def create_user(user_dict): user = User(**user_dict) with local_session() as session: diff --git a/settings.py b/settings.py index f3da9952..89739c80 100644 --- a/settings.py +++ b/settings.py @@ -23,7 +23,7 @@ for provider in OAUTH_PROVIDERS: "id": environ.get(provider + "_OAUTH_ID"), "key": environ.get(provider + "_OAUTH_KEY"), } -FRONTEND_URL = environ.get("FRONTEND_URL") or "http://localhost:3000" +FRONTEND_URL = environ.get("FRONTEND_URL") or "https://localhost:3000" SHOUTS_REPO = "content" SESSION_TOKEN_HEADER = "Authorization"