在 firebase 实时数据库中存储没有用户特定安全规则的 firebase 用户身份验证令牌是否安全?
Is it safe to store a firebase user authentication token without user specific security rules in firebase realtime database?
我正在将 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 启动作为 React 应用程序的浏览器应用程序时调用云函数的地方:
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 来保护数据吗?
你的做法是错误的。您的函数应该 return 将令牌直接发送给调用客户端代码作为其输出。然后客户端可以使用它来登录。您绝对不希望存储不受保护的身份验证令牌。那将是一个安全问题。
我建议查看 documentation 中描述的模式。
我正在将 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 启动作为 React 应用程序的浏览器应用程序时调用云函数的地方:
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 来保护数据吗?
你的做法是错误的。您的函数应该 return 将令牌直接发送给调用客户端代码作为其输出。然后客户端可以使用它来登录。您绝对不希望存储不受保护的身份验证令牌。那将是一个安全问题。
我建议查看 documentation 中描述的模式。