使用 Flutter Web 的 Microsoft Azure 身份验证

我是 Flutter 的新手,我被困在需要使用 Microsoft 身份验证对我的 Web 应用程序进行身份验证的地步。我没有找到任何与此相关的文档,flutter 也没有包这样做。我想我需要在本机平台上编写代码并将其连接到颤振。帮助 !!

stack overflow Microsoft Azure Authentication using Flutter Web
原文答案

答案:

作者头像

找到了一个 Flutter Microsoft 身份验证包,您可以尝试在 Flutter 代码中导入。

通过将 Flutter Microsoft Authentication 包添加到 pubsec.yaml 文件中的依赖项列表中,将 Flutter Microsoft Authentication 包导入到您的 Flutter 应用程序中。

依赖项:

flutter_microsoft_authentication: ^0.1.0

参考: https://pub.dev/packages/flutter_microsoft_authentication

作者头像

一年后,我遇到了同样的问题,尽管我进行了搜索,但没有找到任何明确且有效的解决方案。这就是我所做的。在发布一个支持 Flutter web 的干净且简单的软件包之前,它可能会对某些人有所帮助。

这个概念很简单。为了不处理用户身份验证,我希望用户针对身份提供者 (IP):Azure Active Directory 挑战他的凭据,并让 Azure 使用安全令牌将他重定向到我的应用程序。

客户端应用程序将用户重定向到 Microsoft 身份验证 Web 应用程序并传递一个“回调 url”,一旦用户通过身份验证,Azure 将使用该“回调 URL”来重定向用户。通过重定向到客户端应用程序,Azure 还传递了一个访问令牌,最终提供了一些有关此令牌接收者可能需要知道的角色或权限的信息。我们可以将令牌保存在某个地方。假设在一个全局变量中:

class Globals {
  String azureAccessToken = "";
  Globals._privateConstructor();
  static final Globals _instance = Globals._privateConstructor();
  static Globals get instance => _instance;
}

如果令牌已知,则应用程序处理路由并显示主应用程序小部件,如果尚不知道令牌,则显示身份验证小部件

import 'package:flutter/material.dart';
import 'package:flutterweb_azuread_authentication/helpers/globals.dart';
import 'authenticate.dart';
import 'main_app.dart';
class FlutterAuthenticationApp extends StatefulWidget {
  const FlutterAuthenticationApp({super.key});
  @override
  State<FlutterAuthenticationApp> createState() => _FlutterAuthenticationAppState();
}
class _FlutterAuthenticationAppState extends State<FlutterAuthenticationApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: 
      {
        "/":(context)=>Globals.instance.azureAccessToken==""?const Authenticate():const MainApp(),
        }
    )
    ;
  }
}

MainApp 将简单地显示一条消息,提供令牌

import 'package:flutter/material.dart';
import 'package:flutterweb_azuread_authentication/helpers/globals.dart';
class MainApp extends StatefulWidget {
  const MainApp({super.key});
  @override
  State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
  @override
  Widget build(BuildContext context) {
    return 
    SelectableText("Seems you're authenticated. Your token is ${Globals.instance.azureAccessToken}");
  }
}

Authenticate 小部件显示一个登录按钮。当用户单击登录时,他应该被重定向到 Microsoft 登录应用程序,然后被重定向到该应用程序。

import 'package:flutter/material.dart';
import 'package:openid_client/openid_client_browser.dart' as open_id;
class Authenticate extends StatefulWidget {
  const Authenticate({super.key});
  @override
  State<Authenticate> createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
  @override
  Widget build(BuildContext context) {
    var tenantId = "<your tenant id>";
    var clientId = "<your app registration id>";
    var scope = "api://<your scope>";
    return Scaffold(
      appBar: AppBar(title: const Text("Authenticate with Azure AD")),
      body: Center(
        child: ElevatedButton(
          child: const Text("Login"),
          onPressed: null,
        ),
      ),
    );
  }
}

当用户单击登录时,我们需要将应用程序重定向到 Azure AD 身份验证,并传递包括回调 url 在内的相关参数。此回调 url 必须获取 Azure AD 发送的令牌并最终确定流程。

寻找现有的包,我遇到了以下问题:

  • aad_oauth:出于任何原因,这个包对我不起作用。我面临着许多依赖问题,我认为尽管宣布了什么,但这并不支持 Flutter Web。
  • flutter_aad_auth:不支持网络
  • azure_ad_authentication:不支持网络

最后,我必须使用 openid_client 包,更准确地说是 openid_client_browser 来获得自己的解决方案。

这个包处理流程,特别是将 Flutter Web 应用程序重定向到 Microsoft Azure 身份验证。

为了使用 Azure AD,我们显然需要配置一个 Active Directory。我不会在这里描述它。请注意,您将需要您的tenandId、注册应用程序 ID 和范围。我试图在这个 article 中解释更多。

现在让我们使用 openid_client_browser 重定向到 Azure AD 身份验证并观察会发生什么……

import 'package:flutter/material.dart';
import 'package:openid_client/openid_client_browser.dart' as open_id;
class Authenticate extends StatefulWidget {
  const Authenticate({super.key});
  @override
  State<Authenticate> createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
  @override
  Widget build(BuildContext context) {
    var tenantId = "<your tenant id>";
    var clientId = "<your app registration id>";
    var scope = "api://<your scope>";
    return Scaffold(
      appBar: AppBar(title: const Text("Authenticate with Azure AD")),
      body: Center(
        child: ElevatedButton(
          child: const Text("Login"),
          onPressed: () {           authenticate(Uri.parse("https://login.microsoftonline.com/$tenantId/v2.0"), clientId, [scope]);
          },
        ),
      ),
    );
  }
}
authenticate(Uri uri, String clientId, List<String> scopes) async {
  var issuer = await open_id.Issuer.discover(uri);
  var client = open_id.Client(issuer, clientId);
  var authenticator = open_id.Authenticator(client, scopes: scopes);
  await authenticator.credential;
  authenticator.authorize();
}

单击登录按钮时,将显示 Microsoft 登录页面。输入凭据并完成登录过程后,Azure 会将您的浏览器重定向到 Flutter Web 应用程序的根目录,并添加 #access_token=xxx 对我来说有点奇怪,它没有使用带有 ?access_token 的常规查询参数,但我们会生存下来。现在我们必须在收到令牌后立即从 URI 中提取令牌。所以就在你的主要入口点运行应用程序之前,

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutterweb_azuread_authentication/helpers/globals.dart';
import 'widget/flutter_authentication_app.dart';
void main() {
  if (Uri.base.toString().contains("access_token=")) {
    var idxStart = Uri.base.toString().indexOf("access_token=") + "access_token=".length;
    var idxEnd = min(Uri.base.toString().length - 1, Uri.base.toString().indexOf("&token_type="));
    var accessToken = Uri.base.toString().substring(idxStart, idxEnd);
    Globals.instance.azureAccessToken = accessToken;
  }
  runApp(const FlutterAuthenticationApp());
}

由于我提取令牌的方式,它看起来不太漂亮,但它可以完成工作。

对不起,如果这个答案有点长,但我想尽可能清楚。您可以在 github 上找到代码

相关问题