diff options
6 files changed, 77 insertions, 24 deletions
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs index c0685bc..0e4dc5c 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs @@ -49,7 +49,7 @@ namespace RelyingPartyLogic { return; } - var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKey, OAuthAuthorizationServer.AsymmetricKey); + var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKeyServiceProvider, OAuthAuthorizationServer.AsymmetricKeyServiceProvider); var resourceServer = new ResourceServer(tokenAnalyzer); IPrincipal principal; diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs index 519ee6f..5266eb5 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs @@ -32,7 +32,7 @@ namespace RelyingPartyLogic { var httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; var requestUri = operationContext.RequestContext.RequestMessage.Properties.Via; - var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKey, OAuthAuthorizationServer.AsymmetricKey); + var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKeyServiceProvider, OAuthAuthorizationServer.AsymmetricKeyServiceProvider); var resourceServer = new ResourceServer(tokenAnalyzer); try { diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs index 4cda86e..034afeb 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs @@ -21,7 +21,10 @@ namespace RelyingPartyLogic { /// Provides OAuth 2.0 authorization server information to DotNetOpenAuth. /// </summary> public class OAuthAuthorizationServer : IAuthorizationServer { - internal static readonly RSACryptoServiceProvider AsymmetricKey; + private static readonly RSAParameters AsymmetricKey; + + [ThreadStatic] + internal static readonly RSACryptoServiceProvider AsymmetricKeyServiceProvider = CreateAsymmetricKeyServiceProvider(); private static readonly byte[] secret; @@ -39,7 +42,22 @@ namespace RelyingPartyLogic { // http://social.msdn.microsoft.com/Forums/en-US/clr/thread/7ea48fd0-8d6b-43ed-b272-1a0249ae490f?prof=required var cspParameters = new CspParameters(); cspParameters.Flags = CspProviderFlags.UseArchivableKey | CspProviderFlags.UseMachineKeyStore; - AsymmetricKey = new RSACryptoServiceProvider(cspParameters); + var asymmetricKey = new RSACryptoServiceProvider(cspParameters); + AsymmetricKey = asymmetricKey.ExportParameters(true); + } + + /// <summary> + /// Creates the asymmetric crypto service provider. + /// </summary> + /// <returns>An RSA crypto service provider.</returns> + /// <remarks> + /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread. + /// In this sample we just create one for each incoming request. Be sure to call Dispose on them to release native handles. + /// </remarks> + private static RSACryptoServiceProvider CreateAsymmetricKeyServiceProvider() { + var serviceProvider = new RSACryptoServiceProvider(); + serviceProvider.ImportParameters(AsymmetricKey); + return serviceProvider; } /// <summary> @@ -72,7 +90,7 @@ namespace RelyingPartyLogic { /// servers to validate that the access token is minted by a trusted authorization server. /// </remarks> public RSACryptoServiceProvider AccessTokenSigningPrivateKey { - get { return AsymmetricKey; } + get { return AsymmetricKeyServiceProvider; } } /// <summary> diff --git a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs index ec2f8fd..d71416e 100644 --- a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs +++ b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs @@ -11,9 +11,10 @@ using DotNetOpenAuth.OAuth2.Messages; internal class OAuth2AuthorizationServer : IAuthorizationServer { - internal static readonly RSAParameters AsymmetricTokenSigningPrivateKey; + private static readonly RSAParameters AsymmetricTokenSigningPrivateKey; - internal static readonly RSACryptoServiceProvider AsymmetricTokenSigningServiceProvider; + [ThreadStatic] + internal static readonly RSACryptoServiceProvider AsymmetricTokenSigningServiceProvider = CreateAsymmetricTokenSigningServiceProvider(); private static readonly byte[] secret; @@ -47,12 +48,23 @@ var privateKey = keyPair.ExportParameters(true); var publicKey = keyPair.ExportParameters(false); - // Ultimately the private key information must be what is returned bout the AccessTokenSigningPrivateKey property. + // Ultimately the private key information must be what is returned through the AccessTokenSigningPrivateKey property. AsymmetricTokenSigningPrivateKey = privateKey; #endif + } - AsymmetricTokenSigningServiceProvider = new RSACryptoServiceProvider(); - AsymmetricTokenSigningServiceProvider.ImportParameters(AsymmetricTokenSigningPrivateKey); + /// <summary> + /// Creates the asymmetric token signing service provider. + /// </summary> + /// <returns>An RSA crypto service provider.</returns> + /// <remarks> + /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread. + /// In this sample we just create one for each incoming request. Be sure to call Dispose on them to release native handles. + /// </remarks> + private static RSACryptoServiceProvider CreateAsymmetricTokenSigningServiceProvider() { + var asymmetricTokenSigningServiceProvider = new RSACryptoServiceProvider(); + asymmetricTokenSigningServiceProvider.ImportParameters(AsymmetricTokenSigningPrivateKey); + return asymmetricTokenSigningServiceProvider; } #region Implementation of IAuthorizationServer diff --git a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs index fc332d0..b9fbe65 100644 --- a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs +++ b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs @@ -37,14 +37,20 @@ /// <summary>
/// The resource server's encryption service provider with private key.
/// </summary>
- private static readonly RSACryptoServiceProvider ResourceServerEncryptionServiceProvider;
+ /// <remarks>
+ /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread.
+ /// </remarks>
+ [ThreadStatic]
+ private static RSACryptoServiceProvider ResourceServerEncryptionServiceProvider = CreateResourceServerEncryptionServiceProvider();
/// <summary>
- /// Initializes the <see cref="OAuthController"/> class.
+ /// Creates the resource server's encryption service provider with private key.
/// </summary>
- static OAuthController() {
- ResourceServerEncryptionServiceProvider = new RSACryptoServiceProvider();
- ResourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPublicKey);
+ /// <returns>An RSA crypto service provider.</returns>
+ private static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() {
+ var resourceServerEncryptionServiceProvider = new RSACryptoServiceProvider();
+ resourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPublicKey);
+ return resourceServerEncryptionServiceProvider;
}
/// <summary>
diff --git a/samples/OAuthResourceServer/Code/Global.cs b/samples/OAuthResourceServer/Code/Global.cs index 5080609..a70930b 100644 --- a/samples/OAuthResourceServer/Code/Global.cs +++ b/samples/OAuthResourceServer/Code/Global.cs @@ -34,7 +34,11 @@ /// <summary> /// The authorization server crypto service provider that contains a public key. /// </summary> - public static readonly RSACryptoServiceProvider AuthorizationServerSigningServiceProvider; + /// <remarks> + /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread. + /// </remarks> + [ThreadStatic] + public static readonly RSACryptoServiceProvider AuthorizationServerSigningServiceProvider = CreateAuthorizationServerSigningServiceProvider(); /// <summary> /// An application memory cache of recent log messages. @@ -66,23 +70,36 @@ }; #else [Obsolete("You must use a real key for a real app.", true)] - internal static readonly RSAParameters ResourceServerEncryptionPrivateKey= new RSAParameters(); + internal static readonly RSAParameters ResourceServerEncryptionPrivateKey = new RSAParameters(); #endif /// <summary> /// The crypto service provider for this resource server that contains the private key used to decrypt an access token. /// </summary> - internal static readonly RSACryptoServiceProvider ResourceServerEncryptionServiceProvider; + /// <remarks> + /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread. + /// </remarks> + [ThreadStatic] + internal static readonly RSACryptoServiceProvider ResourceServerEncryptionServiceProvider = CreateResourceServerEncryptionServiceProvider(); /// <summary> - /// Initializes the <see cref="Global"/> class. + /// Creates the crypto service provider for this resource server that contains the private key used to decrypt an access token. /// </summary> - static Global() { - AuthorizationServerSigningServiceProvider = new RSACryptoServiceProvider(); - AuthorizationServerSigningServiceProvider.ImportParameters(AuthorizationServerSigningPublicKey); + /// <returns>An RSA crypto service provider.</returns> + private static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() { + var resourceServerEncryptionServiceProvider = new RSACryptoServiceProvider(); + resourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPrivateKey); + return resourceServerEncryptionServiceProvider; + } - ResourceServerEncryptionServiceProvider = new RSACryptoServiceProvider(); - ResourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPrivateKey); + /// <summary> + /// Creates the crypto service provider for the authorization server that contains the public key used to verify an access token signature. + /// </summary> + /// <returns>An RSA crypto service provider.</returns> + private static RSACryptoServiceProvider CreateAuthorizationServerSigningServiceProvider() { + var authorizationServerSigningServiceProvider = new RSACryptoServiceProvider(); + authorizationServerSigningServiceProvider.ImportParameters(AuthorizationServerSigningPublicKey); + return authorizationServerSigningServiceProvider; } private void Application_Start(object sender, EventArgs e) { |