diff --git a/Directory.Build.props b/Directory.Build.props
index 6d41e536..75dc08ed 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -24,5 +24,6 @@
11.0
true
+ CS8785
diff --git a/Directory.Packages.props b/Directory.Packages.props
index a2ed1444..36ac2ed5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,7 +1,7 @@
-
+
diff --git a/src/D2L.Security.OAuth2.TestFramework/TestAccessToken.cs b/src/D2L.Security.OAuth2.TestFramework/TestAccessToken.cs
index ab2dbb82..3651c1d7 100644
--- a/src/D2L.Security.OAuth2.TestFramework/TestAccessToken.cs
+++ b/src/D2L.Security.OAuth2.TestFramework/TestAccessToken.cs
@@ -6,7 +6,6 @@
using System.Threading.Tasks;
using D2L.Security.OAuth2.Provisioning;
using D2L.Security.OAuth2.Scopes;
-using D2L.Services;
using IAccessToken = D2L.Security.OAuth2.Provisioning.IAccessToken;
namespace D2L.Security.OAuth2.TestFramework {
diff --git a/src/D2L.Security.OAuth2/Keys/Default/Data/IJwksProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/Data/IJwksProvider.cs
index 8a86dfbe..cb1a5767 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/Data/IJwksProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/Data/IJwksProvider.cs
@@ -1,8 +1,11 @@
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
namespace D2L.Security.OAuth2.Keys.Default.Data {
- internal interface IJwksProvider {
+ internal partial interface IJwksProvider {
+ [GenerateSync]
Task RequestJwksAsync();
+ [GenerateSync]
Task RequestJwkAsync( string keyId );
string Namespace { get; }
}
diff --git a/src/D2L.Security.OAuth2/Keys/Default/Data/JwksProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/Data/JwksProvider.cs
index bb5e62b2..5fab2a19 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/Data/JwksProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/Data/JwksProvider.cs
@@ -3,12 +3,13 @@
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
+using D2L.CodeStyle.Annotations;
+using D2L.Security.OAuth2.Utilities;
using D2L.Security.OAuth2.Validation.Exceptions;
-using D2L.Services;
namespace D2L.Security.OAuth2.Keys.Default.Data {
- internal sealed class JwksProvider : IJwksProvider {
- private readonly HttpClient m_httpClient;
+ internal sealed partial class JwksProvider : IJwksProvider {
+ private readonly ID2LHttpClient m_httpClient;
private readonly Uri m_jwksEndpoint;
private readonly Uri m_jwkEndpoint;
@@ -17,11 +18,12 @@ public JwksProvider(
Uri jwksEndpoint,
Uri jwkEndpoint
) {
- m_httpClient = httpClient;
+ m_httpClient = new D2LHttpClient( httpClient );
m_jwksEndpoint = jwksEndpoint;
m_jwkEndpoint = jwkEndpoint;
}
+ [GenerateSync]
async Task IJwksProvider.RequestJwksAsync() {
try {
using( HttpResponseMessage response = await m_httpClient.GetAsync( m_jwksEndpoint ).ConfigureAwait( false ) ) {
@@ -37,6 +39,7 @@ async Task IJwksProvider.RequestJwksAsync() {
}
}
+ [GenerateSync]
async Task IJwksProvider.RequestJwkAsync( string keyId ) {
var url = GetJwkEndpoint( m_jwkEndpoint, keyId );
if( url == null ) {
diff --git a/src/D2L.Security.OAuth2/Keys/Default/ExpiringPublicKeyDataProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/ExpiringPublicKeyDataProvider.cs
index 40fcf57d..48fe117f 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/ExpiringPublicKeyDataProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/ExpiringPublicKeyDataProvider.cs
@@ -2,11 +2,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
using D2L.Security.OAuth2.Utilities;
using D2L.Services;
namespace D2L.Security.OAuth2.Keys.Default {
- internal sealed class ExpiringPublicKeyDataProvider : ISanePublicKeyDataProvider {
+ internal sealed partial class ExpiringPublicKeyDataProvider : ISanePublicKeyDataProvider {
private readonly IPublicKeyDataProvider m_inner;
private readonly IDateTimeProvider m_dateTimeProvider;
@@ -18,6 +19,7 @@ IDateTimeProvider dateTimeProvider
m_dateTimeProvider = dateTimeProvider ?? throw new ArgumentException( nameof( dateTimeProvider ) );
}
+ [GenerateSync]
async Task IPublicKeyDataProvider.GetByIdAsync( Guid id ) {
// We are intentionally fetching *all* public keys from the database
// here. This allows us to clean up all expired public keys even if
@@ -44,6 +46,7 @@ async Task IPublicKeyDataProvider.GetByIdAsync( Guid id ) {
return key;
}
+ [GenerateSync]
async Task> IPublicKeyDataProvider.GetAllAsync() {
IEnumerable keys = await m_inner
.GetAllAsync()
@@ -62,14 +65,17 @@ async Task> IPublicKeyDataProvider.GetAllAsync() {
return result;
}
+ [GenerateSync]
Task IPublicKeyDataProvider.SaveAsync( Guid id, JsonWebKey key ) {
return m_inner.SaveAsync( id, key );
}
+ [GenerateSync]
Task IPublicKeyDataProvider.DeleteAsync( Guid id ) {
return m_inner.DeleteAsync( id );
}
+ [GenerateSync]
private async Task KeyExpiryHelperAsync( JsonWebKey key ) {
if( key == null ) {
return true;
diff --git a/src/D2L.Security.OAuth2/Keys/Default/IPublicKeyProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/IPublicKeyProvider.cs
index b507be28..ccd81aa7 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/IPublicKeyProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/IPublicKeyProvider.cs
@@ -1,23 +1,25 @@
-using System;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
namespace D2L.Security.OAuth2.Keys.Default {
///
/// An abstraction for fetching public keys
///
- internal interface IPublicKeyProvider {
+ internal partial interface IPublicKeyProvider {
///
/// Gets an individual by its
///
/// The key id (kid)
/// The or null if the key doesn't exist or has expired
+ [GenerateSync]
Task GetByIdAsync( string id );
///
/// Perform steps to potentially make future key fetches faster.
///
+ [GenerateSync]
Task PrefetchAsync();
}
diff --git a/src/D2L.Security.OAuth2/Keys/Default/LocalPublicKeyProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/LocalPublicKeyProvider.cs
index 2adecdaa..87c0cdb0 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/LocalPublicKeyProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/LocalPublicKeyProvider.cs
@@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
using D2L.Security.OAuth2.Keys.Caching;
using D2L.Security.OAuth2.Validation.Exceptions;
using D2L.Services;
namespace D2L.Security.OAuth2.Keys.Default {
- internal sealed class LocalPublicKeyProvider : IPublicKeyProvider {
+ internal sealed partial class LocalPublicKeyProvider : IPublicKeyProvider {
private const string PUBLIC_KEY_SOURCE = "Local DB";
@@ -21,6 +22,7 @@ IInMemoryPublicKeyCache cache
m_cache = cache ?? throw new ArgumentNullException( nameof( cache ) );
}
+ [GenerateSync]
async Task IPublicKeyProvider.PrefetchAsync() {
IEnumerable jwks = await m_publicKeyDataProvider
.GetAllAsync()
@@ -42,6 +44,7 @@ async Task IPublicKeyProvider.PrefetchAsync() {
}
}
+ [GenerateSync]
async Task IPublicKeyProvider.GetByIdAsync( string id ) {
D2LSecurityToken result = m_cache.Get( PUBLIC_KEY_SOURCE, id );
if( result != null ) {
diff --git a/src/D2L.Security.OAuth2/Keys/Default/RemotePublicKeyProvider.cs b/src/D2L.Security.OAuth2/Keys/Default/RemotePublicKeyProvider.cs
index fb818ed9..49ee1010 100644
--- a/src/D2L.Security.OAuth2/Keys/Default/RemotePublicKeyProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Default/RemotePublicKeyProvider.cs
@@ -1,12 +1,13 @@
using System;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
using D2L.Security.OAuth2.Keys.Caching;
using D2L.Security.OAuth2.Keys.Default.Data;
using D2L.Security.OAuth2.Validation.Exceptions;
using D2L.Services;
namespace D2L.Security.OAuth2.Keys.Default {
- internal sealed class RemotePublicKeyProvider : IPublicKeyProvider {
+ internal sealed partial class RemotePublicKeyProvider : IPublicKeyProvider {
private readonly IJwksProvider m_jwksProvider;
private readonly IInMemoryPublicKeyCache m_cache;
@@ -18,6 +19,7 @@ IInMemoryPublicKeyCache cache
m_cache = cache;
}
+ [GenerateSync]
async Task IPublicKeyProvider.GetByIdAsync( string id ) {
D2LSecurityToken result = m_cache.Get( m_jwksProvider.Namespace, id );
if( result != null ) {
@@ -38,6 +40,7 @@ async Task IPublicKeyProvider.GetByIdAsync( string id ) {
throw new PublicKeyNotFoundException( id, jwks.Source.AbsoluteUri );
}
+ [GenerateSync]
async Task IPublicKeyProvider.PrefetchAsync() {
JsonWebKeySet jwks = await m_jwksProvider
.RequestJwksAsync()
diff --git a/src/D2L.Security.OAuth2/Keys/Development/InMemoryPublicKeyDataProvider.cs b/src/D2L.Security.OAuth2/Keys/Development/InMemoryPublicKeyDataProvider.cs
index e38cd27d..39c2dce3 100644
--- a/src/D2L.Security.OAuth2/Keys/Development/InMemoryPublicKeyDataProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/Development/InMemoryPublicKeyDataProvider.cs
@@ -4,6 +4,7 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
namespace D2L.Security.OAuth2.Keys.Development {
@@ -11,9 +12,10 @@ namespace D2L.Security.OAuth2.Keys.Development {
/// A simple in-memory key data provider to be used only for testing and prototyping purposes.
///
[Obsolete( "Only use this in tests and for prototyping without a db" )]
- public sealed class InMemoryPublicKeyDataProvider : IPublicKeyDataProvider {
+ public sealed partial class InMemoryPublicKeyDataProvider : IPublicKeyDataProvider {
private readonly ConcurrentDictionary m_keys = new ConcurrentDictionary();
+ [GenerateSync]
Task IPublicKeyDataProvider.GetByIdAsync( Guid id ) {
if( !m_keys.TryGetValue( id, out JsonWebKey key ) ) {
return Task.FromResult( null );
@@ -21,6 +23,7 @@ Task IPublicKeyDataProvider.GetByIdAsync( Guid id ) {
return Task.FromResult( key );
}
+ [GenerateSync]
Task> IPublicKeyDataProvider.GetAllAsync() {
IEnumerable result =
new ReadOnlyCollection( m_keys.Values.ToList() );
@@ -28,6 +31,7 @@ Task> IPublicKeyDataProvider.GetAllAsync() {
return Task.FromResult( result );
}
+ [GenerateSync]
Task IPublicKeyDataProvider.SaveAsync( Guid id, JsonWebKey key ) {
if( !m_keys.TryAdd( id, key ) ) {
throw new InvalidOperationException( "Attempted to add a key twice" );
@@ -35,6 +39,7 @@ Task IPublicKeyDataProvider.SaveAsync( Guid id, JsonWebKey key ) {
return Task.CompletedTask;
}
+ [GenerateSync]
Task IPublicKeyDataProvider.DeleteAsync( Guid id ) {
m_keys.TryRemove( id, out JsonWebKey removedKey );
return Task.CompletedTask;
diff --git a/src/D2L.Security.OAuth2/Keys/IPublicKeyDataProvider.cs b/src/D2L.Security.OAuth2/Keys/IPublicKeyDataProvider.cs
index 90ea91be..881d8d50 100644
--- a/src/D2L.Security.OAuth2/Keys/IPublicKeyDataProvider.cs
+++ b/src/D2L.Security.OAuth2/Keys/IPublicKeyDataProvider.cs
@@ -1,25 +1,28 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
namespace D2L.Security.OAuth2.Keys {
///
/// Data provider for public keys that belong to this service
///
- public interface IPublicKeyDataProvider {
+ public partial interface IPublicKeyDataProvider {
///
/// Gets an individual by its
///
/// The key id (kid)
/// The or null if the key doesn't exist or has expired
+ [GenerateSync]
Task GetByIdAsync( Guid id );
///
/// Gets all the instances
///
/// All keys which haven't expired
+ [GenerateSync]
Task> GetAllAsync();
///
@@ -27,12 +30,14 @@ public interface IPublicKeyDataProvider {
///
/// The key id (kid) of the key to save
/// The key to save
+ [GenerateSync]
Task SaveAsync( Guid id, JsonWebKey key );
///
/// Deletes a key by key (kid)
///
/// The key id (kid) of the key to delete
+ [GenerateSync]
Task DeleteAsync( Guid id );
}
diff --git a/src/D2L.Security.OAuth2/Provisioning/Default/AuthServiceClient.cs b/src/D2L.Security.OAuth2/Provisioning/Default/AuthServiceClient.cs
index 8cf33be2..c56434d3 100644
--- a/src/D2L.Security.OAuth2/Provisioning/Default/AuthServiceClient.cs
+++ b/src/D2L.Security.OAuth2/Provisioning/Default/AuthServiceClient.cs
@@ -6,6 +6,7 @@
using System.Text;
using System.Threading.Tasks;
using D2L.Security.OAuth2.Scopes;
+using D2L.Security.OAuth2.Utilities;
using D2L.Services.Core.Exceptions;
#if NET6_0
@@ -39,7 +40,7 @@ internal sealed class AuthServiceClient : IAuthServiceClient {
SERIALIZATION_ERROR_MESSAGE_PREFIX +
"The Auth Service responded with: ";
- private readonly HttpClient m_client;
+ private readonly ID2LHttpClient m_client;
private readonly Uri m_tokenProvisioningEndpoint;
///
@@ -59,7 +60,7 @@ Uri authEndpoint
throw new ArgumentNullException( "authEndpoint" );
}
- m_client = httpClient;
+ m_client = new D2LHttpClient( httpClient );
m_tokenProvisioningEndpoint = authEndpoint.RelativePathAsNonLeaf( TOKEN_PATH );
}
diff --git a/src/D2L.Security.OAuth2/Utilities/D2LHttpClient.cs b/src/D2L.Security.OAuth2/Utilities/D2LHttpClient.cs
new file mode 100644
index 00000000..d425f171
--- /dev/null
+++ b/src/D2L.Security.OAuth2/Utilities/D2LHttpClient.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
+
+namespace D2L.Security.OAuth2.Utilities {
+ ///
+ /// This class implements sync versions of HTTPClient methods.
+ /// TODO: Replace the sync methods which are currently using Task.Run(async verison); task.Wait();
+ /// With (probably) HttpWebRequest
+ ///
+ internal sealed class D2LHttpClient : ID2LHttpClient {
+ private readonly HttpClient m_httpClient;
+
+ public D2LHttpClient( HttpClient httpClient ) {
+ m_httpClient = httpClient;
+ }
+
+ public Task GetAsync( string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken )
+ => m_httpClient.GetAsync( requestUri, completionOption, cancellationToken );
+ public Task GetAsync( Uri requestUri, CancellationToken cancellationToken )
+ => m_httpClient.GetAsync( requestUri, cancellationToken );
+ public Task GetAsync( Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken )
+ => m_httpClient.GetAsync( requestUri, completionOption, cancellationToken );
+ public Task GetAsync( Uri requestUri, HttpCompletionOption completionOption )
+ => m_httpClient.GetAsync( requestUri, completionOption );
+ public Task GetAsync( string requestUri, HttpCompletionOption completionOption )
+ => m_httpClient.GetAsync( requestUri, completionOption );
+ public Task GetAsync( Uri requestUri )
+ => m_httpClient.GetAsync( requestUri );
+ public Task GetAsync( string requestUri )
+ => m_httpClient.GetAsync( requestUri );
+ public Task GetAsync( string requestUri, CancellationToken cancellationToken )
+ => m_httpClient.GetAsync( requestUri, cancellationToken );
+
+ public Task SendAsync( HttpRequestMessage request )
+ => m_httpClient.SendAsync( request );
+ public Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken )
+ => m_httpClient.SendAsync( request, cancellationToken );
+ public Task SendAsync( HttpRequestMessage request, HttpCompletionOption completionOption )
+ => m_httpClient.SendAsync( request, completionOption );
+ public Task SendAsync( HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken )
+ => m_httpClient.SendAsync( request, completionOption, cancellationToken );
+
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, completionOption, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( Uri requestUri, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, completionOption, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( Uri requestUri, HttpCompletionOption completionOption ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, completionOption ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( string requestUri, HttpCompletionOption completionOption ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, completionOption ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( Uri requestUri ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( string requestUri ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Get( string requestUri, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.GetAsync( requestUri, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Send( HttpRequestMessage request ) {
+ var task = Task.Run( () => m_httpClient.SendAsync( request ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Send( HttpRequestMessage request, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.SendAsync( request, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Send( HttpRequestMessage request, HttpCompletionOption completionOption ) {
+ var task = Task.Run( () => m_httpClient.SendAsync( request, completionOption ) );
+ task.Wait();
+ return task.Result;
+ }
+ [DangerousMethodUsage.Audited( typeof( Task ), "Run", "Ana DuCristea", "2023-07-23", "Temporary sync implementation of HttpClient for generated sync methods to be replaced later" )]
+ public HttpResponseMessage Send( HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken ) {
+ var task = Task.Run( () => m_httpClient.SendAsync( request, completionOption, cancellationToken ) );
+ task.Wait();
+ return task.Result;
+ }
+
+ public void Dispose() { m_httpClient.Dispose(); }
+ }
+}
diff --git a/src/D2L.Security.OAuth2/Utilities/ID2LHttpClient.cs b/src/D2L.Security.OAuth2/Utilities/ID2LHttpClient.cs
new file mode 100644
index 00000000..29c43762
--- /dev/null
+++ b/src/D2L.Security.OAuth2/Utilities/ID2LHttpClient.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace D2L.Security.OAuth2.Utilities {
+ ///
+ /// This interface was created to allow the sync generator in D2L.CodeStyle to strip the async suffix from HttpClient calls
+ /// when it tries to convert async code to sync code.
+ ///
+ internal interface ID2LHttpClient : IDisposable {
+ public Task GetAsync( string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+ public Task GetAsync( Uri requestUri, CancellationToken cancellationToken );
+ public Task GetAsync( Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+ public Task GetAsync( Uri requestUri, HttpCompletionOption completionOption );
+ public Task GetAsync( string requestUri, HttpCompletionOption completionOption );
+ public Task GetAsync( Uri requestUri );
+ public Task GetAsync( string requestUri );
+ public Task GetAsync( string requestUri, CancellationToken cancellationToken );
+
+ public HttpResponseMessage Get( string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+ public HttpResponseMessage Get( Uri requestUri, CancellationToken cancellationToken );
+ public HttpResponseMessage Get( Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+ public HttpResponseMessage Get( Uri requestUri, HttpCompletionOption completionOption );
+ public HttpResponseMessage Get( string requestUri, HttpCompletionOption completionOption );
+ public HttpResponseMessage Get( Uri requestUri );
+ public HttpResponseMessage Get( string requestUri );
+ public HttpResponseMessage Get( string requestUri, CancellationToken cancellationToken );
+
+ public Task SendAsync( HttpRequestMessage request );
+ public Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken );
+ public Task SendAsync( HttpRequestMessage request, HttpCompletionOption completionOption );
+ public Task SendAsync( HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+
+ public HttpResponseMessage Send( HttpRequestMessage request );
+ public HttpResponseMessage Send( HttpRequestMessage request, CancellationToken cancellationToken );
+ public HttpResponseMessage Send( HttpRequestMessage request, HttpCompletionOption completionOption );
+ public HttpResponseMessage Send( HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken );
+ }
+}
diff --git a/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidator.cs b/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidator.cs
index 22fb5b44..dcdf26f5 100644
--- a/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidator.cs
+++ b/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidator.cs
@@ -7,13 +7,14 @@
using D2L.Security.OAuth2.Keys.Default;
using D2L.Security.OAuth2.Validation.Exceptions;
using D2L.Services;
+using D2L.CodeStyle.Annotations;
#if DNXCORE50
using System.IdentityModel.Tokens.Jwt;
#endif
namespace D2L.Security.OAuth2.Validation.AccessTokens {
- internal sealed class AccessTokenValidator : IAccessTokenValidator {
+ internal sealed partial class AccessTokenValidator : IAccessTokenValidator {
internal static readonly ImmutableHashSet ALLOWED_SIGNATURE_ALGORITHMS = ImmutableHashSet.Create(
SecurityAlgorithms.RsaSha256,
SecurityAlgorithms.EcdsaSha256,
@@ -33,8 +34,10 @@ IPublicKeyProvider publicKeyProvider
m_publicKeyProvider = publicKeyProvider;
}
+ [GenerateSync]
Task IAccessTokenValidator.PrefetchAsync() => m_publicKeyProvider.PrefetchAsync();
+ [GenerateSync]
async Task IAccessTokenValidator.ValidateAsync(
string token
) {
diff --git a/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidatorFactory.cs b/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidatorFactory.cs
index 221b4b0f..ab51139f 100644
--- a/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidatorFactory.cs
+++ b/src/D2L.Security.OAuth2/Validation/AccessTokens/AccessTokenValidatorFactory.cs
@@ -4,6 +4,7 @@
using D2L.Security.OAuth2.Keys.Caching;
using D2L.Security.OAuth2.Keys.Default;
using D2L.Security.OAuth2.Keys.Default.Data;
+using D2L.Security.OAuth2.Utilities;
namespace D2L.Security.OAuth2.Validation.AccessTokens {
diff --git a/src/D2L.Security.OAuth2/Validation/AccessTokens/IAccessTokenValidator.cs b/src/D2L.Security.OAuth2/Validation/AccessTokens/IAccessTokenValidator.cs
index 3ff20247..7c17e2d2 100644
--- a/src/D2L.Security.OAuth2/Validation/AccessTokens/IAccessTokenValidator.cs
+++ b/src/D2L.Security.OAuth2/Validation/AccessTokens/IAccessTokenValidator.cs
@@ -1,15 +1,17 @@
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
namespace D2L.Security.OAuth2.Validation.AccessTokens {
///
/// An abstraction for validating access tokens
///
- public interface IAccessTokenValidator {
+ public partial interface IAccessTokenValidator {
///
/// Perform steps to potentially make future validations faster.
///
+ [GenerateSync]
Task PrefetchAsync();
///
@@ -18,6 +20,7 @@ public interface IAccessTokenValidator {
/// The raw token to validate
/// A holding the decoded and validated access token
/// Throws on error
+ [GenerateSync]
Task ValidateAsync(
string accessToken
);
diff --git a/src/D2L.Security.OAuth2/Validation/Request/IRequestAuthenticator.cs b/src/D2L.Security.OAuth2/Validation/Request/IRequestAuthenticator.cs
index bfce0d3f..866c292b 100644
--- a/src/D2L.Security.OAuth2/Validation/Request/IRequestAuthenticator.cs
+++ b/src/D2L.Security.OAuth2/Validation/Request/IRequestAuthenticator.cs
@@ -1,5 +1,6 @@
using System.Net.Http;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
using D2L.Security.OAuth2.Principal;
namespace D2L.Security.OAuth2.Validation.Request {
@@ -9,6 +10,7 @@ public partial interface IRequestAuthenticator {
///
/// The web request object
/// An for an authenticated user.
+ [GenerateSync]
Task AuthenticateAsync(
HttpRequestMessage request
);
@@ -18,6 +20,7 @@ HttpRequestMessage request
///
/// The bearer token.
/// An for an authenticated user.
+ [GenerateSync]
Task AuthenticateAsync(
string bearerToken
);
diff --git a/src/D2L.Security.OAuth2/Validation/Request/RequestAuthenticator.cs b/src/D2L.Security.OAuth2/Validation/Request/RequestAuthenticator.cs
index 65676d03..eb66bf91 100644
--- a/src/D2L.Security.OAuth2/Validation/Request/RequestAuthenticator.cs
+++ b/src/D2L.Security.OAuth2/Validation/Request/RequestAuthenticator.cs
@@ -1,5 +1,6 @@
using System.Net.Http;
using System.Threading.Tasks;
+using D2L.CodeStyle.Annotations;
using D2L.Security.OAuth2.Principal;
using D2L.Security.OAuth2.Validation.AccessTokens;
@@ -14,6 +15,7 @@ internal RequestAuthenticator( IAccessTokenValidator accessTokenValidator ) {
m_accessTokenValidator = accessTokenValidator;
}
+ [GenerateSync]
Task IRequestAuthenticator.AuthenticateAsync(
HttpRequestMessage request
) {
@@ -22,6 +24,7 @@ HttpRequestMessage request
return AuthenticateAsync( bearerToken );
}
+ [GenerateSync]
public async Task AuthenticateAsync(
string bearerToken
) {
diff --git a/test/D2L.Security.OAuth2.Benchmarks/FullStackValidation/FullStackValidationBenchmark.cs b/test/D2L.Security.OAuth2.Benchmarks/FullStackValidation/FullStackValidationBenchmark.cs
index 03a128f7..0791d614 100644
--- a/test/D2L.Security.OAuth2.Benchmarks/FullStackValidation/FullStackValidationBenchmark.cs
+++ b/test/D2L.Security.OAuth2.Benchmarks/FullStackValidation/FullStackValidationBenchmark.cs
@@ -4,6 +4,7 @@
using System.Net.Http;
using D2L.Security.OAuth2.Keys;
using D2L.Security.OAuth2.Keys.Development;
+using D2L.Security.OAuth2.Utilities;
using D2L.Security.OAuth2.Validation.AccessTokens;
using Newtonsoft.Json;
using RichardSzalay.MockHttp;