firebase - 创建 Firebase CustomToken 的 Javascript 函数
问题描述
我正在为 Firebase 创建一个自定义 TamperMonkey 脚本,以便在我的网站上进行一些本地测试插入给定 FireBase 身份验证用户的 UID 我为它创建了一个customToken。
这是我当前的代码
// ==UserScript==
// @name my-name
// @namespace my-namespace
// @version 1.0
// @author Myself
// @match XXXX-my-website-XXXX
// @require https://www.gstatic.com/firebasejs/6.6.2/firebase-app.js
// @require https://www.gstatic.com/firebasejs/6.6.2/firebase-auth.js
// @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js
// @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js
// @grant none
// ==/UserScript==
(function() {
function generateCustomToken(uid) {
if(typeof CryptoJS === undefined) {
alert("CryptoJS not found");
return;
}
// https://console.firebase.google.com/project/my-project-id/settings/serviceaccounts/adminsdk
var serviceAccount = { ... content of json service account file ... };
// https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_a_third-party_jwt_library
var header = {
"alg": "RS256",
"typ": "JWT"
};
var seconds = Math.trunc(new Date().getTime() / 1000);
var payload = {
iss : serviceAccount.client_email,
sub : serviceAccount.client_email,
aud : "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
iat : seconds,
exp : seconds + (60*60), // Maximum expiration time is one hour
uid : uid,
claims : {
premium_account : false
}
};
// https://github.com/firebase/php-jwt/blob/master/src/JWT.php#L156
var segments = [];
segments.push(base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(header))));
segments.push(base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(payload))));
var signingInput = segments.join(".");
var secret = serviceAccount.private_key
.replace('-----END PRIVATE KEY-----', '') // remove head
.replace('-----BEGIN PRIVATE KEY-----', '') // remove tail
.replace(/\n/g, ''); // remove all new-line chars
segments.push(base64url(CryptoJS.HmacSHA256(signingInput, secret)));
return segments.join(".");
}
/**
* https://codepen.io/jpetitcolas/pen/zxGxKN
*/
function base64url(source) {
// Encode in classical base64
var encodedSource = CryptoJS.enc.Base64.stringify(source);
// Remove padding equal characters
encodedSource = encodedSource.replace(/=+$/, '');
// Replace characters according to base64url specifications
encodedSource = encodedSource.replace(/\+/g, '-');
encodedSource = encodedSource.replace(/\//g, '_');
return encodedSource;
}
function firebaseLogin(customToken) {
// FIXME omitted code, firebase initialize
firebase
.auth()
.signInWithCustomToken(customToken)
.then(function(response) {
alert("Success signInWithCustomToken");
})
.catch(function(error) {
alert("signInWithCustomToken ERROR\n" + error.code + "\n" + error.message);
});
}
})();
我遵循了我找到的不同示例(我在代码中链接了它们)和使用自定义客户端的官方文档。
我多次阅读代码,一切似乎都很好,但是对于给定的错误,我认为我错过了一些非常简单的东西,在生成 jwt 令牌时我无法看到。
POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=xxx-my-api-key-xxx
{"token":"xxx-generated-custom-token-xxx","returnSecureToken":true}
HTTP RESPONSE 400
{
"error": {
"code": 400,
"message": "INVALID_CUSTOM_TOKEN",
"errors": [
{
"message": "INVALID_CUSTOM_TOKEN",
"domain": "global",
"reason": "invalid"
}
]
}
}
作为 TamperMonkey,这意味着直接在浏览器中运行,没有可用的 Node 环境或其他环境,这就是为什么我使用“原始”库而不是更集成的库的原因。
您在生成 jwt 令牌时是否看到任何错误?
解决方案
使用jsrsasign解决(它是https://jwt.io/网站建议的 JS 库之一)。我仍然不知道问题出在哪里,我认为与解析密钥有关。大多数代码现在由库管理,因此流程正常工作。
这是与令牌生成相关的更新代码:
添加到脚本标题:
// @require https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.12/jsrsasign-all-min.js
以及创建jwt的功能
var serviceAccount = { ... content of json service account file ... };
// https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_a_third-party_jwt_library
var header = {
"alg": "RS256",
"typ": "JWT"
};
var payload = {
iss : serviceAccount.client_email,
sub : serviceAccount.client_email,
aud : "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
iat : KJUR.jws.IntDate.get('now'),
exp : KJUR.jws.IntDate.get('now + 1hour'),
uid : uid
};
// https://github.com/kjur/jsrsasign/wiki/Tutorial-for-JWT-generation
var sHeader = JSON.stringify(header);
var sPayload = JSON.stringify(payload);
var prvKey = KEYUTIL.getKey(serviceAccount.private_key);
var sJWT = KJUR.jws.JWS.sign("RS256", sHeader, sPayload, prvKey);
return sJWT;
推荐阅读
- python-3.x - 如何让 aiohttp-swagger 识别 GET 查询变量?
- python - CodingBat Python 预热2 front_times
- javascript - React JS:将语音反应到文本识别
- angular - 在 ngFor 中插值标签属性值总是得到“得到插值({{}}),其中表达式是预期的”错误
- javascript - 带有图像剪辑的预加载器动画
- android - 如何在一个按钮内放置多个文本?
- django - 无法通过 Postman 在 Django oauth 工具包客户端凭据授予中获取访问令牌
- postgresql - 没有函数匹配给定的名称和参数类型(PostgreSQL 10.3 -CentOs 7.4)
- jquery - Jquery查找和替换内容的问题
- jquery - 使用 .each Jquery 将类添加到复选框