mirror of
https://github.com/foss42/apidash.git
synced 2025-12-04 20:13:56 +08:00
feat: add oauth2 ui and authorzation code grant handling
This commit is contained in:
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user