【问题标题】:Is it safe to store a firebase user authentication token without user specific security rules in firebase realtime database?在firebase实时数据库中存储没有用户特定安全规则的firebase用户身份验证令牌是否安全?
【发布时间】:2021-12-31 13:43:34
【问题描述】:

我正在将 firebase Google OAuth 添加到我的 Electron 应用程序中 - 我已按照本教程进行操作:https://pragli.com/blog/how-to-authenticate-with-google-in-electron/

一般的想法是启动 Electron 应用程序,然后单击“使用 google 登录”,创建一个 UUID,写入使用此 UUID 索引的 firebase 实时数据库条目,并监听对此条目的更改。然后启动浏览器并在 URL 参数中传递 UUID。当页面加载时,调用 firebase 云函数(从浏览器应用程序)并将 UUID 传递给它。在云函数内部,可以引用数据库条目并将身份验证令牌写入数据库。

这是我在 Electron 应用中创建数据库引用的地方:

function createOAuthDatabaseEntry(
    auth: Auth,
    database: Database,
    electronAuthUuid: string,
): DatabaseReference | undefined {
    if (auth.currentUser) { // at this point in time the currentUser is null because they have not logged in
        const OAuthDatabaseRef = ref(
            database,
            `ot-auth-codes/${auth.currentUser?.uid}/${electronAuthUuid}`,
        );
        return OAuthDatabaseRef;
    }
}

然后监听变化:

function listenForBrowserSignIn(
    auth: Auth,
    OAuthDatabaseRef: DatabaseReference,
): Promise<{
    token: string;
    unsubscribeFromOAuthDatabaseChanges: Unsubscribe;
}> {
    return new Promise(resolve => {
        const unsubscribeFromOAuthDatabaseChanges = onValue(
            OAuthDatabaseRef,
            snapshot => {
                const token = snapshot.val();
                resolve({ token, unsubscribeFromOAuthDatabaseChanges });
            },
        );
    });
}

这是我的云功能代码:

exports.createAuthToken = functions.https.onCall(async (data, context) => {
    if (!context.auth) return { status: 'error', code: 401, message: 'Not signed in' };

    const decodedToken = await admin.auth().verifyIdToken(data.token);
    const authToken = await admin.auth().createCustomToken(decodedToken.uid);

    try {
        await admin
            .database()
            .ref(`ot-auth-codes/${context.auth.uid}/${data.code}`)
            .set(authToken);
        functions.logger.info('-------------> data sucessfully written to database')
    } catch (error) {
        functions.logger.error('-------------> error writing to database')
    }
});

我的问题是我正在尝试向数据库添加安全规则。到目前为止,我已经添加了firebase docs 中建议的这些:

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

这是当 Electron 启动浏览器应用程序时调用云函数的地方,它是一个反应应用程序:

function SignIn() {
    useEffect(() => {
        (async () => {
            try {
                const app = initializeApp(firebaseConfig);
                const functions = getFunctions(app);
                const provider = new GoogleAuthProvider();
                const auth = getAuth();
                const result = await getRedirectResult(auth)
                if (!result) {
                    signInWithRedirect(auth, provider)
                } else {
                    if (!result.user) {
                        return
                    }

                    const params = new URLSearchParams(window.location.search)
                    const token = await result.user.getIdToken()
                    const code = params.get("ot-auth-code")
                    const data = { token, code };
                    const createAuthToken = httpsCallable(functions, 'createAuthToken');
                    await createAuthToken(data)
                }
            } catch (error) {
                console.error('ERROR ----------------------->', error);
            }
        })()
    }, [])

我的问题是我不能使用这些特定规则来保护数据,因为在第一次创建对数据库的引用时,用户没有登录,因此 firebase 用户 uid 不可用。

我的问题是,为这个用例删除用户特定的数据库规则是否安全,或者我可以使用其他东西来代替 uid 来保护数据?

【问题讨论】:

  • 存储身份验证令牌是否安全(您的问题中不需要更多详细信息/条件)?没有

标签: javascript firebase-realtime-database firebase-authentication google-cloud-functions firebase-admin


【解决方案1】:

你做错了。您的函数应将令牌作为其输出直接返回给调用客户端代码。然后客户端可以使用它来登录。您绝对不想存储不受保护的身份验证令牌。那将是一个安全问题。

我建议查看documentation 中描述的模式。

【讨论】:

  • 嗨@Doug Stevenson,好的,谢谢 - 所以你会建议教程中的实现是错误的,不应该按照它建议的方式开发?作者似乎认为它是安全的,我只是想保护数据库,因为我不断收到通知说它将很快退出测试模式。
  • 不,文档告诉你的和我告诉你的一样——将令牌直接返回给客户端应用程序。不要将其保存在数据库中,绝对不是未受保护的数据库。
猜你喜欢
  • 1970-01-01
  • 2020-06-23
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 2019-01-20
  • 1970-01-01
  • 2021-07-05
相关资源
最近更新 更多