Flutter Web:无法使用 Google Drive API 获取授权客户端


Error: Failed to get user consent: idpiframe_initialization_failed.

at Object.createErrorWithStack (http://localhost:56990/dart_sdk.js:4368:12)
at Object._rethrow (http://localhost:56990/dart_sdk.js:38289:16)
at async._AsyncCallbackEntry.new.callback (http://localhost:56990/dart_sdk.js:38283:13)
at Object._microtaskLoop (http://localhost:56990/dart_sdk.js:38115:13)
at _startMicrotaskLoop (http://localhost:56990/dart_sdk.js:38121:13)
at http://localhost:56990/dart_sdk.js:33618:9

浏览器显示登录窗口,但同时抛出上面的错误,并且不等待用户的响应。

import "package:googleapis_auth/auth_browser.dart";
var id = new auth.ClientId('APP_ID.apps.googleusercontent.com', null);
var scopes = [drive.DriveApi.DriveFileScope, drive.DriveApi.DriveScope];
createImplicitBrowserFlow(id, scopes).then((BrowserOAuth2Flow flow) {
flow.clientViaUserConsent().then((AuthClient client) {
print(client); // never execute this
client.close();
flow.close();
});
});

对于Android/iOS,我使用auth_io.dart,没有问题

这与obtainAccessCredentialsViaUserConsent有关,是预期行为:

https://pub.dev/documentation/googleapis_auth/latest/auth_browser/BrowserOAuth2Flow/obtainAccessCredentialsViaUserConsent.html

如果immediate为true,则不会有用户参与。如果用户未登录或尚未授予该应用程序访问时,将抛出UserConsentException。

如果immediate为false,则可能会要求用户登录(如果不是已登录(,并可能被要求授予应用程序访问权限(如果应用程序以前未被授予访问权限(。。。这个如果用户具有给定应用程序对其数据的访问权限。否则,未来完成UserConsentException。

样本

查看示例代码中的异常/承诺处理:https://github.com/dart-archive/googleapis_examples/blob/master/drive_search_web/web/index.dart#L36

你需要这样的东西:

var id = new ClientId("client-id.apps.googleusercontent.com", null);
var scopes = [drive.DriveApi.DriveFileScope, drive.DriveApi.DriveScope];
var responseTypes = [ResponseType.token, ResponseType.idToken];
// Initialize the browser oauth2 flow functionality.
createImplicitBrowserFlow(id, scopes).then((BrowserOAuth2Flow flow) {
flow.obtainAccessCredentialsViaUserConsent(immediate: true, responseTypes: responseTypes).then((AccessCredentials credentials) async {
handleAccessCredentials(flow, credentials);
}).catchError((e) {
print('exception 1: ${e.toString()}');
flow.obtainAccessCredentialsViaUserConsent(immediate: false, responseTypes: responseTypes).then((AccessCredentials credentials) async {
handleAccessCredentials(flow, credentials);
}).catchError((e) {
print('exception 2: ${e.toString()}');
});
});
});
static void handleAccessCredentials(flow, credentials) {
// Credentials are available in [credentials].
print(
'received credentials access:${credentials.accessToken}, refreshToken:${credentials.refreshToken} ' +
'id:${credentials.idToken}');
flow.close();
}

您应该考虑使用PCKE,因为它被认为更安全。

后端的ID/刷新令牌

如果你想使用";代码授权";grant方法,那么您需要以不同的方式处理此问题。

idTokenrefreshToken需要在设置了clientIdclientSecret的情况下从服务器端交换您的授权码accessToken

https://github.com/dart-lang/googleapis/issues/205https://developers.google.com/identity/protocols/oauth2/native-app#exchange-授权码

这是前端(Dart、Flutter(和后端之间的不同集成模式,因此您可能需要一些自定义的云功能。

最新更新