From 4d1d23606631c95068c071039f808ebb13109553 Mon Sep 17 00:00:00 2001 From: Son NK Date: Fri, 28 Feb 2020 17:29:33 +0700 Subject: [PATCH] add POST /api/auth/google --- README.md | 14 ++++---- app/api/views/auth_login.py | 65 +++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0158eb65..4d51f2e8 100644 --- a/README.md +++ b/README.md @@ -745,13 +745,15 @@ Input: - device: device name. Used to create the API Key. Should be humanly readable so user can manage later on the "API Key" page. Output: Same output as for `/api/auth/login` endpoint -- name: user name, could be an empty string -- mfa_enabled: boolean -- mfa_key: only useful when user enables MFA. In this case, user needs to enter their OTP token in order to login. -- api_key: if MFA is not enabled, the `api key` is returned right away. -The `api_key` is used in all subsequent requests. It's empty if MFA is enabled. -If user hasn't enabled MFA, `mfa_key` is empty. + +#### POST /api/auth/google + +Input: +- google_token: Facebook access token +- device: device name. Used to create the API Key. Should be humanly readable so user can manage later on the "API Key" page. + +Output: Same output as for `/api/auth/login` endpoint #### GET /api/aliases diff --git a/app/api/views/auth_login.py b/app/api/views/auth_login.py index 9fb4fb88..cd29e918 100644 --- a/app/api/views/auth_login.py +++ b/app/api/views/auth_login.py @@ -1,22 +1,21 @@ -from flask import g +from flask import jsonify, request +import facebook +import google.oauth2.credentials +import googleapiclient.discovery from flask import jsonify, request from flask_cors import cross_origin from itsdangerous import Signer from app import email_utils -from app.api.base import api_bp, verify_api_key +from app.api.base import api_bp from app.config import ( - EMAIL_DOMAIN, - MAX_NB_EMAIL_FREE_PLAN, FLASK_SECRET, DISABLE_REGISTRATION, ) from app.email_utils import can_be_used_as_personal_email, email_already_used from app.extensions import db from app.log import LOG -from app.models import GenEmail, AliasUsedOn, User, ApiKey, SocialAuth -from app.utils import convert_to_id -import facebook +from app.models import User, ApiKey, SocialAuth @api_bp.route("/auth/login", methods=["POST"]) @@ -105,6 +104,58 @@ def auth_facebook(): return jsonify(**auth_payload(user, device)), 200 +@api_bp.route("/auth/google", methods=["POST"]) +@cross_origin() +def auth_google(): + """ + Authenticate user with Facebook + Input: + google_token: Google access token + device: to create an ApiKey associated with this device + Output: + 200 and user info containing: + { + name: "John Wick", + mfa_enabled: true, + mfa_key: "a long string", + api_key: "a long string" + } + + """ + data = request.get_json() + if not data: + return jsonify(error="request body cannot be empty"), 400 + + google_token = data.get("google_token") + device = data.get("device") + + cred = google.oauth2.credentials.Credentials(token=google_token) + + build = googleapiclient.discovery.build("oauth2", "v2", credentials=cred) + + user_info = build.userinfo().get().execute() + email = user_info.get("email") + + user = User.get_by(email=email) + + if not user: + if DISABLE_REGISTRATION: + return jsonify(error="registration is closed"), 400 + if not can_be_used_as_personal_email(email) or email_already_used(email): + return jsonify(error=f"cannot use {email} as personal inbox"), 400 + + LOG.d("create Google user with %s", user_info) + user = User.create(email=email.lower(), name="", activated=True) + db.session.commit() + email_utils.send_welcome_email(user) + + if not SocialAuth.get_by(user_id=user.id, social="google"): + SocialAuth.create(user_id=user.id, social="google") + db.session.commit() + + return jsonify(**auth_payload(user, device)), 200 + + def auth_payload(user, device) -> dict: ret = { "name": user.name,