更新记录

0.0.4(2026-05-21) 下载此版本

fix: 移除 AndroidManifest.xml 的测试id

0.0.3(2026-05-21) 下载此版本

0.0.3

fix:修复飞书鉴权插件只能打包自定义基座无法打包正式包的 bug

0.0.2(2026-05-15) 下载此版本

0.0.2

插件支持鸿蒙系统

查看更多

平台兼容性

uni-app(4.84)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙 鸿蒙插件版本
- - - - - - 5.0 12 12 0.0.2
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

cnd-feishu-auth

飞书鉴权登录 UTS 原生插件,基于飞书官方 LarkSSO SDK 实现,支持 Android、iOS 和鸿蒙(HarmonyOS Next)三端。

拉起飞书 App 完成 SSO 授权登录,获取 authorization code,可用于后端换取 user_access_token 获取用户信息。

功能特性

  • 调用飞书原生SDK 拉起飞书 App 进行 SSO 授权
  • 支持 PKCE 挑战码模式(useChallengeCode),可选开启
  • 支持自定义 scope 权限范围
  • 支持检测飞书是否已安装
  • 完善的错误码体系,覆盖用户取消、参数错误、未安装等场景

环境要求

平台 最低版本
Android minSdkVersion 21 (Android 5.0)
iOS deploymentTarget 12.0
HarmonyOS OpenHarmony API 12(HarmonyOS 5.0.0),飞书 >= v7.37

暴露的 API

插件对外导出 3 个方法

import {
  sendFeishuAuth,
  isFeishuInstalled,
  handleFeishuOpenURL
} from "@/uni_modules/cnd-feishu-auth"

1. sendFeishuAuth(options)

发起飞书授权登录。调用后会拉起飞书 App,用户确认授权后通过回调返回 code

参数 options 类型:FeishuLoginOptions

属性 类型 必填 默认值 说明
appId string - 飞书开放平台的 App ID,如 "cli_xxxxxxxxxx"
scope string[] [] 权限范围数组,如 ["contact:user.id:readonly"]。不传则使用应用默认权限
useChallengeCode boolean true 是否开启 PKCE 挑战码模式。开启后回调中会包含 codeVerifier
success (result: FeishuLoginResult) => void - 授权成功回调
fail (error: FeishuLoginError) => void - 授权失败回调
complete () => void - 授权完成回调(无论成功失败都会调用)

成功回调 result 类型:FeishuLoginResult

属性 类型 说明
code string 飞书授权码,有效期 5 分钟,且只能使用一次
codeVerifier string PKCE 挑战码。仅 useChallengeCode = true 时有值

失败回调 error 类型:FeishuLoginError

属性 类型 说明
errCode number 错误码,见下方错误码表
errMsg string 错误描述信息

2. isFeishuInstalled()

检测飞书是否已安装。

返回值类型:IsFeishuInstalledResult

属性 类型 说明
installed boolean true 表示飞书已安装

注意:iOS 端需要在 manifest.json 中配置 LSApplicationQueriesSchemes 包含 "lark",否则始终返回 false。鸿蒙端使用 bundleManager.isApplicationEnabledSync 检测,无需额外配置。

3. handleFeishuOpenURL(url)

处理飞书 SSO 回调 URL。需要在 App.vue 中调用,将飞书授权完成后跳回 App 的 URL 传给 SDK 解析。

参数 类型 说明
url string 飞书回调的完整 URL 字符串

返回值booleantrue 表示该 URL 已被 SDK 成功处理。

注意:Android 端新架构下,飞书回调由 FeishuCallbackActivity 直接处理,不再经过 App.vuenewintent 事件。此方法在 Android 端作为兜底保留,iOS 端仍需调用,鸿蒙端无需调用(始终返回 false)


鸿蒙端接入说明

第一步:获取 SDK

下载飞书鸿蒙 SDK,将 larksso-1.0.0.har 放入:

utssdk/app-harmony/libs/larksso-1.0.0.har

SDK 下载地址(官方):
https://sf3-cn.feishucdn.com/obj/lark-eco-passport/LarkSSOSDKHarmony-v1.0.0.zip

第二步:配置宿主应用的 module.json5

在当前应用的 harmony-configs/entry/src/main/module.json5中添加以下配置:

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet",
      "2in1"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:layered_image",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ],
    "querySchemes": [
      "lark",
      "wxworkapi"
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

说明querySchemes 声明允许查询 lark:// Scheme,是检测飞书安装状态和拉起飞书授权的必要配置。

第三步:调用授权

调用方式与 Android/iOS 完全一致,无需额外初始化或 URL 回调处理:

import { sendFeishuAuth, isFeishuInstalled } from "@/uni_modules/cnd-feishu-auth"

sendFeishuAuth({
  appId: 'cli_xxxxxxxxxx',
  useChallengeCode: true,
  success(res) {
    console.log('授权码:', res.code)
    console.log('codeVerifier:', res.codeVerifier)
  },
  fail(err) {
    console.error('授权失败:', err.errCode, err.errMsg)
  }
})

鸿蒙与 iOS 的关键区别:iOS 授权完成后需要在 App.vue 中调用 handleFeishuOpenURL 处理 URL Scheme 回调;鸿蒙端 SDK 内置回调机制,不需要处理 URL 或 Want 回调,startSSOVerifyIGetDataCallback 会直接触发。

错误码

错误码 常量名 说明
0 FEISHU_SUCCESS 成功
20001 FEISHU_NOT_INSTALLED 飞书未安装(无法跳转飞书)
20002 FEISHU_USER_CANCEL 用户取消了授权
20003 FEISHU_AUTH_FAILED 飞书授权失败
20004 FEISHU_INVALID_PARAMS 参数错误(如 appId 为空)
20005 FEISHU_SDK_INIT_FAILED SDK 初始化或发送请求失败
20006 FEISHU_BAD_STATE state 校验失败
20007 FEISHU_NO_VALID_CODE 未获取到有效凭证
20099 FEISHU_UNKNOWN 未知错误

关于 utssdk/index.uts

本插件除了 utssdk/app-android/index.utsutssdk/app-ios/index.uts 之外,还需要保留 utssdk/index.uts 作为通用入口。

原因不是业务逻辑需要这个文件,而是 uni-app 在 H5 开发和部分非 App 平台做模块解析时,会优先查找 utssdk/index.utsutssdk/<当前平台>/index.uts。如果插件只有 Android 和 iOS 平台实现,没有这个通用入口,像下面这种导入在 Vite 依赖扫描阶段就会直接报“Cannot find module”:

import {
  sendFeishuAuth,
  isFeishuInstalled,
  handleFeishuOpenURL
} from "@/uni_modules/cnd-feishu-auth"

建议约定如下:

  • utssdk/app-android/index.uts:Android 真正实现
  • utssdk/app-ios/index.uts:iOS 真正实现
  • utssdk/index.uts:非 App 平台的兜底入口,至少保证模块可解析

这样做的好处是:

  • H5 本地开发不会因为依赖扫描而启动失败
  • 条件编译代码即使最终不会在 H5 执行,导入阶段也能正常通过
  • 插件结构和 uni-app 的 UTS 解析规则保持一致,后续维护成本更低

接入步骤

第一步:配置 manifest.json

打开项目根目录的 manifest.json,配置 URL Scheme 和白名单。

关键规则

  • Android 的 scheme 为 App ID 原值(带下划线),如 cli_axxxxxxxxx
  • iOS 的 scheme 为 App ID 去掉下划线,如 cli_axxxxxxxxx
  • 两端的 scheme 格式不同,这是飞书 SDK 的设计,不要搞混

请将以下示例中的 cli_axxxxxxxxx 替换为你自己的 App ID:

{
  "app-plus": {
    "distribute": {
      "android": {
        "schemes": "cli_axxxxxxxxx"
      },
      "ios": {
        "urltypes": [
          {
            "urlschemes": ["cli_axxxxxxxxx"]
          }
        ],
        "urlschemewhitelist": "lark",
        "LSApplicationQueriesSchemes": ["lark"]
      }
    }
  }
}
配置项 平台 作用
android.schemes Android 注册 URL Scheme,飞书授权后跳回 App
ios.urltypes[].urlschemes iOS 注册 URL Scheme,飞书授权后跳回 App
ios.urlschemewhitelist iOS 允许查询的 scheme 白名单
ios.LSApplicationQueriesSchemes iOS 允许检测飞书是否安装(canOpenURL

如果你的项目同时使用了其他插件(如企业微信),schemes 之间用逗号分隔:

"schemes": "cli_axxxxxxxxx,wxxxxxxxx"

第二步:修改插件内 AndroidManifest.xml 的 scheme(Android 必须)

插件内的 utssdk/app-android/AndroidManifest.xml 中,FeishuCallbackActivity 的 intent-filter scheme 是硬编码的示例值。你需要将其替换为你自己的 App ID:

打开 uni_modules/cnd-feishu-auth/utssdk/app-android/AndroidManifest.xml,找到:

<data android:scheme="cli_axxxxxxxxx" />

替换为你的 App ID(保持带下划线的格式):

<data android:scheme="你的_App_ID" />

为什么需要这一步? Android 端飞书授权后,飞书 App 通过 URL Scheme 跳回你的 App。FeishuCallbackActivity 注册的 scheme 必须与你的 App ID 一致,否则飞书回调无法路由到此 Activity,导致授权完成后无响应。

如果还是无法授权 请直接将以下代码复制一份到你的项目根目录,改名为 AndriodMainfest.xml,将cli_xxxxx 改成你的飞书项目 ID

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="io.dcloud.nativeresouce">

    <application>
        <activity
            android:name="io.dcloud.PandoraEntryActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="cli_xxxxx" />
            </intent-filter>
        </activity>
    </application>

</manifest>

第五步:配置 App.vue

飞书授权完成后,飞书会通过 URL Scheme 跳回你的 App。你需要在 App.vue 中捕获回调 URL 并传给插件处理。

重要newintent 事件中需要加 setTimeout 延迟(建议 100ms),确保系统已经更新完 plus.runtime.arguments

<script>
  // #ifdef APP-PLUS
  import { handleFeishuOpenURL } from "@/uni_modules/cnd-feishu-auth"
  // #endif

  export default {
    onLaunch: function () {
      // #ifdef APP-PLUS
      // 处理冷启动时的 URL Scheme
      this.handleSchemeUrl()

      // 监听热启动时的 URL Scheme(从飞书跳回)
      var self = this
      plus.globalEvent.addEventListener("newintent", function () {
        setTimeout(function () {
          self.handleSchemeUrl()
        }, 100)
      })
      // #endif
    },
    methods: {
      // #ifdef APP-PLUS
      handleSchemeUrl: function () {
        var args = plus.runtime.arguments
        if (!args) return

        // 飞书 SSO 回调处理
        // Android scheme: cli_xxx://...  iOS scheme: clixxx://...
        if (args.indexOf("cli") === 0) {
          console.log("飞书 SSO 回调 URL:", args)
          handleFeishuOpenURL(args)
          plus.runtime.arguments = ""
          return
        }

        plus.runtime.arguments = ""
      }
      // #endif
    }
  }
</script>

第六步:调用授权 API

// #ifdef APP-PLUS
import {
  sendFeishuAuth,
  isFeishuInstalled
} from "@/uni_modules/cnd-feishu-auth"
// #endif

// 检测飞书安装状态
var result = isFeishuInstalled()
console.log("飞书已安装:", result.installed)

// 发起授权(普通模式)
sendFeishuAuth({
  appId: "cli_xxxxxxxxxx",
  scope: ["contact:user.id:readonly"],
  useChallengeCode: false,
  success: function (res) {
    console.log("授权码:", res.code)
    // 将 code 发送给后端换取 user_access_token
  },
  fail: function (err) {
    console.error("授权失败:", err.errCode, err.errMsg)
  }
})

第七步(可选):PKCE 挑战码模式

PKCE 模式允许客户端直接用 code + codeVerifier 换取 Token,无需 app_secret

sendFeishuAuth({
  appId: "cli_xxxxxxxxxx",
  scope: ["contact:user.id:readonly"],
  useChallengeCode: true,
  success: function (res) {
    console.log("code:", res.code)
    console.log("codeVerifier:", res.codeVerifier)

    // PKCE 模式换取 token
    uni.request({
      url: "https://xxxxxxxxxx", //你自己的后端地址
      method: "POST",
      header: { "Content-Type": "application/json" },
      data: {
        grant_type: "authorization_code",
        client_id: "cli_xxxxxxx",
        code: res.code,
        code_verifier: res.codeVerifier
      },
      success: function (tokenRes) {
        console.log("access_token:", tokenRes.data.access_token)
      }
    })
  }
})

重要注意事项

1. Android 回调机制(必读)

Android 端使用了独立的 FeishuCallbackActivity 架构来解决 uni-app 主 Activity 回调丢失问题:

  • 问题背景:uni-app 的主 Activity (PandoraEntryActivity) 是 singleTask 模式,飞书 SDK 回调时走 onNewIntent,但 HBuilderX 框架不会将 onNewIntent 的数据同步到 plus.runtime.arguments,导致回调数据丢失。
  • 解决方案:插件内置了 FeishuCallbackActivitysingleTop + exported=true),作为 SDK 的 context 和回调接收者。飞书 App 直接回调到这个 Activity,绕过了 PandoraEntryActivity 的问题。
  • 对使用者的影响:Android 端授权回调是自动处理的,不依赖 App.vue 中的 handleFeishuOpenURL。但仍建议保留 App.vue 中的调用作为兜底。

2. Android 根目录 AndroidManifest.xml(通常不需要)

插件已内置 FeishuCallbackActivity 专门处理飞书回调(见第四步),因此正常情况下不需要在项目根目录添加 AndroidManifest.xml

历史背景:早期方案曾在根目录 AndroidManifest.xml 中给 PandoraEntryActivity 注册飞书 scheme 的 intent-filter。这是因为当时没有独立的回调 Activity,需要主 Activity 来接收回调。现在有了 FeishuCallbackActivity,这个配置已不再需要。如果你的项目根目录有这样的遗留配置,可以保留(不影响功能),也可以删除以避免混淆。

仅当以下情况才需要考虑根目录 AndroidManifest.xml

  • 遇到 Permission Denial 错误,需要将 PandoraEntryActivity 设为 exported=true
  • 某些特殊 HBuilderX 版本的打包行为不会合并插件内的 manifest

3. iOS 端 scheme 去掉下划线

这是最容易出错的地方。飞书 iOS SDK 会自动将 App ID 中的下划线去掉作为 URL Scheme:

App ID Android Scheme iOS Scheme
cli_axxxxxxxxxxxx cli_axxxxxxxxxxxx cliaxxxxxxxxxxx

如果 iOS 的 urltypes 配置了带下划线的 scheme,飞书授权后将无法跳回 App。

4. iOS LSApplicationQueriesSchemes 必须配置

iOS 9+ 系统要求声明 LSApplicationQueriesSchemes 才能使用 canOpenURL 检测其他 App 是否安装。如果不配置:

  • isFeishuInstalled() 始终返回 false
"ios": {
    "LSApplicationQueriesSchemes": ["lark"]
}

5. code 有效期和一次性使用

飞书返回的 authorization code 有以下限制:

  • 有效期 5 分钟
  • 只能使用一次(换取 token 后立即失效)

如果你在调试时反复用同一个 code 换 token,会收到 invalid_grant 错误。每次测试需要重新发起授权。

6. Android queries 声明(Android 11+)

Android 11(API 30)引入了包可见性限制,需要在 AndroidManifest 中声明 <queries> 才能检测飞书是否安装。本插件已在 utssdk/app-android/AndroidManifest.xml 中内置了此配置:

<queries>
    <package android:name="com.ss.android.lark" />
    <package android:name="com.larksuite.suite" />
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="lark" android:host="ssoclient" />
    </intent>
</queries>

一般无需手动添加。


插件目录结构

cnd-feishu-auth/
├── package.json # 插件元信息
└── utssdk/
    ├── interface.uts # 跨平台类型定义
    ├── unierror.uts  # 错误码常量
    ├── index.uts     # 非 App 平台兜底入口
    ├── app-android/
    │   ├── index.uts           # Android 实现(含 FeishuCallbackActivity)
    │   ├── config.json         # Android 构建配置
    │   ├── AndroidManifest.xml # Activity 注册 + queries 声明
    │   └── libs/
    │       └── larksso-3.0.10.aar  # 飞书 Android SDK
    ├── app-ios/
    │   ├── index.uts    # iOS 实现
    │   ├── config.json  # iOS 构建配置(frameworks 依赖)
    │   └── Frameworks/
    │       ├── LarkSSOSDK.framework  # 飞书 iOS SDK
    │       └── LarkSSO.bundle        # SDK 资源包
    └── app-harmony/
        ├── index.uts    # 鸿蒙实现
        ├── config.json  # 鸿蒙构建配置(minAPIVersion + 依赖)
        └── libs/
            └── larksso-1.0.0.har    # 飞书鸿蒙 SDK(需手动放入)

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android - 权限: android.permission.INTERNET 用途: 网络访问,用于飞书 SDK 通信 - 权限: android.permission.ACCESS_NETWORK_STATE 用途:检查网络连接状态,SDK 内部判断网络可用性 iOS: 无 鸿蒙: 无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件自身不采集任何数据,插件使用的飞书移动端 SDK 采集数据请参考其官方说明:https://open.feishu.cn/document/common-capabilities/sso/mobile-app/sdk

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。