@spryteam/nativescript-oauth2
为 NativeScript 提供的 OAuth 2.0 通用授权插件,无需安装第三方本地库
npm i --save @spryteam/nativescript-oauth2

NativeScript OAuth 2 插件

Build Status NPM version Downloads Twitter Follow

用于在 NativeScript 应用程序中与 OAuth 2.0 交互的库,它提供了与支持 OAuth 2.0 协议的 OAuth 提供商(如 Microsoft、Facebook 和 Google)的简化直接客户端访问,不仅限于任何登录提供商,甚至允许您连接自己的。这个库不使用任何本地库,仅依赖于内置的内容——使其非常轻量级。

注意: 这是旧版 nativescript-oauth 插件 的新版本

NativeScript OAuth 2

已针对 Microsoft、Facebook 和 Google 提供商进行测试。更多提供商即将推出。感谢所有为旧插件提供提供商的人——请为此插件也做同样的事情。

简介

一些提供商是 OpenId 认证的(Google、Microsoft),因此它们在这方面更加安全,因为它们不必在客户端存储客户端密钥(这总是可能被足够聪明的人攻破,这些人足以进入您的应用程序)。Google 不允许传递客户端密钥,并要求使用应用程序外的浏览器进行身份验证。此插件支持需要此方法的任何提供商,但必须执行一些额外的配置步骤才能使此功能正常工作,更多内容见下文。

Facebook 不支持 OpenId,并使用应用程序内 WebView 实现的身份验证过程。因此,虽然这需要较少的配置,但将客户端密钥保留在应用程序中存在轻微的安全风险。如果您有严格的安全要求,您必须通过使用您的后端作为此插件和 Facebook 身份验证服务器之间的代理来实现 Facebook 登录。

先决条件

Office 365 / Microsoft

要使用您的 Office 365 账户进行登录,您应该有一个 Office 365 账户管理员账户。如果您还没有,您可以在这里获取免费试用。

请关注我的 YouTube 频道,了解如何使用插件设置 Facebook 的视频。

在此处注册您的移动应用程序 这里。这将要求您使用 Office 365 账户登录。然后,您可以点击大型的 "添加应用程序" 按钮,按照那里列出的步骤进行操作,首先是给您的应用程序命名。在应用程序创建屏幕上,您需要做三件事

  1. 点击 "添加平台" 按钮,并选择 "移动应用程序"
  2. 从 "移动应用程序" 部分复制 "客户端 ID" GUID。
  3. 在底部点击 "保存"。

Microsoft 登录可以使用应用程序内 WebView 方法,在这种情况下,您可以设置 redirectUri 配置属性为 urn:ietf:wg:oauth:2.0:oob。或者,它可以使用更安全的方法,无需客户端密钥,但需要注册自定义 URL 方案(见下文)。

Facebook 账户

要使用您的 Facebook 账户进行登录,您应该有一个 Facebook 开发者账户。如果您还没有,您可以在这里获取一个。

请关注我的 YouTube 频道,了解如何使用插件设置 Facebook 的视频。

按照“我的应用”->“添加新应用”下的向导注册您的移动应用。

  1. 前往 https://developers.facebook.com/apps 创建一个新的应用
  2. 如果您看到产品设置页面,请选择“Facebook 登录”
  3. 确保开启“嵌入式浏览器 OAuth 登录”选项
  4. 点击保存
  5. 将仪表板页面中的 App ID 和 App Secret 复制到您的应用中。这些将分别对应 ClientID 和 ClientSecret。

Google 账户

要使用您的 Google 账户登录,您应该有一个 Google 开发者账户。如果您还没有,您可以在 这里 获取一个。

关注我的 YouTube 频道,了解如何使用此插件设置 Google。

按照开发者控制台中的向导注册您的移动应用。(更多信息即将到来)

Google 登录仅适用于应用外浏览器。您必须为您的应用注册一个自定义 URL 方案(见下文)。

LinkedIn 账户

要使用您的 LinkedIn 账户登录,您应该有一个 LinkedIn 开发者账户。如果您还没有,您可以在 这里 获取一个。

  1. 点击 我的应用 并使用您的 LinkedIn 凭据登录,或者点击“立即加入”创建新账户。
  2. 登录后,点击 创建应用
  3. 填写所有字段为应用的信息,然后点击 提交
  4. 如果一切顺利,您应该会得到您的应用的认证密钥,这包括客户端 ID 和客户端密钥。
  5. 在此页面上,确保添加一个 授权重定向 URL。(这可以是以 http:// 或 https:// 开头的任何 URL)。
  6. 复制认证密钥和授权重定向 URL。

设置

如果您还没有添加 TypeScript,请将其添加到您的 NativeScript 项目中。虽然这不是必需的,但强烈推荐。如果您想观看如何将现有的基于 JavaScript 的 NativeScript 应用程序转换为 TypeScript 的视频,请 在此观看

从命令提示符转到您的应用的根目录,并执行

npm install nativescript-oauth2 --save

用法

如果您想快速入门,可以从以下两个演示应用之一开始

引导

当您的应用启动时,您必须注册一个或多个身份验证提供者以使用 nativescript-oauth2 插件。您将使用下面的代码来注册提供者。

NativeScript 核心库

如果您正在使用 NativeScript 核心库,请打开 app.ts 并在 application.start(); 之前添加以下注册代码。

使用 Angular 的 NativeScript

如果您正在使用 Angular 并且您不使用 <page-router-outlet,您需要启用框架,以便插件可以打开一个带有登录屏幕的新原生页面。为此,请打开您的 main.ts 文件。您需要显式使用框架,因此请确保将带有 createFrameOnBootstrap 标志设置为 true 的选项对象传递给 platformNativeScriptDynamic,如下所示。

// main.ts
platformNativeScriptDynamic({ createFrameOnBootstrap: true }).bootstrapModule(
AppModule
);

如果您已经在组件中使用了 <page-router-outlet>,则无需执行此操作。

然后,在调用登录之前,在您的 Auth 服务中添加以下注册代码,例如在 demo-angular 项目中。

使用 Vue 的 NativeScript

如果您正在使用 NativeScript-Vue,那么您将在应用引导时添加此注册代码。Vue 演示应用包含在 GitHub 存储库中。

// This is the provider registration example code

import { configureTnsOAuth } from "nativescript-oauth2";

import {
TnsOaProvider,
TnsOaProviderOptionsFacebook,
TnsOaProviderFacebook,
TnsOaProviderOptionsGoogle,
TnsOaProviderGoogle,
TnsOaProviderOptionsMicrosoft,
TnsOaProviderMicrosoft
} from "nativescript-oauth2/providers";

function configureOAuthProviderGoogle(): TnsOaProvider {
const googleProviderOptions: TnsOaProviderOptionsGoogle = {
openIdSupport: "oid-full",
clientId:
"932931520457-buv2dnhgo7jjjjv5fckqltn367psbrlb.apps.googleusercontent.com",
redirectUri:
"com.googleusercontent.apps.932931520457-buv2dnhgo7jjjjv5fckqltn367psbrlb:/auth",
urlScheme:
"com.googleusercontent.apps.932931520457-buv2dnhgo7jjjjv5fckqltn367psbrlb",
scopes: ["email"]
};
const googleProvider = new TnsOaProviderGoogle(googleProviderOptions);
return googleProvider;
}

function configureOAuthProviderFacebook(): TnsOaProvider {
const facebookProviderOptions: TnsOaProviderOptionsFacebook = {
openIdSupport: "oid-none",
clientId: "691208554415641",
clientSecret: "d8725ac416fa1bb1917ccffd1670e3c7",
redirectUri: "https://#/connect/login_success.html",
scopes: ["email"]
};
const facebookProvider = new TnsOaProviderFacebook(facebookProviderOptions);
return facebookProvider;
}

configureTnsOAuth([
configureOAuthProviderGoogle(),
configureOAuthProviderFacebook()
]);

该插件提供了一些有用的接口,您可以使用这些接口实现提供者以及可以传递给每个提供者构造函数的选项。您不必使用这些接口,但它们是有用的指南。上面的代码显示了这些接口。

最后对 configureTnsOAuth() 的调用接受一个提供者数组并将其注册为可用。

登录

当您准备登录,或者响应登录按钮的点击事件时,您可以创建一个新的 TnsOAuthClient 实例,并在该实例上调用 loginWithCompletion() 方法,传入您想要登录的提供者。提供者的类型为 TnsOaProviderType,或者可以是字符串 'google'、'facebook'、'microsoft' 等。

import { TnsOAuthClient, ITnsOAuthTokenResult } from "nativescript-oauth2";

const client = new TnsOAuthClient(providerType);

client.loginWithCompletion((tokenResult: ITnsOAuthTokenResult, error) => {
if (error) {
console.error("back to main page with error: ");
console.error(error);
} else {
console.log("back to main page with access token: ");
console.log(tokenResult);
}
});

登录完成后,将调用完成处理程序并返回结果。

刷新访问令牌

一旦登录完成,您可以在您的 TnsOAuthClient 实例上调用 refreshTokenWithCompletion() 方法尝试刷新您的访问令牌。为了执行此操作,必须满足以下条件:

  • 登录时请求了 offline_access 范围。
  • TnsOAuthClient 必须有您之前登录的令牌结果。如果您有用于登录的原始实例,它已经在对象上了。如果您没有用于登录的原始 TnsOAuthClient 实例,例如如果应用已重新启动,则将客户端的 tokenResult 属性分配给您的令牌。

如果满足上述条件,则可以按照以下方式刷新令牌:

import { TnsOAuthClient, ITnsOAuthTokenResult } from "nativescript-oauth2";

...

client.refreshTokenWithCompletion((tokenResult: ITnsOAuthTokenResult, error) => {
if (error) {
console.error("Unable to refresh token with error: ");
console.error(error);
} else {
console.log("Successfully refreshed access token: ");
console.log(tokenResult);
}
});

创建自定义提供者

如果您看不到所需的身份验证提供者,您可以自行实现 - 请参阅 GitHub 仓库中的 demo-custom-provider 项目以获取如何操作的示例。

您需要实现两个接口:适合您的提供者的提供者选项(以下将详细介绍),以及用于提供者端点细节的 TnsOaProvider

提供者选项

通过扩展 TnsOaUnsafeProviderOptions 接口(如果您的提供者不是 Open Id 兼容的)或 TnsOaOpenIdProviderOptions 接口(如果您的提供者 Open Id 兼容的)来实现您的提供者选项。

注意:接口的名称中包含“unsafe”一词,因为非 Open Id 兼容的提供者(如 Facebook)通常需要您使用客户端密钥发送给提供者以换取令牌。建议将密钥存储在除客户端应用之外的地方(如代理),但大多数人没有这样做,只是将密钥与应用程序一起存储 - 因此不安全。

//Provider options example

export interface TnsOaMyCustomProviderOptions extends TnsOaUnsafeProviderOptions { }

TnsOaProvider

然后您可以通过实现 TnsOaProvider 接口来创建您的提供者类。

//Provider implementation example

export class TnsOaProviderMyCustomProvider implements TnsOaProvider {
public options: TnsOaProviderOptions;
public openIdSupport: OpenIdSupportNone = "oid-none";
public providerType = "myCustomProvider";
public authority = "https://#/v3.1/dialog";
public tokenEndpointBase = "https://graph.facebook.com";
public authorizeEndpoint = "/oauth";
public tokenEndpoint = "/v3.1/oauth/access_token";
public cookieDomains = ["facebook.com"];

constructor(options: TnsOaMyCustomProviderOptions) {
this.options = options;
}

public parseTokenResult(jsonData): ITnsOAuthTokenResult {
return jsonData;
}
}

最后,您将在将提供者注册到应用时使用它。

// app.ts

import * as application from "tns-core-modules/application";
import { configureOAuthProviders } from "./auth-service";
configureOAuthProviders();
application.run({ moduleName: "app-root" });
// auth-service.ts

export function configureOAuthProviders() {
const myCustomProvider = configureOAuthProviderMyCustomProvider();
configureTnsOAuth([myCustomProvider]);
}
function configureOAuthProviderMyCustomProvider(): TnsOaProvider {
const facebookProviderOptions: TnsOaMyCustomProviderOptions = {
openIdSupport: "oid-none",
clientId: "<your client/app id>",
clientSecret: "<your client secret>",
redirectUri: "<redirect Uri>",
scopes: ["email"],
customQueryParams: {
foo: "bar"
}
};
const facebookProvider = new TnsOaProviderMyCustomProvider(facebookProviderOptions);
return facebookProvider;
}

自定义 URL 方案

如果您正在使用 OpenId 认证的提供者并且需要使用应用程序外的浏览器进行身份验证,则必须将自定义 URL 方案注册到您的应用中。使用 NativeScript 实现这一点非常简单。第一步是在注册您的应用时将自定义方案注册到您的提供者。

Android

要为 Android 注册自定义 URL 方案,请打开 Android 应用资源,这些资源位于以下路径:app/App_Resources/Android/src/main/AndroidManifest.xml。AndroidManifest.xml 文件曾经位于 Android 文件夹中,但现在已向下移动了一些。尽管如此,它仍然是同一个文件。

找到名为 com.tns.NativeScriptActivity<activity> 部分,并添加属性 android:launchMode="singleTask"(或 singleTop)。然后在活动内部添加一个包含您的自定义 URL 方案的新 <intent-filter> 部分。

以下是整个 <activity> 部分的示例

		<activity android:name="com.tns.NativeScriptActivity" android:launchMode="singleTask" android:label="@string/title_activity_kimera" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/LaunchScreenTheme">

<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Custom URL Schemes -->
<data android:scheme="com.googleusercontent.apps.932931520457-buv2dnhgo7jjjjv5fckqltn367psbrlb"/>
<data android:scheme="msalf376fa87-64a9-89a1-8b56-e0d48fc08107"/>
</intent-filter>

</activity>

注意,在上面的配置中,我已经为我的应用注册了两个自定义 URL 方案 - 这是具有 pathscheme 属性的 <data> 元素。

iOS

要为 iOS 注册自定义 URL 方案,请打开 iOS 应用资源,这些资源位于以下路径:app/App_Resources/iOS/Info.plist。在此文件的键/值字典中,如果尚不存在,请添加一个键 CFBundleURLTypes。并将该键的值作为数组添加。整个添加内容如下

	<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>org.nativescript.testnsazmobaplugin</string>
<key>CFBundleURLSchemes</key>
<array>
<string>msalf376fa87-64a9-49a1-8b57-e0d48fc08107</string>
<string>fb691208554415647</string>
<string>com.googleusercontent.apps.932931520457-buv2dnhgo7jjjjv5fckqltn367psbrlb</string>
</array>
</dict>
</array>

注意,对于键 CFBundleURLSchemes,列出了三个自定义 URL 方案作为字符串,所有这些方案都会打开您的应用。

贡献

  1. 请遵循 NativeScript 文档中的插件编写指南
  2. 请使用此处可找到的 Pull Request 模板来提交 PR。