【发布时间】: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。有效。我同时使用了
signInSuccessWithAuthResult和onAuthStateChanged来设置一个带有id_token 的cookie,然后我通过后端读取它。
标签: html python-3.x google-app-engine flask firebase-authentication