firebase auth не подключается к проекту appengine для входа в систему - PullRequest
0 голосов
/ 28 февраля 2020

Первоначально у меня было веб-приложение appengine с пользователями. Я хотел перенести аутентификацию в базу данных. Я следовал учебному пособию (https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine) и настроил основные компоненты c. Но когда я нажимаю кнопку входа в систему, он запрашивает у меня войти, но не входит в веб-приложение. В консоли Firebase я связал свой проект с appengine. Теперь пользователь находится в базе данных Firebase. Но я не хочу этого.

Аутентификация firebase не подключается автоматически к app-engine и не изменяет / не регистрирует пользователей? Какие дополнительные конфигурации мне нужно сделать. Проект представляет собой python бэкэнд-приложение.

My Orginal Google Login Handler

class GoogleSigninHandler(NoahSiteHandler):
""" Google sign-in & register redirect """

#@decorator.oauth_aware
@decorator.oauth_required
def get(self):
    try:
        user = None
        login = None
        is_new_account = False
        is_new_link = False


        http = decorator.http()
        google_user = plus_service.people().get(userId='me').execute(http=http)
        logging.info("user data: %s" % google_user)
        if google_user:
            google_id = google_user.get('id')
            displayName = google_user.get('displayName')
            email = None
            emails = google_user.get('emails', [])
            if len(emails) > 0:
                email = emails[0].get('value')
            username = google_user.get('name', {}).get('givenName') or google_user.get('displayName')
            if email and not username:
                username = email.split('@')[0]
            image_url = None
            image_data = google_user.get('image')
            if image_data:
                is_default_image = image_data.get('isDefault', True)
                if not is_default_image:
                    image_url = image_data.get('url')
                    if image_url:
                        image_url = image_url.replace('sz=50', 'sz=200')

            if google_id:
                profile_key = 'https://www.google.com/profiles/%s' % google_id

                login = NoahLogin.get_by_key_name(profile_key)
                if login and login.user:
                    user = login.user
                    logging.info('logging existing user in')
                else:
                    if not login:
                        logging.info('creating new login with key: %s' % profile_key)

                        is_new_link = True
                        login = NoahLogin(
                                    key_name=profile_key,
                                    provider='Google',
                                    email=email,
                                    preferredUsername=username,
                                    displayName=displayName,
                                    photo=image_url
                                )

                    if self.session.has_key('me'):
                        user = NoahUser.smart_get(self.session['me'])
                        if user:
                            login.user = user
                            logging.info('adding google link to noahuser: %s based on session cookie' % login.user.nick)
                            login.put()

                    if not user:
                        #Search for legacy user based on email
                        logging.info('searching for legacy user with email %s', email)

                        #then by email
                        if email:
                            legacy_matches = NoahUser.all().filter('email =', email).fetch(1)
                            if len(legacy_matches) > 0:
                                #legacy Google user
                                logging.info('linking google accout to user with email: %s' % email)
                                login.user = legacy_matches[0]
                                user = login.user

                    if not user:
                        logging.info('creating new user account from google')

                        is_new_account = True
                        is_new_link = True
                        source = None
                        ua = self.request.headers['User-Agent']
                        if ua.find('Android') != -1:
                            source = 'android'
                        elif ua.find('Darwin') != -1:
                            source = 'iphone'
                        else:
                            source = 'web'

                        user = NoahUser(
                                    source=source,
                                    email=email,
                                    nick=unique_username_from(username or displayName)
                        )
                        user.put()

                    login.user = user
                    login.put()
                    taskqueue.add(url='/task/avatar/fetch', params = {'login': login.key()})

        if user and is_new_account:
            Event.new_user(user)
            user.deferred_update(source='new_account')
            sync_user_with_campaign_monitor(user)

        if user:
            self.session['me'] = str(user.key())
            self.request.registry['current_user'] = user

        if is_new_account:
            exit_url = self.url_for('index', new_account='1')
        elif is_new_link:
            exit_url = self.url_for('my_settings')
        else:
            exit_url = self.url_for('index')

        logging.info('redirecting to: %s' % exit_url)
        self.redirect(exit_url)

    except client.AccessTokenRefreshError:
      self.redirect(self.url_for('signin_google'))

1 Ответ

1 голос
/ 03 марта 2020

У меня была похожая проблема. Пользователи уже были зарегистрированы в моем приложении appengine и пользовательской модели (изначально из webapp2). Затем я мог бы добавить аутентификацию Firebase и затем сопоставить учетные данные из Firebase с моей моделью пользователя. Ниже приведен мой шаблон входа, если он может вам помочь (он использует flask framework с python 3 runtime):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>FirebaseUI</title>

    <!-- The core Firebase JS SDK is always required and must be listed first -->
    <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-analytics.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-firestore.js"></script>

    <script>
        // Your web app's Firebase configuration
        var firebaseConfig = {
            apiKey: "0123456789apikey",
            authDomain: "myappname.firebaseapp.com",
            databaseURL: "https://myappname.firebaseio.com",
            projectId: "myappname",
            storageBucket: "myappname.appspot.com",
            messagingSenderId: "01234567890",
            appId: "1:01234567890:web:21ee025bb5fb02b11337",
            measurementId: "F-ZZ34N242F8"
        };
        // Initialize Firebase
        firebase.initializeApp(firebaseConfig);
        firebase.analytics();
    </script>

    <script src="https://cdn.firebase.com/libs/firebaseui/4.2.0/firebaseui.js"></script>
    <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/4.2.0/firebaseui.css"/>
    <script type="text/javascript">
        // FirebaseUI config.
        var uiConfig = {
            signInSuccessUrl: '/',
            signInOptions: [
                // Comment out any lines corresponding to providers you did not check in
                // the Firebase console.

                {
                    provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
                    signInMethod: firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD
                },

                firebase.auth.GoogleAuthProvider.PROVIDER_ID,
                //firebase.auth.EmailAuthProvider.PROVIDER_ID,
                //firebase.auth.FacebookAuthProvider.PROVIDER_ID,
                //firebase.auth.TwitterAuthProvider.PROVIDER_ID,
                //firebase.auth.GithubAuthProvider.PROVIDER_ID,
                //firebase.auth.PhoneAuthProvider.PROVIDER_ID

            ],
            // Terms of service url.
            tosUrl: 'https://www.example.com',

            privacyPolicyUrl: function () {
                window.location.assign('https://www.example.com');
            }
        };


        // Initialize the FirebaseUI Widget using Firebase.
        //var ui = new firebaseui.auth.AuthUI(firebase.auth());
        // The start method will wait until the DOM is loaded.
        //ui.start('#firebaseui-auth-container', uiConfig);


        window.addEventListener('load', function () {
            document.getElementById('sign-out').onclick = function () {
                firebase.auth().signOut();
            };

            firebase.auth().onAuthStateChanged(function (user) {
                // alert("statechanged")
                if (user) {
                    //alert("user logged in")

                    // User is signed in, so display the "sign out" button and login info.
                    document.getElementById('sign-out').hidden = false;
                    document.getElementById('login-info').hidden = false;
                    console.log(`Signed in as (${user.email})`);
                    user.getIdToken().then(function (token) {
                        // Add the token to the browser's cookies. The server will then be
                        // able to verify the token against the API.
                        // SECURITY NOTE: As cookies can easily be modified, only put the
                        // token (which is verified server-side) in a cookie; do not add other
                        // user information.
                        document.cookie = "token=" + token;
                    });
                } else {
                    // User is signed out.
                    // Initialize the FirebaseUI Widget using Firebase.
                    var ui = new firebaseui.auth.AuthUI(firebase.auth());
                    // Show the Firebase login button.
                    ui.start('#firebaseui-auth-container', uiConfig);
                    // Update the login state indicators.
                    document.getElementById('sign-out').hidden = true;
                    document.getElementById('login-info').hidden = true;
                    // Clear the token cookie.
                    document.cookie = "token=";
                }
            }, function (error) {
                console.log(error);
                alert('Unable to log in: ' + error)
            });
        });


    </script>
</head>
<body>
<!-- The surrounding HTML is left untouched by FirebaseUI.
     Your app may use that space for branding, controls and other customizations.-->
<h1>Welcome</h1>
<div id="firebaseui-auth-container"></div>
<button id="sign-out" hidden=true>Sign Out</button>
<div id="login-info" hidden=true>
    <h2>Login info:</h2>
    {% if user_data %}
        <dl>
            <dt>Name</dt>
            <dd>{{ user_data['name'] }}</dd>
            <dt>Email</dt>
            <dd>{{ user_data['email'] }}</dd>
        </dl>
    {% elif error_message %}
        <p>Error: {{ error_message }}</p>
    {% endif %}
</div>
</body>
</html>

Тогда бэкэнд с python довольно легко получить объект учетных данных пользователя «заявки» (который будет JSON объект), который содержит адрес электронной почты, который можно сопоставить с профилем пользователя, уже находящимся в моем хранилище:

from google.oauth2 import id_token as gid_token
from flask import Flask, render_template, request, redirect, g

@app.before_request
def before_request_func():
    id_token = request.cookies.get("token")
    system_info = None
    error_message = None
    claims = None
    if id_token:
        try:
            claims = gid_token.verify_firebase_token(
                id_token, firebase_request_adapter)
            g.friendly_id = claims.get('name', claims.get('email', 'Unknown'))
        except ValueError as exc:
            error_message = str(exc)
    g.error_message = error_message  # Make a list of errors
    g.system_info = system_info
    g.claims = claims

Теперь объект заявок доступен в любом обработчике запросов:

@app.route("/my-page.html")
def my_ads():
    if g.claims is None:
        return redirect(f"/login.html", code=302)
    else:
        claims = g.claims
        email = claims.get("email")
    ...

Если у вас все еще есть проблемы и вы хотите попробовать описанное выше, я мог бы создать пример проекта, открытого на GitHub или подобном.

...