本文最初发布在Okta开发人员博客上 。 感谢您支持使SitePoint成为可能的合作伙伴。
Electron是一个框架,可使用JavaScript,HTML和CSS等Web技术构建跨平台的桌面应用程序。 它是为GitHub的Atom编辑器创建的,此后得到了广泛的采用。 电子为我每天使用的多个应用程序提供动力:Slack,Kitematic和Visual Studio Code等。
Electron 2.0于2018年5月上旬发布,并对项目进行了更改以遵守严格的语义版本控制。 这对开发人员来说是个好消息,因为这意味着修补程序版本将更加稳定,并且新功能将仅在主要版本中提供。 当开放源代码项目正确使用语义版本控制时,最终用户不会经常看到破坏性的更改,并且往往会提高工作效率。
Electron 3.0于2018年9月18日发布,包含主要版本的颠簸和一些新功能。 有关更多信息,请参见Electron博客 。
使用Web技术开发桌面应用程序是一个吸引人的概念。 我认为Gerard Sans的这则推文很钉钉:
人们总是问什么是最好的框架。 他们应该问的是,他们需要使用哪种框架X才能生产什么技能? 这个问题通常是他们缺乏技能,没有哪个框架他们使用#angular #reactjs #vuejs #javascript ✨🚀 pic.twitter.com/8DWwM4PJoT
-ᐸGerardSans /ᐳ😉🇬🇧(@gerardsans) 2018年8月5日
你有网页开发技能吗? 大! 您具有使用Electron构建桌面应用程序所需的条件!
在本文中,我将向您展示如何使用TypeScript,AppAuth-JS和OpenID Connect(OIDC)创建Electron应用程序。 您将学习如何为用户添加身份验证和保护Electron应用程序。
什么是AppAuth?
AppAuth是一个旨在为本机应用程序创建客户端SDK的项目。 使用OIDC和OAuth 2.0,可以在您的应用中实现身份验证和授权。 它具有可用于iOS,macOS,Android和JavaScript环境的SDK。 AppAuth-JS是JavaScript客户端的SDK。 AppAuth还支持OAuth的PKCE扩展 ,以使公共客户端更加安全。
几乎每个应用程序都依赖于安全的身份管理系统。 对于正在构建Electron应用程序的大多数开发人员,在滚动自己的身份验证/授权或插入托管身份服务(如Okta)之间都需要做出决定。
使用Electron构建桌面应用
我将为您简化事情。 您将使用现有示例,而不是从头开始构建应用程序。 AppAuth-JS项目有两个示例,一个服务器端示例,其节点位于src / node_app / index.ts ,一个appauth-js-electron-sample 。 克隆电子示例开始。
git clone https://github.com/googlesamples/appauth-js-electron-sample.git okta-electron-example
在此项目中打开package.json
并进行以下更改。
"scripts": {
"compile": "tsc",
"watch": "tsc --watch",
"start": "npm run compile && npx electron .",
"dev": "npm run compile && npm run watch & npx electron ."
},
"files": [
"built/**"
"author": "rahulrav",
"license": "MIT",
"dependencies": {
"@openid/appauth": "^1.1.1",
"@types/react": "^16.3.17",
"@types/react-dom": "^16.0.6",
"material-design-lite": "^1.3.0"
},
"devDependencies": {
"electron": "^3.0.0",
"typescript": "^2.9.1"
}
}
这些更改不是必需的,但它们会使事情变得更容易。 “脚本”中的更改使得它可以在运行npm run dev
或npm start
之前进行编译。 您还需要将electron
依赖关系变为devDependency
并将TypeScript升级到最新版本。
导航到克隆目录,使用npm安装依赖项,然后运行该应用程序。
cd okta-electron-example
npm i
npm run dev
它应该启动该应用程序并显示一个登录链接。
如果您拥有Google帐户,请点击登录 ,然后登录 ,您将被重定向回您的应用程序。 您应该会看到您的头像和名称。
下图显示了如何使用OpenID Connect进行此授权流程。
此时,您可以看到正在通过Google进行身份验证。 在下一节中,我将向您展示如何添加PKCE支持以使该应用程序更安全,以及如何使用Okta代替Google。
为什么要使用Okta进行身份验证?
您可能会问:当使用Google身份验证时,为什么我应该使用Okta? 原因很简单。 如果您想管理应用程序的用户(并且不可避免),Okta可以实现。 使用Google,拥有Google帐户的任何人都可以登录,但是您无法撤消访问权限或更新用户的权限,因为您无法通过Google管理用户。 Okta使您可以管理用户,以及修改其属性和权限。 更好的是,您仍然可以使用Okta将Google用作社交登录机制!
在桌面应用程序中使用Okta与OIDC进行身份验证
Okta的目标是使身份管理比以往更加轻松,安全和可伸缩。 Okta是一项云服务,允许开发人员创建,编辑和安全地存储用户帐户和用户帐户数据,并将它们与一个或多个应用程序连接。 我们的API使您能够:
你准备好了吗? 立即注册一个永久免费的开发者帐户 ! 完成后,请完成以下步骤以创建本机OIDC应用程序。
- 登录到您在developer.okta.com上的开发者帐户。
- 导航到“ 应用程序” ,然后单击“ 添加应用程序” 。
- 选择本机 ,然后单击下一步 。
- 为应用程序命名(例如
My Electron App
),然后添加http://localhost:8000
作为登录重定向URI。 - 对于允许的授予类型,除了授权代码外,选择刷新令牌 。
- 单击完成 。
现在,您可以使用应用程序设置将使用Google更改为Okta。 修改flow.ts
以使用Okta应用程序的设置。
const openIdConnectUrl = 'https://{yourOktaDomain}/oauth2/default';
const clientId = '{yourClientId}';
const redirectUri = 'http://localhost:8000';
您还需要更新app.ts
以使用应用程序的/userinfo
端点。
let request =
new Request('https://{yourOktaDomain}/oauth2/default/v1/userinfo', {
headers: new Headers({'Authorization': `Bearer ${accessToken}`}),
method: 'GET',
cache: 'no-cache'
});
如果您重新启动应用程序并尝试登录,它将失败,因为您没有使用PKCE。 在启动的浏览器的地址栏中,您会看到类似以下的错误。
error=invalid_request&error_description=PKCE+code+challenge+is+required+when+the+token+endpoint+authentication+method+is+%27NONE%27.
将PKCE支持添加到您的桌面应用程序
PKCE(发音为“ pixy”)是OAuth 2.0的安全扩展,适用于移动(和桌面)客户端上的公共客户端。 它旨在防止在同一设备上运行的恶意应用程序拦截授权代码。
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| End Device (e.g., Smartphone) |
| |
| +-------------+ +----------+ | (6) Access Token +----------+
| |Legitimate | | Malicious|<--------------------| |
| |OAuth 2.0 App| | App |-------------------->| |
| +-------------+ +----------+ | (5) Authorization | |
| | ^ ^ | Grant | |
| | \ | | | |
| | \ (4) | | | |
| (1) | \ Authz| | | |
| Authz| \ Code | | | Authz |
| Request| \ | | | Server |
| | \ | | | |
| | \ | | | |
| v \ | | | |
| +----------------------------+ | | |
| | | | (3) Authz Code | |
| | Operating System/ |<--------------------| |
| | Browser |-------------------->| |
| | | | (2) Authz Request | |
| +----------------------------+ | +----------+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
PKCE工作组提供了一个很好的解释,我在下面进行了介绍。 您可以在官方RFC中阅读更多内容。
“为减轻这种攻击,PKCE使用了动态创建的密码随机密钥,称为“代码验证器”。 为每个授权请求创建一个唯一的代码验证器,并将其转换后的值(称为“代码挑战”)发送到授权服务器以获取授权代码。 然后,将获得的授权代码与“代码验证者”一起发送到令牌端点,服务器将其与先前接收的请求代码进行比较,以便它可以执行客户端对“代码验证者”的拥有证明。 这是缓解措施,因为攻击者不知道此一次性密钥,因为它是通过TLS发送的并且无法被截获。”
下图显示了PKCE如何与您的应用程序和Okta一起使用。
现在,您将PKCE添加到您的Electron应用程序中! 在flow.ts
,为PKCE添加一个challengePair
变量作为AuthFlow
类的成员变量。
private challengePair: { verifier: string, challenge: string };
在构造函数的末尾添加一行以初始化此变量。
this.challengePair = AuthService.getPKCEChallengePair();
创建pkce.ts
来定义AuthService
类。
const crypto = require('crypto');
export class AuthService {
static getPKCEChallengePair() {
let verifier = AuthService.base64URLEncode(crypto.randomBytes(32));
let challenge = AuthService.base64URLEncode(AuthService.sha256(verifier));
return {verifier, challenge};
}
static base64URLEncode(str: Buffer) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
static sha256(buffer: string) : Buffer {
return crypto.createHash('sha256').update(buffer).digest();
}
}
将此类的导入添加到flow.ts
:
import { AuthService } from './pkce';
在makeAuthorizationRequest()
方法中,在if (username) {}
逻辑之后,将代码质询和方法添加到extras
映射中。
// PKCE
extras['code_challenge'] = this.challengePair.challenge;
extras['code_challenge_method'] = 'S256';
在makeRequestTokenRequest()
,添加一个tokenRequestExtras
变量并将其发送到请求中。
let tokenRequestExtras = { code_verifier: this.challengePair.verifier };
// use the code to make the token request.
let request = new TokenRequest(
clientId,
redirectUri,
GRANT_TYPE_AUTHORIZATION_CODE,
code,
undefined,
tokenRequestExtras
);
进行这些更改之后,您应该可以登录。但是,当您单击USER INFO时 ,您将看不到用户的名称或头像。 通过查看 > 切换开发者工具打开Chrome开发者工具以了解原因。
要解决此问题,请在flow.ts
中将scope
变量flow.ts
为包括profile
。 在使用时,请添加offline_access
以便您的应用无需互联网即可正常运行。
const scope = 'openid profile offline_access';
刷新您的应用程序(在Mac上为Command + R,在Windows / Linux上为Ctrl + R),现在单击USER INFO时应会看到名称。
注意:我利用这些PKCE代码示例来完成所有这些工作。
在Okta中添加头像
您可能会注意到,用户信息端点未返回化身。 app.ts
的代码根据picture
属性设置头像。
private updateUi() {
this.handleSignIn.textContent = SIGN_OUT;
this.fetchUserInfo.style.display = '';
if (this.userInfo) {
this.userProfileImage.src = `${this.userInfo.picture}?sz=96`;
this.userName.textContent = this.userInfo.name;
this.showSnackBar(
{message: `Welcome ${this.userInfo.name}`, timeout: 4000});
this.userCard.style.display = '';
}
}
您可以在上面的代码中删除?sz=96
,因为此示例未使用它。
要向您的用户添加picture
属性,请登录Okta仪表板,然后导航至Users > Profile Editor 。 单击第一个“用户”并添加picture
属性。 点击保存 。
浏览回到配置文件编辑器,然后为您的Electron App单击映射 。 创建从user.picture
到picture
的映射,然后选择将映射应用于用户创建和更新。 单击“ 保存映射并立即应用更新” 。
现在转到“ 用户” >“ 人员” ,选择一个用户,导航至“ 个人资料”标签,然后点击“ 编辑” 。 在底部添加picture
的值。 例如,您可以使用我们的Okta Developer徽标的URL。
https://www.okta.com/sites/all/themes/Okta/images/logos/developer/Dev_Logo-02_Large.png
现在,如果您单击用户信息链接,则应该看到与您的用户关联的头像。
提示:如果要在生产中使用此图像,建议您为图片使用较小的图像(例如150×150尺寸)。 您还可以对图像进行base64编码 ,并将其值用于图片。
下面的屏幕截图显示了此应用,并为我的帐户添加了一些额外的修饰和base64图像值。
打包您的桌面应用以进行生产
要将此应用打包以进行生产发行,可以使用electronic-builder 。 使用npm安装电子生成器。
npm i -D electron-builder@20.28.4
在您的package.json
添加一个build
部分:
"build": {
"appId": "com.okta.developer.electron",
"productName": "Electron Awesomeness",
"mac": {
"category": "public.app-category.developer-tools"
}
}
然后添加pack
, dist
和postinstall
脚本。
"scripts": {
...
"pack": "npm run compile && electron-builder --dir",
"dist": "npm run compile && electron-builder",
"postinstall": "electron-builder install-app-deps"
}
要将您的应用打包以进行生产,请使用以下命令:
-
npm run pack
会生成package目录,而不会真正打包它。 这对于测试目的很有用。 -
npm run dist
将以可分发格式打包(例如dmg,Windows安装程序,deb软件包)。
注意:如果应用程序在打包后仍未启动,则可能是因为您未配置代码签名 。 要在构建macOS时禁用代码签名,请运行export CSC_IDENTITY_AUTO_DISCOVERY=false
。 如果您拥有Apple开发者帐户,请打开Xcode,转到“首选项” >“ 帐户”并确保您已登录,并下载了开发证书。
电子示例应用程序源代码
您可以在此处找到本文的源代码。
我做了一些小的调整(例如,优化导入,将双引号更改为单引号),但是没有什么大的调整。 要查看该项目与原始项目之间的区别, 请单击此处 。
了解有关Electron,AppAuth和OIDC的更多信息
你有它! 继续并使用您的网络技能来创建出色的桌面应用程序!
要了解有关Electron,AppAuth,React和OIDC的更多信息,请查看以下资源:
- 编写您的第一个电子应用程序
- 使用Kotlin在Android中构建基本的CRUD应用
- 使用React,GraphQL和用户身份验证构建运行状况跟踪应用
- 身份,声明和令牌– OpenID Connect入门,第1部分,共3部分
有问题吗? 请在下面发表评论, 在Twitter上对我进行ping操作 ,或在我们的开发者论坛上提问。
喜欢在这里学到的东西吗? 关注@oktadev , 在Facebook上像我们一样, 在LinkedIn 上关注我们,或在YouTube上观看我们的视频 。
变更日志:
- 2018年9月19日:更新为使用Electron 3.0.0和AppAuth 1.1.1。 请参阅okta-appauth-js-electron-example#1中的示例应用程序更改; 可以在okta.github.io#2327中查看对此职位的更改。
From: https://www.sitepoint.com/use-your-web-dev-skills-to-build-a-desktop-app-with-electron/