【发布时间】:2021-12-14 20:28:30
【问题描述】:
所以大部分关于 Authorization 的教程只是使用 Firebase 的 Auth,并且大部分后端工作都得到了处理。
我需要在 Dart/Flutter 中为 Intuit 的 Quickbooks Online 创建一个 OAuth 客户端。
我的基本理解是当用户启动我的 Flutter Web 应用程序时,我会弹出一个屏幕来启动 Authorization Code Grant - OAuth。
他们使用此弹出屏幕登录 Intuit Quickbooks,然后授予我的应用程序权限。
此时我的应用程序应该会收到一个授权码。
我猜我需要将此授权码存储在我的 Google Cloud Firestore 中?
我需要将此授权码发送回 Intuit 并接收两件事:访问令牌和刷新令牌。
我想我也应该将这些存储在 Cloud Firestore 中?
但我看不出云功能在这张照片中的位置。我是否使用云函数向 Cloud Firestore 写入/读取?
如何处理用户会话?我还需要解决状态管理问题。
我开始明白为什么很多人只使用 Firebase Auth 的内置开箱即用功能,因为在 Dart/Flutter 中开发自定义 OAuth 客户端是一项艰巨的任务。
我开始感到困惑和迷茫。我需要一些建议或组织,因为我忽略了需要修改、设计或开发的内容。
Main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:html' as html;
import 'dart:convert';w
import 'package:cloud_firestore/cloud_firestore.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(App());
}
class App extends StatefulWidget {
// Create the initialization Future outside of `build`:
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
@override
Widget build(BuildContext context) {
return FutureBuilder(
/// Initialize FlutterFire:
future: _initialization,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
/// Once complete, show your application
if (snapshot.connectionState == ConnectionState.done) {
return MyApp();
}
/// Otherwise, show something whilst waiting for initialization to complete
return CircularProgressIndicator();
},
);
}
}
/// Client id provided by Intuit, our production app ClientID
const String clientId = "ABS0R9arxiHjNcAb0rP7OMs8aS1FRiMIINxOkhQimUPewGmQ2H";
const String clientSecret = "";
class MyApp extends StatelessWidget {
/// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: cPrimaryColor,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late String _token;
late html.WindowBase _popupWin;
Future<String> _validateToken() async {
final response = await http.get(
Uri.parse('https://appcenter.intuit.com/connect/oauth2'),
headers: {'Authorization': 'OAuth $_token'},
);
return (jsonDecode(response.body) as Map<String, dynamic>)['login']
.toString();
}
void _login(String data) {
/// Parse data to extract the token.
final receivedUri = Uri.parse(data);
/// Close the popup window
if (_popupWin != null) {
_popupWin.close();
_popupWin == null; // changed = to ==
}
setState(() => _token = receivedUri.fragment
.split('&')
.firstWhere((e) => e.startsWith('access_token='))
.substring('access_token='.length));
}
@override
void initState() {
super.initState();
/// Listen to message send with `postMessage`.
html.window.onMessage.listen((event) {
/// The event contains the token which means the user is connected.
if (event.data.toString().contains('access_token=')) {
_login(event.data);
}
});
/// You are not connected so open the Intuit authentication page.
WidgetsBinding.instance!.addPostFrameCallback((_) {
final currentUri = Uri.base;
final redirectUri = Uri(
host: currentUri.host,
scheme: currentUri.scheme,
port: currentUri.port,
path: '/static.html',
);
final authUrl = //TODO add state=security_token
'https://appcenter.intuit.com/connect/oauth2?client_id=ABS0R9arxiHjNcAb0rP7OMs8aS1FRiMIINxOkhQimUPewGmQ2H&response_type=code&scope=com.intuit.quickbooks.accounting&redirect_uri=https://google.com/&state=security_token%3D138r5719ru3e1%26url%3Dhttps://qb-payment-app.web.app/';
_popupWin = html.window.open(
authUrl, "Intuit QuickBooks Online Auth", "width=800, height=900, scrollbars=yes");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My App Bar'),
)
);
}
}
【问题讨论】:
标签: firebase flutter dart google-cloud-firestore oauth-2.0