我正在电子应用程序中使用auth0身份验证。我无论如何都不使用电子应用程序的浏览器窗口。因此,我想在外部浏览器(chrome,Firefox等)或已安装的默认浏览器中打开auth0身份验证窗口。有什么办法吗?
答案 0 :(得分:2)
您可以在此处使用一些电子功能。首先,您需要使用this Electron api
在外部浏览器中打开Auth0身份验证窗口然后,您使用默认浏览器登录,并且必须在重定向URL中设置一个自定义协议,该协议使用this Electron api指向您的react应用,现在您的Electron应用中已经有令牌。
答案 1 :(得分:0)
我尝试了@Donflopez's answer中描述的方法,但到那里却只有一半。
问题是我正在为我的应用程序使用Google Auth,并且它在重定向URL中不支持自定义协议。 (Invalid parameter value for redirect_uri: Invalid scheme: my-custom-protocol://auth/handler
)
然后我的想法是使用这样的重定向URI(使用NodeJS express服务器接收数据):http://localhost:XXXX/auth/handler
登录标签的打开代码:
// not sure if this is the correct url to try, but it's what was opened when firebase.auth().signInWithRedirect() was called
require("electron").shell.openExternal(
`https://${projectID}.firebaseapp.com/__/auth/handler`
+ `apiKey=${apiKey}&appName=%5BDEFAULT%5D&authType=signInViaRedirect`
+ `&providerId=google.com&scopes=profile&v=7.7.0`
+ `&redirectUrl=http%3A%2F%2Flocalhost%3A${oauthPort}%2Fauth%2Fhandler`);
OAuth数据接收器(NodeJS Express服务器):
const express = require("express");
const oauthPort = XXXX;
const redirectServer = express();
redirectServer.get("/auth/handler", (req, res)=>{
debugger;
// I inspected the request data with debugger, but found nothing useful!
});
但是,我无法正常工作。虽然我可以设置一个NodeJS Express服务器来尝试接收数据,但是当实际请求进入时(对于localhost:XXXX/auth/handler
,在浏览器选项卡重定向到它之后),我在请求中没有看到任何内容网址或看起来像凭证数据的标头。
如果有人弄清楚如何将请求数据提取/转换为凭证数据,请告诉我! (同时,我在下面使用稍微复杂一些的方法。)
我的下一个想法(可行)是让我的Electron应用程序在外部浏览器中打开一个选项卡,指向与Electron应用程序相同的域,但是指向一个特殊的页面,该页面随后将启动Google登录弹出窗口用于网站:
require("electron").shell.openExternal(`${electronApp_domain}/sign-in-helper`);
(如果您的电子页面是在本地提供的,例如[file:///
],则可能需要添加本地快递服务器来为“外部浏览器”选项卡提供登录帮助页面-不确定是否Google登录可以在file:///
页上进行。)
然后该页面检索Google id令牌和访问令牌,如下所示:
const firebase = require("firebase");
firebase.auth().signInWithPopup(provider).then(result=>{
const idToken = result.credential.idToken;
const accessToken = result.credential.accessToken;
// You now have the id-token and access-token.
// Either one is sufficient to sign-in your Electron app, just need to transfer it.
TransferTokensToElectronApp(idToken, accessToken);
});
为了将其转移到Electron,我这样做:
const desktopApp_receiveTokensPort = XXXX;
function TransferTokensToElectronApp(idToken, accessToken) {
const script = document.createElement("script");
script.src = `http://localhost:${desktopApp_receiveTokensPort}/receive-tokens/?idToken=${idToken}&accessToken=${accessToken}`;
document.head.appendChild(script);
// after 1s, remove the script element, and close the page
setTimeout(()=>{
script.remove();
window.close();
}, 1000);
}
以及电子应用程序中的接收代码:
const express = require("express");
const receiveTokensServer = express();
const receiveTokensPort = XXXX;
const receiveTokensServer_domainStr = `http://localhost:${receiveWebSignInPort}`;
receiveWebSignInServer.get("/receive-tokens", (req, res)=>{
const url = new URL(`${receiveTokensServer_domainStr}/${req.url}`);
const idToken = url.searchParams.get("idToken");
const accessToken = url.searchParams.get("accessToken");
console.log("Received sign-in data from web helper:", {idToken, accessToken});
SendTokensToRenderer(idToken, accessToken);
});
receiveWebSignInServer.listen(receiveWebSignInPort);
SendTokensToFrontEnd
函数的实现取决于您在应用程序中执行通信的方式,但以使用Electron的ipc system为例:
function SendTokensToRenderer(idToken, accessToken) {
browserWindow.webContents.send("token-transfer-channel", {idToken, accessToken});
}
最后,要在渲染器/前端中接收这些令牌,并使用其登录Firebase:
const {ipcRenderer} = require("electron");
const firebase = require("firebase");
ipcRenderer.on("token-transfer-channel", (event, data)=>{
const cred = firebase.auth.GoogleAuthProvider.credential(data.idToken, data.accessToken);
firebase.auth().signInWithCredential(cred);
});
编辑:此后不久便找到了一个教程,该教程使用了类似的方法(但它是通过共享数据库而不是localhost
“脚本”请求将凭据转移到前端的) :https://pragli.com/blog/how-to-authenticate-with-google-in-electron