如何在电子应用程序中使用外部浏览器(chrome、firefox 等)实现 auth0 身份验证

Posted

技术标签:

【中文标题】如何在电子应用程序中使用外部浏览器(chrome、firefox 等)实现 auth0 身份验证【英文标题】:how implement auth0 authentication using external browser(chrome,firefox etc.) in electron application 【发布时间】:2019-10-31 17:02:52 【问题描述】:

我在电子应用程序中使用 auth0 身份验证。无论如何,我都没有使用电子应用程序的浏览器窗口。所以,我想在外部浏览器(chrome、Firefox 等)或安装的默认浏览器中打开我的 auth0 身份验证窗口。有什么办法吗?

【问题讨论】:

【参考方案1】:

您可以在这里使用一些电子功能。首先你需要在外部浏览器中使用this Electron api打开Auth0 auth窗口

然后您使用默认浏览器登录,并且必须在重定向 URL 中设置一个自定义协议,该协议使用 this Electron api 指向您的 React 应用程序,现在您的 Electron 应用程序中有令牌。

【讨论】:

谢谢,但这种方法不适用于 linux。我也需要linux支持。有什么解决方法吗? 什么部分?在默认浏览器中打开身份验证链接似乎可以正常工作 -> github.com/electron/electron/issues/16149 协议相同 -> github.com/electron/electron/issues/6440 @Donflopez,很好的答案。话虽如此,一旦我使用 Auth0 在浏览器中成功进行身份验证并确认使用深层链接打开应用程序,浏览器窗口仍然保持打开状态。你知道如何关闭之前由 Electron 应用触发的浏览器窗口吗? @AlexTamoykin 我认为你只能以一种 hacky 的方式做到这一点,例如,一个简单的方法是从电子应用程序运行命令以关闭你想要的选项卡 -> ***.com/questions/20441793/… 好电话,您知道如何从电子应用程序中选择关闭哪个标签吗?一旦你调用 shell.openExternal,看起来应用程序就会失去上下文【参考方案2】:

方法 1(无效)

我尝试了@Donflopez's answer 中描述的方法,结果成功了一半。

问题是我在我的应用程序中使用 Google Auth,它不支持重定向 url 中的自定义协议。 (Invalid parameter value for redirect_uri: Invalid scheme: my-custom-protocol://auth/handler)


方法 2(无效)

然后我的想法是使用这样的重定向 URI(使用 NodeJS 快速服务器接收数据):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 快递服务器):

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,在浏览器选项卡重定向到它之后),我在请求 url 中没有看到任何内容或看起来像凭据数据的标头。

如果有人知道如何将请求数据提取/转换为凭证数据,请告诉我! (同时,我使用下面稍微复杂的方法。)


方法 3(有效)

我的下一个想法(可行)是让我的 Electron 应用程序在外部浏览器中打开一个选项卡,指向与 Electron 应用程序相同的域,但指向一个特殊页面,然后启动 Google 登录弹出窗口对于网站:

require("electron").shell.openExternal(`$electronApp_domain/sign-in-helper`);

(如果您的 Electron 页面在本地提供 [例如。file:///],您可能需要添加本地快速服务器来提供外部浏览器选项卡的登录帮助页面 - 不确定 Google 是否签名-in 适用于file:/// 页面。)

然后该页面检索 Google id-token 和 access-token,如下所示:

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);

以及 Electron 应用中的接收代码:

const express = require("express");
const receiveTokensServer = express();
const receiveTokensPort = XXXX;
const receiveTokensServer_domainStr = `http://localhost:$receiveTokensPort`;

receiveTokensServer.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);
);
receiveTokensServer.listen(receiveTokensPort);

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“脚本”请求):@ 987654323@

【讨论】:

以上是关于如何在电子应用程序中使用外部浏览器(chrome、firefox 等)实现 auth0 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何从 PhoneGap 3.1 应用程序打开外部链接到 Safari/Chrome 浏览器?

从外部 url 打开已安装的 PWA

chrome怎么打开postman

如何使用 Chrome 浏览器在 ASP.Net 中停止将输入类型自动填充为密码

电子APP的FCM/GCM

在 chromebook/chrome 操作系统上注册 Android 应用程序的协议处理程序以打开外部链接?