【问题标题】:App Engine Firebase Authentication UI Widget IssueApp Engine Firebase 身份验证 UI 小部件问题
【发布时间】:2020-09-02 09:42:43
【问题描述】:

我已经在标准环境中使用 Python37 和 Flask 在 Google App Engine 上开发了一个应用程序。我有以下文件作为 index.html 进行身份验证。我已将 Firebase 身份验证应用程序配置为包括 Google、电子邮件和 Facebook 身份验证。但是,该小部件仅显示 Google 和电子邮件。 Firebase Authentication-UI 的其他实现均未返回可在 python main.py 应用程序中验证的 Token。

index.html - 我的真实 html 文件中有正确的 Firebase 配置值

<!doctype html>
<html>
<head>
  <title>Myapp</title>

  <link rel="stylesheet" href="/static/bulma.min.css">
  <script defer src="/static/all.js"></script>

  <script src="https://www.gstatic.com/firebasejs/5.8.4/firebase.js"></script>
    <script>
      // Initialize Firebase
      var config = {
          apiKey: "<API_KEY>",
          authDomain: "<PROJECT_ID>.firebaseapp.com",
          databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
          projectId: "<PROJECT_ID>",
          storageBucket: "<BUCKET>.appspot.com",
          messagingSenderId: "<MESSAGING_SENDER_ID>"
      };
      firebase.initializeApp(config);
    </script>
  <script>
    if (typeof firebase === 'undefined') {
      const msg = "Please paste the Firebase initialization snippet into index.html. See https://console.firebase.google.com > Overview > Add Firebase to your web app.";
      console.log(msg);
      alert(msg);
    }
  </script>
  <!-- [START gae_python37_auth_include_firebaseui] -->
  <script src="https://cdn.firebase.com/libs/firebaseui/2.6.2/firebaseui.js"></script>
  <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/2.6.2/firebaseui.css">
  <!-- [END gae_python37_auth_include_firebaseui] -->
  <script src="{{ url_for('static', filename='script.js') }}"></script>
  <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

</head>
<body>

  <br><br><br>
  <div class="title is-4 has-text-centered">
    <div>
        Welcome to Myapp
    </div>
  </div>
  <div class="title is-5 has-text-centered">Myapp</div>

<!-- [START gae_python37_auth_firebase_html] -->
<div id="firebaseui-auth-container"></div>

<button id="sign-out" hidden=true>Sing out</button>

<div id="login-info" hidden=true>

</div>
<!-- [END gae_python37_auth_firebase_html] -->

<!-- Footer Section -->

</body>
</html>

main.py

id_token = request.cookies.get("token")
claims = google.oauth2.id_token.verify_firebase_token(
     id_token, firebase_request_adapter)

请参阅下面我根据@Ajordat 提到的this documentation 所做的实现。我收到一个空的 id_token 错误 - 提供了非法 ID 令牌:无。 ID 令牌必须是非空字符串 enter image description here

这里是 index.html 页面

<!doctype html>
<html>
<head>
  <title>Datastore and Firebase Auth Example</title>

  <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
  <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />

  <script src="https://www.gstatic.com/firebasejs/5.8.4/firebase.js"></script>
    <script>
      // Initialize Firebase
      var config = {
          apiKey: "<API_KEY>",
          authDomain: "<PROJECT_ID>.firebaseapp.com",
          databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
          projectId: "<PROJECT_ID>",
          storageBucket: "<BUCKET>.appspot.com",
          messagingSenderId: "<MESSAGING_SENDER_ID>"
      };
      firebase.initializeApp(config);
    </script>


  <script>
  var uiConfig = {
    callbacks: {
      signInSuccessWithAuthResult: function(authResult, redirectUrl) {
        // User successfully signed in.
        // Return type determines whether we continue the redirect automatically
        // or whether we leave that to developer to handle.
        return true;
      },
      uiShown: function() {
        // The widget is rendered.
        // Hide the loader.
        document.getElementById('loader').style.display = 'none';
      }
    },
    // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
    signInFlow: 'popup',
    signInSuccessUrl: '/',
    signInOptions: [
      // Leave the lines as is for the providers you want to offer your users.
      firebase.auth.GoogleAuthProvider.PROVIDER_ID,
      firebase.auth.FacebookAuthProvider.PROVIDER_ID,
      firebase.auth.EmailAuthProvider.PROVIDER_ID
    ],
    // Terms of service url.
    tosUrl: '<your-tos-url>',
    // Privacy policy url.
    privacyPolicyUrl: '<your-privacy-policy-url>'
  };

  // 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);

  </script>

</head>
<body>

<h1>Datastore and Firebase Auth Example</h1>

<!-- [START gae_python37_auth_firebase_html] -->
<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>
      <dt>Last 10 visits</dt><dd>
    {% for time in times %}
          <p>{{ time['timestamp'] }}</p>
        {% endfor %} </dd>
    </dl>
  {% elif error_message %}
    <p>Error: {{ error_message }}</p>
  {% endif %}
</div>

User id :{{ uid }}
<br>
User: {{ user.email }}
<br>
Error: {{ error_message }}
<br><br><br>
{{ id_token }}

<!-- [END gae_python37_auth_firebase_html] -->
</body>
</html>

验证id_token的main.py代码

...
default_app = firebase_admin.initialize_app()

@app.route('/')
def root():
    # Verify Firebase auth.
    id_token = request.cookies.get("token")
    error_message = ''
    uid = None
    user = None

    # if id_token:
    try:
        decoded_token = auth.verify_id_token(id_token)
        uid = decoded_token['uid']
        user = auth.get_user(uid)
    except ValueError as exc:
        error_message = str(exc)

    return render_template(
        'index.html',
        uid=uid, user=user, error_message = error_message)

【问题讨论】:

  • 我无法理解您的工作流程,您是否遵循this documentation 或其他指南?如果是后者,我想知道是哪一个,以便进一步调查。如果您有更多与身份验证相关的代码,分享它可能会有所帮助。
  • 嗨@Ajordat,是的,我做到了。文档中使用 CDN 的实现会调出小部件,但登录成功后不会在浏览器上创建 id_token 以便可以在服务器端通过 python 对其进行验证。唯一返回 id_token 的小部件是上面的小部件(CDN - .../2.6.2/firebaseui.js)。但是,即使我在 Firebase 身份验证应用程序上启用了 Facebook 身份验证选项,它也没有提供。
  • 根据我在documentation 中看到的关于回调signInSuccessWithAuthResult 的内容,您可以从参数authResult 中检索令牌,因为它将具有this signature。您将负责将您想要的值发送到服务器。
  • 谢谢@Ajordat。有效。我同时使用了signInSuccessWithAuthResultonAuthStateChanged 来设置一个带有id_token 的cookie,然后我通过后端读取它。

标签: html python-3.x google-app-engine flask firebase-authentication


【解决方案1】:

解决方案是从authResult.user 获取令牌并将其设置为cookie,以便以后可以从服务器检索。见附件代码:

signInSuccessWithAuthResult: function(authResult, redirectUrl) {
    var user = authResult.user;
    var credential = authResult.credential;
    var isNewUser = authResult.additionalUserInfo.isNewUser;
    var providerId = authResult.additionalUserInfo.providerId;
    var operationType = authResult.operationType;
    if (user) {
        user.getIdToken().then(function (accessToken) {
            console.log("token retrieved: " + accessToken);
            document.cookie = "token=" + accessToken + "; samesite=Lax";
        });
    }
    return true;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-30
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    相关资源
    最近更新 更多