From 83b7872e95f125556a5b3fa1caf06cc8ab5fe4b0 Mon Sep 17 00:00:00 2001 From: Ricardo Boss Date: Wed, 14 Feb 2024 02:08:12 +0100 Subject: [PATCH] Started work on authentication abstractions --- lib/kiota_abstractions.dart | 5 +++ .../authentication/access_token_provider.dart | 14 +++++++ .../allowed_hosts_validator.dart | 41 +++++++++++++++++++ .../anonymous_authentication_provider.dart | 9 ++++ .../authentication_provider.dart | 11 +++++ 5 files changed, 80 insertions(+) create mode 100644 lib/src/authentication/access_token_provider.dart create mode 100644 lib/src/authentication/allowed_hosts_validator.dart create mode 100644 lib/src/authentication/anonymous_authentication_provider.dart create mode 100644 lib/src/authentication/authentication_provider.dart diff --git a/lib/kiota_abstractions.dart b/lib/kiota_abstractions.dart index 44c1695..7d891cd 100644 --- a/lib/kiota_abstractions.dart +++ b/lib/kiota_abstractions.dart @@ -7,12 +7,17 @@ library kiota_abstractions; import 'dart:async'; +import 'dart:collection'; import 'dart:math'; import 'dart:typed_data'; import 'package:kiota_abstractions/src/case_insensitive_map.dart'; import 'package:std_uritemplate/std_uritemplate.dart'; +part 'src/authentication/allowed_hosts_validator.dart'; +part 'src/authentication/access_token_provider.dart'; +part 'src/authentication/anonymous_authentication_provider.dart'; +part 'src/authentication/authentication_provider.dart'; part 'src/api_client_builder.dart'; part 'src/base_request_builder.dart'; part 'src/error_mappings.dart'; diff --git a/lib/src/authentication/access_token_provider.dart b/lib/src/authentication/access_token_provider.dart new file mode 100644 index 0000000..59a4b21 --- /dev/null +++ b/lib/src/authentication/access_token_provider.dart @@ -0,0 +1,14 @@ +part of '../../kiota_abstractions.dart'; + +/// Defines a contract for obtaining an access token for a given url. +abstract class AccessTokenProvider { + /// Gets an access token for the given url and additional authentication + /// context. + Future getAuthorizationToken( + Uri uri, [ + Map? additionalAuthenticationContext, + ]); + + /// The [AllowedHostsValidator] to use when validating the host of the url. + AllowedHostsValidator get allowedHostsValidator; +} diff --git a/lib/src/authentication/allowed_hosts_validator.dart b/lib/src/authentication/allowed_hosts_validator.dart new file mode 100644 index 0000000..19f6318 --- /dev/null +++ b/lib/src/authentication/allowed_hosts_validator.dart @@ -0,0 +1,41 @@ +part of '../../kiota_abstractions.dart'; + +/// Validator for handling allowed hosts for authentication. +class AllowedHostsValidator { + /// Initializes a new instance of the [AllowedHostsValidator] class. + AllowedHostsValidator([Iterable? validHosts]) { + validHosts ??= []; + _validateHosts(validHosts); + _allowedHosts = HashSet( + equals: (a, b) => a.toUpperCase() == b.toUpperCase(), + hashCode: (o) => o.toUpperCase().hashCode, + )..addAll(validHosts); + } + + late final Set _allowedHosts; + + /// Gets the allowed hosts. + Iterable get allowedHosts => _allowedHosts; + + /// Sets the allowed hosts. + set allowedHosts(Iterable value) { + _validateHosts(value); + _allowedHosts = HashSet( + equals: (a, b) => a.toUpperCase() == b.toUpperCase(), + hashCode: (o) => o.toUpperCase().hashCode, + )..addAll(value); + } + + /// Validates that the given [uri] is valid. + bool isUrlHostValid(Uri uri) { + return _allowedHosts.isEmpty || _allowedHosts.contains(uri.host); + } + + static void _validateHosts(Iterable hostsToValidate) { + if (hostsToValidate + .map((e) => e.toLowerCase()) + .any((x) => x.startsWith('http://') || x.startsWith('https://'))) { + throw ArgumentError('Host should not contain http or https prefix'); + } + } +} diff --git a/lib/src/authentication/anonymous_authentication_provider.dart b/lib/src/authentication/anonymous_authentication_provider.dart new file mode 100644 index 0000000..3b41921 --- /dev/null +++ b/lib/src/authentication/anonymous_authentication_provider.dart @@ -0,0 +1,9 @@ +part of '../../kiota_abstractions.dart'; + +/// This authentication provider does not perform any authentication. +class AnonymousAuthenticationProvider implements AuthenticationProvider { + @override + Future authenticateRequest(RequestInformation request, [Map? additionalAuthenticationContext]) { + return Future.value(); + } +} diff --git a/lib/src/authentication/authentication_provider.dart b/lib/src/authentication/authentication_provider.dart new file mode 100644 index 0000000..0e438cc --- /dev/null +++ b/lib/src/authentication/authentication_provider.dart @@ -0,0 +1,11 @@ +part of '../../kiota_abstractions.dart'; + +/// Authenticates the application request. +abstract class AuthenticationProvider { + /// Authenticates the give [request] with the given + /// [additionalAuthenticationContext]. + Future authenticateRequest( + RequestInformation request, [ + Map? additionalAuthenticationContext, + ]); +}