Flutter Azure AD 登录插件dart_azure_ad_sign_in的使用

Flutter Azure AD 登录插件 dart_azure_ad_sign_in 的使用

1. 平台支持

平台 Dart Flutter 测试环境
Android ✖️ ✔️ Pixel 4 (模拟器) 和 Xiaomi 9T
iOS ✖️ 尚未测试,但应该可以工作
Linux ✔️ ✔️ Ubuntu 22.04 LTS
macOS 尚未测试,但应该可以工作
Web ✖️ ✖️ 使用 dart.io 的 HttpServer,无法在 Web 上工作
Windows ✔️ ✔️ Windows 11

2. 功能

dart_azure_ad_sign_in 插件允许 Flutter 和 Dart 应用程序获取用于访问受保护资源(如 Azure Web API)的认证令牌。该插件可以无需任何配置即可使用,提供与 Azure CLI 相同的访问权限,也可以通过配置来修改访问权限。

3. 认证流程

SignIn Wokrflow

4. 入门指南

4.1 安装

前往 Pub.dev 获取最新版本。

4.2 导入

在 Dart 文件中导入 dart_azure_ad_sign_in 包:

import 'package:dart_azure_ad_sign_in/dart_azure_ad_sign_in.dart';
4.3 Android 设置
4.3.1 网络设置

确保在 AndroidManifest.xml 中启用网络权限:

<manifest xmlns:android...>
  ...
  <uses-permission android:name="android.permission.INTERNET" />
  <application ...
</manifest>
4.3.2 明文流量

创建 res/xml/network_security_config.xml 文件并配置如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

然后在 AndroidManifest.xml 中加载该文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <application
        ...
        android:networkSecurityConfig="@xml/network_security_config"
        ...>
        ...
    </application>
</manifest>
4.4 iOS 设置
4.4.1 网络设置

iOS 不需要额外的网络设置。

4.4.2 明文流量

info.plist 中添加以下规则以允许本地主机的明文流量:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>
4.5 macOS 设置
4.5.1 网络设置

.entitlements 文件中启用网络权限:

<key>com.apple.security.network.client</key>
<true/>
4.5.2 明文流量

info.plist 中添加以下规则以允许本地主机的明文流量:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>
4.6 Windows 设置

无需额外设置。

4.7 Linux 设置

无需额外设置。

5. 使用方法

5.1 创建和配置 AzureSignIn 实例

AzureSignIn 类非常灵活,无需设置参数即可使用,默认会使用 Azure CLI 配置。有关所有可用变量的详细信息,请参阅 AzureSignIn 变量

5.1.1 使用默认设置创建实例
final azureSignIn = AzureSignIn();
5.1.2 使用参数创建实例

如果需要,可以设置认证和本地 HTTP 服务器的参数:

final azureSignIn = AzureSignIn(
  // 应用程序(客户端)ID,Azure 门户 - 应用注册页面分配给你的应用。
  clientId: '04b07795-8ddb-461a-bbee-02f9e1bf7b46',
  // 用户需要同意的权限范围。
  scope: [
    'https://management.core.windows.net//.default',
    'offline_access',
    'openid',
    'profile',
  ],
  // 本地 HTTP 服务器的端口,用于接收登录后的代码。
  port: 5000,
  // 登录成功后用户在浏览器中看到的响应。
  serverSuccessResponse: '<h1>登录成功。</h1><p>可以关闭此窗口。</p>',
  // 登录失败后用户在浏览器中看到的响应。
  serverErrorResponse: '<h1>登录失败。</h1><p>请关闭此窗口并重试。</p>',
  // 本地 HTTP 服务器等待用户登录的时间。
  signInTimeoutDuration: Duration(minutes: 5),
);
5.2 登录
5.2.1 获取 Microsoft 登录页面 URL

用户需要在浏览器中登录,可以通过 signInUri 获取登录 URL。如果使用 Flutter,可以使用 url_launcher 插件打开该 URL。

// 打印登录 URL,用户需要在浏览器中打开。
print(azureSignIn.signInUri);
5.2.2 启动登录过程

启动登录过程将返回一个新的 Token。在后台,会启动一个 HttpServer,等待浏览器登录后接收到代码,然后调用 Microsoft Token Endpoint 获取令牌。

Token token = await azureSignIn.signIn();
5.3 取消登录过程

用户可以在需要时取消登录过程。azureSignIn.signIn() 将返回一个带有取消信息的 Token

// 取消登录过程。
await azureSignIn.cancelSignIn();
5.4 刷新令牌

当令牌过期时,可以通过提供现有的 Token 或刷新令牌字符串来刷新令牌。

5.4.1 使用现有 Token 刷新
// 使用现有令牌对象刷新令牌。
token = await azureSignIn.refreshToken(token: token);
5.4.2 使用刷新令牌字符串刷新
// 使用刷新令牌字符串刷新令牌。
token = await azureSignIn.refreshToken(refreshToken: refreshTokenString);
5.5 AzureSignIn 变量
名称 类型 默认值 是否可修改 描述
azureSignIn.clientId String 04b07795-8ddb-461a-bbee-02f9e1bf7b46 应用程序(客户端)ID,默认使用 Azure CLI 客户端 ID。
azureSignIn.scope List<String> ['https://management.core.windows.net//.default', 'offline_access', 'openid', 'profile'] 用户需要同意的权限范围,默认使用 Azure CLI 权限范围。
azureSignIn.grantType String authorization_code 授权类型,必须为 authorization_code
azureSignIn.port int 5000 本地 HTTP 服务器的端口。
azureSignIn.signInTimeoutDuration Duration() Duration(minutes: 5) 本地 HTTP 服务器等待用户登录的时间。
azureSignIn.serverSuccessResponse String Sign In successful. This window can now be closed. 登录成功后用户在浏览器中看到的响应。
azureSignIn.serverErrorResponse String Sign In failed. Close this window and try again. 登录失败后用户在浏览器中看到的响应。
azureSignIn.signInUri String 生成的 Microsoft 登录 URL 获取 Microsoft 登录 URL。
azureSignIn.signOutUri String https://login.microsoftonline.com/common/oauth2/v2.0/logout 用于登出的 Azure Auth URL。
5.6 Token 实体
名称 类型 示例值 描述
token.tokenType String Bearer 表示令牌类型,Azure AD 支持的唯一类型是 Bearer
token.scope String user_impersonation 令牌有效的权限范围。
token.expiresIn String 5084 令牌的有效时间(秒)。
token.extExpiresIn String 5084 用于表示令牌的扩展生命周期。
token.expiresOn String 1674580651 令牌过期的时间戳。
token.notBefore String 1674575266 令牌生效的时间戳。
token.resource String https://management.core.windows.net/ 令牌访问的资源。
token.accessToken String eyJ0eXAiOiJKV1QiLCJhbGciOiJS... 访问令牌,应用程序可以使用此令牌访问受保护的资源。
token.refreshToken String 0.AQUAjHBCWE0CK06v4qgD88sl3Z... OAuth 2.0 刷新令牌,用于在当前访问令牌过期后获取新的访问令牌。
token.idToken String eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs... JSON Web Token,应用程序可以解码此令牌以获取用户信息。
token.foci String 1 使用 FOCI(客户端 ID 家族)访问 Microsoft Office 应用程序。
token.status int 0: 成功<br>1: Azure API 错误<br>2: HttpServer 错误<br>3: 登录已取消 令牌授权代码流的结果状态。
token.error String invalid_grant 错误代码字符串,用于分类错误类型。
token.errorDescription String AADSTS900144: The request body must contain the following parameter: 'code'... 具体的错误消息,帮助开发者识别认证错误的根本原因。
token.errorCodes List<dynamic> [900144] STS 特定的错误代码列表,用于诊断。
token.errorUri String https://login.microsoftonline.com/error?code=900144 关于出现错误的 Microsoft 文档 URL。

6. 下一步

使用 token.accessToken,你现在已经可以访问 Microsoft APIs。更多关于 Azure REST API 的信息可以参考 Azure Rest API 参考,或查看 常用 Microsoft 应用程序的应用 ID 以添加一些预定义的 azureSignIn.clientId

7. Bug 和问题

请在 GitHub Issues 提交功能请求和 bug。

完整示例 Demo

以下是一个完整的示例,展示了如何使用 dart_azure_ad_sign_in 插件进行 Azure AD 登录和令牌刷新:

// Copyright 2023 Patrick Hettich. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:dart_azure_ad_sign_in/dart_azure_ad_sign_in.dart';

void main(List<String> args) async {
  // 创建 Azure SignIn 实例,所有参数都是可选的。
  final azureSignIn = AzureSignIn();

  // 打印登录 URL。
  print(azureSignIn.signInUri);

  // 启动 HTTP 服务器并等待用户登录。
  // 也可以通过 azureSignIn.cancelSignIn() 取消登录。
  Token token = await azureSignIn.signIn();

  // 打印令牌信息
  printToken(token: token, title: '初始令牌');

  // 刷新过期的令牌
  token = await azureSignIn.refreshToken(token: token);

  // 打印更新后的令牌信息
  printToken(token: token, title: '刷新后的令牌');
}

void printToken({required Token token, required String title}) {
  print(
      '------------------------------------------------------------------------------------------------------------------------------------');
  print(title);
  print(
      '------------------------------------------------------------------------------------------------------------------------------------');
  print('状态: ${token.status}');
  print('错误: ${token.error}');
  print('错误消息: ${token.errorDescription}');
  print('访问令牌:');
  print(token.accessToken);
  print('刷新令牌:');
  print(token.refreshToken);
}

更多关于Flutter Azure AD 登录插件dart_azure_ad_sign_in的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Azure AD 登录插件dart_azure_ad_sign_in的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个使用 dart_azure_ad_sign_in 插件在 Flutter 应用中实现 Azure AD 登录的示例代码。请确保您已经按照插件的文档完成了相关的设置,包括在 Azure 门户中注册您的应用并获取所需的客户端 ID 和重定向 URI。

首先,您需要在 pubspec.yaml 文件中添加 dart_azure_ad_sign_in 依赖:

dependencies:
  flutter:
    sdk: flutter
  dart_azure_ad_sign_in: ^x.y.z  # 请替换为最新的版本号

然后,运行 flutter pub get 来获取依赖。

接下来,是主要的 Flutter 代码示例:

import 'package:flutter/material.dart';
import 'package:dart_azure_ad_sign_in/dart_azure_ad_sign_in.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Azure AD Login',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AzureADLoginPage(),
    );
  }
}

class AzureADLoginPage extends StatefulWidget {
  @override
  _AzureADLoginPageState createState() => _AzureADLoginPageState();
}

class _AzureADLoginPageState extends State<AzureADLoginPage> {
  final AzureADSignIn _azureADSignIn = AzureADSignIn(
    clientId: 'YOUR_CLIENT_ID',  // 替换为您的 Azure AD 应用的客户端 ID
    redirectUri: 'YOUR_REDIRECT_URI',  // 替换为您在 Azure 门户中设置的重定向 URI
    tenantId: 'YOUR_TENANT_ID',  // 替换为您的 Azure AD 租户 ID(如果需要特定租户)
  );

  String _userDisplayName = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Azure AD Login'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'User Display Name: $_userDisplayName',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                try {
                  final result = await _azureADSignIn.signIn();
                  if (result != null) {
                    setState(() {
                      _userDisplayName = result.displayName;
                    });
                  }
                } catch (e) {
                  print('Error during Azure AD login: $e');
                }
              },
              child: Text('Sign In with Azure AD'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的 Flutter 应用,其中包含一个按钮,用户点击该按钮后将触发 Azure AD 登录流程。登录成功后,我们将用户的显示名称显示在屏幕上。

请确保将 YOUR_CLIENT_IDYOUR_REDIRECT_URIYOUR_TENANT_ID 替换为您在 Azure 门户中配置的实际值。

此外,您可能还需要在 Android 和 iOS 项目中进行一些额外的配置,以确保重定向 URI 能够正确处理。这通常涉及到修改 AndroidManifest.xml 文件和 iOS 的 Info.plist 文件,以及可能需要在 Xcode 和 Android Studio 中进行一些设置。具体步骤请参考 dart_azure_ad_sign_in 插件的官方文档。

回到顶部