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

Flutter Web端对接Tesla API:如何拦截OAuth2重定向URI?

使用flutter_web_auth_2实现Tesla OAuth2登录的问题

我正在用flutter_web_auth_2开发Web应用,通过OAuth2访问Tesla账户,当前运行在Web环境。Tesla的重定向URI固定为https://auth.tesla.com/void/callback。调用authenticate方法能打开Tesla授权端点的新标签页完成登录,但应用无法获取重定向URL,反而跳转到Tesla的404页面。

flutter_web_auth_2文档提到需要创建一个端点页面,将重定向信息传递给应用,但我不确定能否在这个固定地址下设置端点?如果不可行,该如何获取重定向结果?其他支持第三方OAuth2登录的网站是如何拦截redirect_uri的?它们是否可以在自身域名内指定自定义URI?


补充说明

附上代码参考,我是Flutter/Dart新手,代码可能不够规范,欢迎指正。打算先在Android移动端测试认证,再迁移到Web应用。

1. 抽象类WebAuthService

abstract class WebAuthService {
  final String authUrl;
  final String urlScheme;

  WebAuthService(this.authUrl, this.urlScheme);

  Future<String> authenticate();
}

2. TeslaAuth实现类

class TeslaAuth extends WebAuthService
{
  TeslaAuth() : super("https://auth.tesla.com/oauth2/v3/authorize", "https");

  @override
  Future<String> authenticate() async {
    var request = TeslaAuthRequestHelper().asRequest();
    var response = await http.Client().get(request);
    if(response.statusCode == 200) {
      return response.body;
    } else {
      return "";
    }
  }
}

3. TeslaAuthRequestHelper类

class TeslaAuthRequestHelper
{

  final clientId = "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384";
  final clientSecret = "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3";
  late final String codeVerifier;
  late final String codeChallenge;
  final codeChallengeMethod = "S256";
  final redirectUri = "https://auth.tesla.com/void/callback";
  final responseType = "code";
  final scope = "openid email offline_access";
  final state = utf8.fuse(base64Url).encode(getRandomString(20));

  static const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
  static final Random _rnd = Random();

  static String getRandomString(int length) => String.fromCharCodes(Iterable.generate(
      length, (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length))));
  TeslaAuthRequestHelper() {
    codeVerifier = getRandomString(87);
    // 创建融合utf8和base64url的编解码器,先将字符串编码为utf-8,再编码为base64Url
    codeChallenge = utf8.fuse(base64Url).encode(codeVerifier);
  }

  Uri asRequest() {
    return Uri.https('auth.tesla.com', 'oauth2/v3/authorize', {
      "client_id": "ownerapi",
      // "client_secret": clientSecret,
      "code_challenge": codeChallenge,
      "code_challenge_method": codeChallengeMethod,
      "redirect_uri": redirectUri,
      "response_type": responseType,
      "scope": scope,
      "state": state,
    });
  }
}

4. 主Widget代码

final authService = TeslaAuthService();
final auth2 = TeslaAuth();

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // 应用根Widget
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tesla Authorizer',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Tesla Web Auth Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _result = '';

  @override
  void initState() {
    super.initState();
    print("Current Uri : ${Uri.base}");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Result: $_result\n'),
            const SizedBox(height: 80),
            ElevatedButton(
                onPressed: () async {
                  _result = await authService.authenticate();
                  print(_result);
                },
                child: const Text('Authenticate'))
          ],
        ),
      ),
    );
  }
}

5. Android Manifest配置

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="tesla_auth"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- 指定Android进程启动后立即应用的主题,Flutter UI初始化时对用户可见,之后用于确定Flutter UI背后的窗口背景 -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
                android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
                android:exported="true">
            <intent-filter android:label="flutter_web_auth_2">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="https" />
            </intent-filter>
        </activity>
        <!-- 不要删除下面的meta-data,Flutter工具用它生成GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

在Pixel 4a上测试时,登录后WebView无法返回应用,显示404页面,地址栏中可见重定向URL。已按照flutter_web_auth_2文档建议,在Manifest文件中添加了额外的activity标签。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:04:51