-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathoauth.dart
138 lines (118 loc) · 4.76 KB
/
oauth.dart
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import 'dart:collection';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:visa/engine/debug.dart';
import 'package:webview_flutter/webview_flutter.dart';
/// This class contains [OAuth] data and
/// functionality. It has one public method
/// that returns a [WebView] which has been set up
/// for OAuth 2.0 Authentication.
class OAuth {
OAuth(
{required this.baseUrl,
required this.clientID,
required this.redirectUri,
required this.state,
required this.scope,
required this.debugMode,
this.clientSecret,
this.responseType,
this.otherQueryParams});
final String baseUrl; // OAuth url
final String clientID; // OAuth clientID
final String? clientSecret; // OAuth clientSecret
final String? responseType; // OAuth clientSecret
final String redirectUri; // OAuth redirectUri
final String state; // OAuth state
final String scope; // OAuth scope
final Map<String, String>? otherQueryParams;
final bool debugMode; // Debug mode?
static const String TOKEN_KEY = 'access_token'; // OAuth token key
static const String CODE_KEY = 'code'; // OAuth code key
static const String STATE_KEY = 'state'; // OAuth state key
static const String SCOPE_KEY = 'scope'; // OAuth scope key
static const String CLIENT_ID_KEY = 'clientID'; // custom client id key
static const String CLIENT_SECRET_KEY =
'clientSecret'; // custom client secret key
static const String REDIRECT_URI_KEY =
'redirectURI'; // custom redirect uri key
final String userAgent = 'Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/87.0.4280.86 Mobile Safari/537.36'; // UA
final Debug _debug = Debug(prefix: 'In OAuth ->');
/// Sets up a [WebView] for OAuth authentication.
/// [onDone] is called when authentication is
/// completed successfully.
WebView authenticate({required Function onDone, bool clearCache = false}) {
String clientSecretQuery =
clientSecret != null ? '&client_secret=$clientSecret' : '';
String responseTypeQuery =
'&response_type=${responseType == null ? 'token' : responseType}';
String otherParams = '';
if (otherQueryParams != null) {
for (String key in otherQueryParams!.keys) {
otherParams += '&$key=${otherQueryParams![key]}';
}
}
String authUrl = '$baseUrl'
'?client_id=$clientID'
'$clientSecretQuery'
'&redirect_uri=$redirectUri'
'&state=$state'
'&scope=$scope'
'$responseTypeQuery'
'$otherParams';
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
return WebView(
onWebViewCreated: (controller) async {
if (clearCache) {
if (debugMode) _debug.info('Clearing Cache and Cookies...');
CookieManager cookieManager = CookieManager();
await cookieManager.clearCookies();
await controller.clearCache();
}
},
userAgent: userAgent,
initialUrl: authUrl,
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: _getNavigationDelegate(onDone));
}
/// Returns a navigation delegate that attempts
/// to match the redirect url whenever the browser
/// navigates to a new page. Once the redirect url
/// is found, it calls the [onDone] callback.
_getNavigationDelegate(onDone) => (NavigationRequest request) {
String url = request.url;
if (debugMode) _debug.info('Inspecting Url Before Loading: $url');
if (url.startsWith(redirectUri)) {
if (debugMode) _debug.info('Found Redirect Url: $url');
var returnedData = _getQueryParams(url);
returnedData[CLIENT_ID_KEY] = clientID;
returnedData[REDIRECT_URI_KEY] = redirectUri;
returnedData[STATE_KEY] = state;
if (clientSecret != null) {
returnedData[CLIENT_SECRET_KEY] = clientSecret!;
}
onDone(returnedData);
} else if (debugMode) {
_debug.info('Redirect Url Not Found');
_debug.info('Url = $url');
//_debug.info('Redirect Url = $redirectUri');
}
return NavigationDecision.navigate;
};
/// Parses url query params into a map
/// @param url: The url to parse.
Map<String, String> _getQueryParams(String url) {
if (debugMode) _debug.info('Getting Query Params From Url: $url');
final List<String> urlParams = url.split(RegExp('[?&# ]'));
final Map<String, String> queryParams = HashMap();
List<String> parts;
for (String param in urlParams) {
if (!param.contains('=')) continue;
parts = param.split('=');
queryParams[parts[0]] = Uri.decodeFull(parts[1]);
}
if (debugMode) _debug.info('Extracted Query Params: $queryParams');
return queryParams;
}
}