-
Notifications
You must be signed in to change notification settings - Fork 247
Expand file tree
/
Copy pathflutter_web_auth.dart
More file actions
58 lines (49 loc) · 2.8 KB
/
flutter_web_auth.dart
File metadata and controls
58 lines (49 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import 'dart:async';
import 'dart:core';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart' show MethodChannel;
class _OnAppLifecycleResumeObserver extends WidgetsBindingObserver {
final Function onResumed;
_OnAppLifecycleResumeObserver(this.onResumed);
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
onResumed();
}
}
}
class FlutterWebAuth {
static const MethodChannel _channel = const MethodChannel('flutter_web_auth');
static RegExp _schemeRegExp = new RegExp(r"^[a-z][a-z0-9+.-]*$");
static final _OnAppLifecycleResumeObserver _resumedObserver = _OnAppLifecycleResumeObserver(() {
_cleanUpDanglingCalls(); // unawaited
});
/// Ask the user to authenticate to the specified web service.
///
/// The page pointed to by [url] will be loaded and displayed to the user. From the page, the user can authenticate herself and grant access to the app. On completion, the service will send a callback URL with an authentication token, and this URL will be result of the returned [Future].
///
/// [callbackUrlScheme] should be a string specifying the scheme of the url that the page will redirect to upon successful authentication.
/// [preferEphemeral] if this is specified as `true`, an ephemeral web browser session will be used where possible (`FLAG_ACTIVITY_NO_HISTORY` on Android, `prefersEphemeralWebBrowserSession` on iOS/macOS)
///
/// [debug] flag - used for avoid comparing Url.base.origin and messageEvent.origin that gives us opportunity to test without deploy (ex. deployed back example.com and local flutter app localhost)
static Future<String> authenticate({required String url, required String callbackUrlScheme, bool? preferEphemeral, bool? debug}) async {
if (!_schemeRegExp.hasMatch(callbackUrlScheme)) {
throw ArgumentError.value(callbackUrlScheme, 'callbackUrlScheme', 'must be a valid URL scheme');
}
WidgetsBinding.instance.removeObserver(_resumedObserver); // safety measure so we never add this observer twice
WidgetsBinding.instance.addObserver(_resumedObserver);
return await _channel.invokeMethod('authenticate', <String, dynamic>{
'url': url,
'debug': debug ?? false,
'callbackUrlScheme': callbackUrlScheme,
'preferEphemeral': preferEphemeral ?? false,
}) as String;
}
/// On Android, the plugin has to store the Result callbacks in order to pass the result back to the caller of
/// `authenticate`. But if that result never comes the callback will dangle around forever. This can be called to
/// terminate all `authenticate` calls with an error.
static Future<void> _cleanUpDanglingCalls() async {
await _channel.invokeMethod('cleanUpDanglingCalls');
WidgetsBinding.instance.removeObserver(_resumedObserver);
}
}