Firebase:使用令牌登录 [英] Firebase: Sign in with a token
问题描述
我的目标是让用户登录主要由NodeJS制作的桌面应用程序
My goal is to keep a user signed in a desktop app made primarily with NodeJS
- 用户登录
- 存储某种令牌以供以后登录用户
- 用户重新打开应用程序时,请使用该令牌(如果有)登录用户
- 令牌可以过期/无效
当前,Firebase似乎依赖某种cookie.是否可以通过一种方法重新登录没有电子邮件/密码的用户?
Currently, it seems Firebase relies on cookies of some sort. Is there a way to sign in a user without their email/password again?
我目前正在尝试将Firebase身份验证用作我的Electron应用程序的一部分,在该应用程序中,我无法让Firebase身份验证代码成为通常可以访问浏览器级存储的渲染器进程的一部分.
I am currently trying to use Firebase authentication as part of my Electron app where I cannot have the Firebase authentication code be part of a renderer process which would normally have access to browser-level storage.
理想的情况是这样的:
const auth_token = await user.getIdToken();
firebase
.auth()
.signInWithCustomToken(auth_token) // But maybe some other method?
.then((user) => {
console.log(user);
})
您将如何在无法访问浏览器存储的NodeJS应用中执行此操作,从而使用户不需要连续登录?
How would you do this in a NodeJS app that has no access to browser storage such that the user does not need to continuously login?
引用此问题:针对Node.js客户端应用程序的持久Firebase用户
首先,我不希望与其他应用程序共享这些令牌.
fwiw, I don't wish to share these tokens with another application.
一个稍有不同的问题:Electron中的主要流程是否可以存储Firebase可以访问的cookie?
A slightly different question: Can the main process in Electron store cookies that Firebase could access?
最近阅读: https://github.com/firebase/firebase -js-sdk/issues/292
推荐答案
我对此的解决方案是:
- 通过电子邮件/密码(寿命约1年)获取刷新令牌
- 获取带有刷新令牌的id_token(短暂)
- 获取带有id_token的自定义令牌(短暂时间:〜1小时)
- 使用自定义令牌登录
- 在本地保存刷新令牌-永不共享
所以,像这样:
import Store from 'electron-store';
import firebase from 'firebase';
import * as request from 'request-promise';
const store = new Store({ name: 'config' });
function logout() {
const user = firebase.auth().currentUser;
store.delete('refresh_token');
if (user) {
return firebase.auth().signOut();
}
}
// https://firebase.google.com/docs/reference/rest/auth#section-create-email-password
function signup(email, password) {
return request
.post({
headers: { 'content-type': 'application/x-www-form-urlencoded' },
url: `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${firebase_config['apiKey']}`,
body: `email=${email}&password=${password}&returnSecureToken=true`,
json: true,
})
.then((res) => {
store.set({ refresh_token: res.refreshToken });
return login_with_id_token(res.idToken);
});
}
// Generates a refresh_token that we later use & save
async function login_with_email(email: string, password: string) {
const res = await request.post({
headers: { 'content-type': 'application/x-www-form-urlencoded' },
url: `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${firebase_config['apiKey']}`,
body: `email=${email}&password=${password}&returnSecureToken=true`,
json: true,
});
const refresh_token = res.refreshToken;
store.set({ refresh_token });
console.log(store.path);
return login_with_refresh_token(refresh_token);
}
/**
* Needed to acquire a refresh_token
* @param refresh_token string
*/
function get_id_token(refresh_token) {
return request.post({
headers: { 'content-type': 'application/x-www-form-urlencoded' },
url: `https://securetoken.googleapis.com/v1/token?key=${firebase_config['apiKey']}`,
body: `grant_type=refresh_token&refresh_token=${refresh_token}`,
json: true,
});
}
/**
* Generates a custom token we can use to sign in given an id_token
* @param id_token string
*/
function get_custom_token(id_token) {
return request.get({
url: `https://us-central1-${firebase_config['projectId']}.cloudfunctions.net/create_custom_token?id_token=${id_token}`,
json: true,
});
}
function login_with_id_token(id_token) {
if (id_token) {
return get_custom_token(id_token).then((token) => {
// console.log(`Retrieved custom token: ${custom_token}`);
return firebase.auth().signInWithCustomToken(token);
});
}
}
/**
* If token is null, it attempts to read it from disk otherwise
* it will use the one supplied to login
* @param token string || null
*/
async function login_with_refresh_token(token = null) {
let id_token = null;
let refresh_token = token;
if (!refresh_token) {
refresh_token = store.get('refresh_token');
store.get('refresh_token', null);
// console.log('Using a cached refresh token...');
}
if (refresh_token) {
const res = await get_id_token(refresh_token);
if (res) {
id_token = res['id_token'];
return login_with_id_token(id_token);
}
}
}
// Purposely attempt to login without a refresh_token in case it's on disk
function attempt_login() {
return login_with_refresh_token(null);
}
Firebase云功能:
Firebase cloud function:
exports.create_custom_token = functions.https.onRequest(async (req, res) => {
const id_token = req.query.id_token;
const user = await admin.auth().verifyIdToken(id_token);
if (user) {
const custom_token = await admin.auth().createCustomToken(user.uid);
res.setHeader('Content-Type', 'application/json');
res.status(200).send(custom_token);
} else {
res.sendStatus(500);
}
});
这篇关于Firebase:使用令牌登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!