mirror of
https://github.com/foss42/apidash.git
synced 2025-12-05 04:18:56 +08:00
feat: add oauth2 ui and authorzation code grant handling
This commit is contained in:
@@ -9,6 +9,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
app_links:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "85ed8fc1d25a76475914fff28cc994653bd900bc2c26e4b57a49e097febb54ba"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.0"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_linux
|
||||
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
app_links_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_web
|
||||
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -88,6 +120,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
desktop_webview_window:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: desktop_webview_window
|
||||
sha256: "57cf20d81689d5cbb1adfd0017e96b669398a669d927906073b0e42fc64111c0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
ed25519_edwards:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -104,6 +144,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -130,6 +178,27 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_auth_2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_web_auth_2
|
||||
sha256: "3c14babeaa066c371f3a743f204dd0d348b7d42ffa6fae7a9847a521aff33696"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
flutter_web_auth_2_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_web_auth_2_platform_interface
|
||||
sha256: c63a472c8070998e4e422f6b34a17070e60782ac442107c70000dd1bed645f4d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
freezed_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -138,6 +207,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
gtk:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gtk
|
||||
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -226,6 +303,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
oauth2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: oauth2
|
||||
sha256: c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -234,6 +319,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.17"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -242,6 +375,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -318,6 +467,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.16"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.3"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -342,6 +555,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
webview_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: c3e4fe614b1c814950ad07186007eff2f2e5dd2935eba7b9a9a1af8e5885f1ba
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.13.0"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: "9573ad97890d199ac3ab32399aa33a5412163b37feb573eb5b0a76b35e9ffe41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.2"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_platform_interface
|
||||
sha256: f0dc2dc3a2b1e3a6abdd6801b9355ebfeb3b8f6cde6b9dc7c9235909c4a1f147
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.1"
|
||||
webview_flutter_wkwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: "71523b9048cf510cfa1fd4e0a3fa5e476a66e0884d5df51d59d5023dba237107"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.22.1"
|
||||
window_to_front:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: window_to_front
|
||||
sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.3"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -352,4 +613,4 @@ packages:
|
||||
version: "6.5.0"
|
||||
sdks:
|
||||
dart: ">=3.8.0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
flutter: ">=3.27.0"
|
||||
|
||||
@@ -43,6 +43,15 @@ const kJwtAlgos = [
|
||||
'EdDSA',
|
||||
];
|
||||
|
||||
enum OAuth2GrantType {
|
||||
authorizationCode("Authorization Code"),
|
||||
clientCredentials("Client Credentials"),
|
||||
resourceOwnerPassword("Resource Owner Password");
|
||||
|
||||
const OAuth2GrantType(this.displayType);
|
||||
final String displayType;
|
||||
}
|
||||
|
||||
enum HTTPVerb {
|
||||
get("GET"),
|
||||
head("HEAD"),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:better_networking/consts.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'auth_oauth2_model.g.dart';
|
||||
@@ -7,7 +8,7 @@ part 'auth_oauth2_model.freezed.dart';
|
||||
@freezed
|
||||
class AuthOAuth2Model with _$AuthOAuth2Model {
|
||||
const factory AuthOAuth2Model({
|
||||
@Default("authorization_code") String grantType,
|
||||
@Default(OAuth2GrantType.authorizationCode) OAuth2GrantType grantType,
|
||||
|
||||
required String authorizationUrl,
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ AuthOAuth2Model _$AuthOAuth2ModelFromJson(Map<String, dynamic> json) {
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AuthOAuth2Model {
|
||||
String get grantType => throw _privateConstructorUsedError;
|
||||
OAuth2GrantType get grantType => throw _privateConstructorUsedError;
|
||||
String get authorizationUrl => throw _privateConstructorUsedError;
|
||||
String get accessTokenUrl => throw _privateConstructorUsedError;
|
||||
String get clientId => throw _privateConstructorUsedError;
|
||||
@@ -56,7 +56,7 @@ abstract class $AuthOAuth2ModelCopyWith<$Res> {
|
||||
) = _$AuthOAuth2ModelCopyWithImpl<$Res, AuthOAuth2Model>;
|
||||
@useResult
|
||||
$Res call({
|
||||
String grantType,
|
||||
OAuth2GrantType grantType,
|
||||
String authorizationUrl,
|
||||
String accessTokenUrl,
|
||||
String clientId,
|
||||
@@ -112,7 +112,7 @@ class _$AuthOAuth2ModelCopyWithImpl<$Res, $Val extends AuthOAuth2Model>
|
||||
grantType: null == grantType
|
||||
? _value.grantType
|
||||
: grantType // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as OAuth2GrantType,
|
||||
authorizationUrl: null == authorizationUrl
|
||||
? _value.authorizationUrl
|
||||
: authorizationUrl // ignore: cast_nullable_to_non_nullable
|
||||
@@ -189,7 +189,7 @@ abstract class _$$AuthOAuth2ModelImplCopyWith<$Res>
|
||||
@override
|
||||
@useResult
|
||||
$Res call({
|
||||
String grantType,
|
||||
OAuth2GrantType grantType,
|
||||
String authorizationUrl,
|
||||
String accessTokenUrl,
|
||||
String clientId,
|
||||
@@ -244,7 +244,7 @@ class __$$AuthOAuth2ModelImplCopyWithImpl<$Res>
|
||||
grantType: null == grantType
|
||||
? _value.grantType
|
||||
: grantType // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as OAuth2GrantType,
|
||||
authorizationUrl: null == authorizationUrl
|
||||
? _value.authorizationUrl
|
||||
: authorizationUrl // ignore: cast_nullable_to_non_nullable
|
||||
@@ -314,7 +314,7 @@ class __$$AuthOAuth2ModelImplCopyWithImpl<$Res>
|
||||
@JsonSerializable()
|
||||
class _$AuthOAuth2ModelImpl implements _AuthOAuth2Model {
|
||||
const _$AuthOAuth2ModelImpl({
|
||||
this.grantType = "authorization_code",
|
||||
this.grantType = OAuth2GrantType.authorizationCode,
|
||||
required this.authorizationUrl,
|
||||
required this.accessTokenUrl,
|
||||
required this.clientId,
|
||||
@@ -337,7 +337,7 @@ class _$AuthOAuth2ModelImpl implements _AuthOAuth2Model {
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final String grantType;
|
||||
final OAuth2GrantType grantType;
|
||||
@override
|
||||
final String authorizationUrl;
|
||||
@override
|
||||
@@ -453,7 +453,7 @@ class _$AuthOAuth2ModelImpl implements _AuthOAuth2Model {
|
||||
|
||||
abstract class _AuthOAuth2Model implements AuthOAuth2Model {
|
||||
const factory _AuthOAuth2Model({
|
||||
final String grantType,
|
||||
final OAuth2GrantType grantType,
|
||||
required final String authorizationUrl,
|
||||
required final String accessTokenUrl,
|
||||
required final String clientId,
|
||||
@@ -475,7 +475,7 @@ abstract class _AuthOAuth2Model implements AuthOAuth2Model {
|
||||
_$AuthOAuth2ModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get grantType;
|
||||
OAuth2GrantType get grantType;
|
||||
@override
|
||||
String get authorizationUrl;
|
||||
@override
|
||||
|
||||
@@ -9,7 +9,9 @@ part of 'auth_oauth2_model.dart';
|
||||
_$AuthOAuth2ModelImpl _$$AuthOAuth2ModelImplFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _$AuthOAuth2ModelImpl(
|
||||
grantType: json['grantType'] as String? ?? "authorization_code",
|
||||
grantType:
|
||||
$enumDecodeNullable(_$OAuth2GrantTypeEnumMap, json['grantType']) ??
|
||||
OAuth2GrantType.authorizationCode,
|
||||
authorizationUrl: json['authorizationUrl'] as String,
|
||||
accessTokenUrl: json['accessTokenUrl'] as String,
|
||||
clientId: json['clientId'] as String,
|
||||
@@ -30,7 +32,7 @@ _$AuthOAuth2ModelImpl _$$AuthOAuth2ModelImplFromJson(
|
||||
Map<String, dynamic> _$$AuthOAuth2ModelImplToJson(
|
||||
_$AuthOAuth2ModelImpl instance,
|
||||
) => <String, dynamic>{
|
||||
'grantType': instance.grantType,
|
||||
'grantType': _$OAuth2GrantTypeEnumMap[instance.grantType]!,
|
||||
'authorizationUrl': instance.authorizationUrl,
|
||||
'accessTokenUrl': instance.accessTokenUrl,
|
||||
'clientId': instance.clientId,
|
||||
@@ -47,3 +49,9 @@ Map<String, dynamic> _$$AuthOAuth2ModelImplToJson(
|
||||
'identityToken': instance.identityToken,
|
||||
'accessToken': instance.accessToken,
|
||||
};
|
||||
|
||||
const _$OAuth2GrantTypeEnumMap = {
|
||||
OAuth2GrantType.authorizationCode: 'authorizationCode',
|
||||
OAuth2GrantType.clientCredentials: 'clientCredentials',
|
||||
OAuth2GrantType.resourceOwnerPassword: 'resourceOwnerPassword',
|
||||
};
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:better_networking/utils/auth/jwt_auth_utils.dart';
|
||||
import 'package:better_networking/utils/auth/digest_auth_utils.dart';
|
||||
import 'package:better_networking/better_networking.dart';
|
||||
import 'package:better_networking/utils/auth/oauth2_utils.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
Future<HttpRequestModel> handleAuth(
|
||||
HttpRequestModel httpRequestModel,
|
||||
@@ -157,8 +160,54 @@ Future<HttpRequestModel> handleAuth(
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
case APIAuthType.oauth2:
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
final oauth2 = authData.oauth2;
|
||||
|
||||
if (oauth2 == null) {
|
||||
throw Exception("Failed to get OAuth2 Data");
|
||||
}
|
||||
|
||||
if (oauth2.redirectUrl == null) {
|
||||
throw Exception("No Redirect URL found!");
|
||||
}
|
||||
|
||||
//TODO: Create a proper credentials file path, use the existing file utils if needed.
|
||||
final credentialsDir = Directory.systemTemp;
|
||||
final credentialsFile = File(
|
||||
'${credentialsDir.path}/oauth2_credentials.json',
|
||||
);
|
||||
|
||||
switch (oauth2.grantType) {
|
||||
case OAuth2GrantType.authorizationCode:
|
||||
final res = await oAuth2AuthorizationCodeGrantHandler(
|
||||
identifier: oauth2.clientId,
|
||||
secret: oauth2.clientSecret,
|
||||
authorizationEndpoint: Uri.parse(oauth2.authorizationUrl),
|
||||
redirectUrl: Uri.parse(
|
||||
oauth2.redirectUrl ?? "apidash://oauth2/callback",
|
||||
),
|
||||
tokenEndpoint: Uri.parse(oauth2.accessTokenUrl),
|
||||
credentialsFile: credentialsFile,
|
||||
scope: oauth2.scope,
|
||||
);
|
||||
debugPrint(res.credentials.accessToken);
|
||||
|
||||
// Add the access token to the request headers
|
||||
updatedHeaders.add(
|
||||
NameValueModel(
|
||||
name: 'Authorization',
|
||||
value: 'Bearer ${res.credentials.accessToken}',
|
||||
),
|
||||
);
|
||||
updatedHeaderEnabledList.add(true);
|
||||
|
||||
break;
|
||||
case OAuth2GrantType.clientCredentials:
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
case OAuth2GrantType.resourceOwnerPassword:
|
||||
// TODO: Handle this case.
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
return httpRequestModel.copyWith(
|
||||
|
||||
75
packages/better_networking/lib/utils/auth/oauth2_utils.dart
Normal file
75
packages/better_networking/lib/utils/auth/oauth2_utils.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer' show log;
|
||||
import 'dart:io';
|
||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||
import 'package:oauth2/oauth2.dart' as oauth2;
|
||||
|
||||
Future<oauth2.Client> oAuth2AuthorizationCodeGrantHandler({
|
||||
required String identifier,
|
||||
required String secret,
|
||||
required Uri authorizationEndpoint,
|
||||
required Uri tokenEndpoint,
|
||||
required Uri redirectUrl,
|
||||
required File credentialsFile,
|
||||
String? state,
|
||||
String? scope,
|
||||
}) async {
|
||||
if (await credentialsFile.exists()) {
|
||||
try {
|
||||
final json = await credentialsFile.readAsString();
|
||||
|
||||
final credentials = oauth2.Credentials.fromJson(json);
|
||||
|
||||
if (credentials.accessToken.isNotEmpty && !credentials.isExpired) {
|
||||
log('Using existing valid credentials');
|
||||
|
||||
return oauth2.Client(
|
||||
credentials,
|
||||
identifier: identifier,
|
||||
secret: secret,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
log('Error reading existing credentials: $e');
|
||||
}
|
||||
}
|
||||
|
||||
final grant = oauth2.AuthorizationCodeGrant(
|
||||
identifier,
|
||||
authorizationEndpoint,
|
||||
tokenEndpoint,
|
||||
secret: secret,
|
||||
);
|
||||
|
||||
final authorizationUrl = grant.getAuthorizationUrl(
|
||||
redirectUrl,
|
||||
scopes: scope != null ? [scope] : null,
|
||||
state: state,
|
||||
);
|
||||
log('Generated authorization URL: ${authorizationUrl.toString()}');
|
||||
log('Expected redirect URL: ${redirectUrl.toString()}');
|
||||
|
||||
final uri = await FlutterWebAuth2.authenticate(
|
||||
url: authorizationUrl.toString(),
|
||||
callbackUrlScheme: redirectUrl.scheme,
|
||||
options: const FlutterWebAuth2Options(useWebview: true),
|
||||
);
|
||||
|
||||
try {
|
||||
final client = await grant.handleAuthorizationResponse(
|
||||
Uri.parse(uri).queryParameters,
|
||||
);
|
||||
|
||||
log('OAuth2 authorization successful, saving credentials');
|
||||
|
||||
await credentialsFile.writeAsString(client.credentials.toJson());
|
||||
|
||||
return client;
|
||||
} catch (e) {
|
||||
log('Error handling authorization response: $e');
|
||||
|
||||
log('URI query parameters: ${Uri.parse(uri).queryParameters}');
|
||||
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -5,3 +5,5 @@ export 'http_response_utils.dart';
|
||||
export 'string_utils.dart' hide RandomStringGenerator;
|
||||
export 'uri_utils.dart';
|
||||
export 'auth/handle_auth.dart';
|
||||
export 'auth/oauth2_webview_utils.dart';
|
||||
export 'auth/handle_auth_webview.dart';
|
||||
|
||||
@@ -28,6 +28,10 @@ dependencies:
|
||||
json_annotation: ^4.9.0
|
||||
seed: ^0.0.3
|
||||
xml: ^6.3.0
|
||||
oauth2: ^2.0.3
|
||||
flutter_web_auth_2: ^4.1.0
|
||||
app_links: ^6.4.0
|
||||
webview_flutter: ^4.10.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user