基于OAuth2的Flutter应用集成Microsoft Azure单点登录问题咨询
Flutter集成Azure单点登录(SSO)问题解答
一、Azure应用注册配置
- 应用类型:必须注册为移动和桌面应用,而非Web类型。Flutter属于跨平台移动端/桌面端范畴,Web类型仅适用于纯Web应用场景。
- 特殊配置:
- 在"身份验证"页面添加对应平台的重定向URI:
- 移动端(Android/iOS):使用自定义URL Scheme,格式为
msal{你的客户端ID}://auth - 桌面/调试场景:可配置
http://localhost:3000/redirect或http://localhost
- 移动端(Android/iOS):使用自定义URL Scheme,格式为
- 开启"允许公共客户端流"(在"身份验证"的"高级设置"中),Flutter客户端属于公共客户端,无法安全存储密钥,必须开启此选项。
- 在"身份验证"页面添加对应平台的重定向URI:
二、oauth2库的redirect()和listen()实现
oauth2库基于授权码流程实现SSO,redirect负责跳转至Azure授权页,listen负责监听授权回调并获取令牌。
1. redirect() 实现
通过url_launcher库打开Azure授权URL,引导用户完成登录授权:
import 'package:url_launcher/url_launcher.dart'; import 'package:oauth2/oauth2.dart'; // 替换为你的Azure租户ID、客户端ID final tenantId = '你的租户ID'; final clientId = '你的客户端ID'; final redirectUri = Uri.parse('msal$clientId://auth'); // 与Azure配置的重定向URI一致 final authorizationEndpoint = Uri.parse('https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize'); final tokenEndpoint = Uri.parse('https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token'); // 初始化授权客户端 final grant = AuthorizationCodeGrant( clientId, authorizationEndpoint, tokenEndpoint, ); // 生成授权URL并跳转 Future<void> redirect() async { final authorizationUrl = grant.getAuthorizationUrl(redirectUri); if (await canLaunchUrl(authorizationUrl)) { await launchUrl(authorizationUrl); } else { throw Exception('无法打开授权页面'); } }
2. listen() 实现
根据平台差异,监听授权回调的方式不同:
- 移动端:通过
app_links库捕获URL Scheme回调:
import 'package:app_links/app_links.dart'; final appLinks = AppLinks(); Future<void> listen() async { appLinks.uriLinkStream.listen((Uri? uri) async { if (uri != null && uri.queryParameters.containsKey('code')) { // 用授权码交换令牌 final client = await grant.handleAuthorizationResponse(uri.queryParameters); // 保存并使用令牌:client.credentials.accessToken、refreshToken等 print('获取到访问令牌:${client.credentials.accessToken}'); } }); }
- 桌面/调试场景:用
shelf库启动临时本地服务器接收localhost回调:
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; Future<void> listen() async { final handler = const Pipeline().addHandler((Request request) async { if (request.requestedUri.queryParameters.containsKey('code')) { final client = await grant.handleAuthorizationResponse(request.requestedUri.queryParameters); // 处理令牌逻辑 return Response.ok('登录成功,可关闭此页面'); } return Response.ok('等待授权...'); }); // 启动本地服务器监听3000端口,与重定向URI端口一致 await shelf_io.serve(handler, 'localhost', 3000); }
三、localhost访问说明
- 若重定向URI使用
http://localhost格式,桌面端调试时必须启动本地Web服务器,用于接收Azure返回的授权码回调; - 移动端使用自定义URL Scheme作为重定向URI时,无需启动本地Web服务器,直接通过App的URL Scheme回调即可。
内容的提问来源于stack exchange,提问作者Sara Petrovic
相关产品推荐
相关产品推荐

