You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用url_launcher实现OAuth授权并捕获authorization_code问题

Flutter 用 url_launcher 实现 OAuth 授权并捕获 authorization_code

问题解决步骤

1. 配置应用 URL Scheme

要让浏览器能跳转回你的应用,必须先在各平台配置对应的 URL Scheme:

iOS 配置(Info.plist)

打开 ios/Runner/Info.plist,添加以下内容:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myappurlschemes</string> <!-- 替换成你自己的 Scheme -->
    </array>
  </dict>
</array>

Android 配置(AndroidManifest.xml)

打开 android/app/src/main/AndroidManifest.xml,在 <activity> 标签内添加 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" />
  <data android:scheme="myappurlschemes" /> <!-- 与 iOS 保持一致的 Scheme -->
</intent-filter>

2. 修正授权请求的 redirect_uri

把原来的 redirect_uri 改成完整的 Scheme URI,比如 myappurlschemes://auth/callback,确保授权服务器能正确跳转回应用:

final url = Uri.https('auth_link', '/login', {
  'client_id': "clientid",
  'redirect_uri': 'myappurlschemes://auth/callback', // 完整的跳转地址
  'grant_type': 'authorization_code',
  'response_type': 'code',
  'code_challenge': codeChallenge,
  'code_challenge_method': 'S256',
  'scope': 'openid profile offline_access email', // 用空格分隔 scope,部分服务器不支持+
});

3. 监听深链接捕获 authorization_code

使用 uni_links 包(非 OAuth 相关,仅用于处理深链接)监听应用被唤起时的链接,从中提取授权码:

添加依赖

在 pubspec.yaml 中添加:

dependencies:
  url_launcher: ^6.2.4
  uni_links: ^0.5.1

完整实现代码

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:uni_links/uni_links.dart';

class OAuthLoginPage extends StatefulWidget {
  const OAuthLoginPage({super.key});

  @override
  State<OAuthLoginPage> createState() => _OAuthLoginPageState();
}

class _OAuthLoginPageState extends State<OAuthLoginPage> with WidgetsBindingObserver {
  StreamSubscription? _linkSubscription;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _setupLinkListener();
  }

  @override
  void dispose() {
    _linkSubscription?.cancel();
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  // 初始化链接监听,处理冷启动和热启动的跳转
  Future<void> _setupLinkListener() async {
    // 处理应用未启动时的跳转链接
    final initialLink = await getInitialLink();
    if (initialLink != null) {
      _extractAuthCode(initialLink);
    }

    // 监听应用后台时的跳转链接
    _linkSubscription = linkStream.listen((link) {
      if (link != null) {
        _extractAuthCode(link);
      }
    });
  }

  // 从跳转链接中提取 authorization_code
  void _extractAuthCode(String link) {
    final uri = Uri.parse(link);
    final authCode = uri.queryParameters['code'];
    if (authCode != null) {
      // 拿到授权码后,执行后续逻辑(比如换取 token)
      print('获取到授权码:$authCode');
      // 这里可以添加跳转、存储等操作
    }
  }

  // 启动授权页面
  Future<void> _launchAuthPage() async {
    final codeChallenge = 'your_generated_code_challenge'; // 替换为实际生成的 code challenge
    final authUrl = Uri.https('auth_link', '/login', {
      'client_id': "clientid",
      'redirect_uri': 'myappurlschemes://auth/callback',
      'grant_type': 'authorization_code',
      'response_type': 'code',
      'code_challenge': codeChallenge,
      'code_challenge_method': 'S256',
      'scope': 'openid profile offline_access email',
    });

    if (await canLaunchUrl(authUrl)) {
      // 使用默认浏览器打开授权页面
      await launchUrl(authUrl, mode: LaunchMode.externalApplication);
    } else {
      throw '无法打开授权链接';
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('OAuth 登录')),
      body: Center(
        child: ElevatedButton(
          onPressed: _launchAuthPage,
          child: const Text('开始授权登录'),
        ),
      ),
    );
  }
}

关键说明

  • 确保 URL Scheme 在 iOS 和 Android 配置中完全一致,否则无法唤起应用
  • redirect_uri 必须是授权服务器已配置允许的地址,否则会被拒绝跳转
  • 使用 LaunchMode.externalApplication 强制调用系统默认浏览器,符合你的需求
  • uni_links 仅用于监听深链接,不属于 OAuth 相关包,满足你不想用 OAuth 包的要求

内容的提问来源于stack exchange,提问作者VolkanUstekidag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:07:50