summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs14
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs46
-rw-r--r--projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs38
-rw-r--r--samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs66
-rw-r--r--samples/OAuthAuthorizationServer/Controllers/OAuthController.cs19
-rw-r--r--samples/OAuthResourceServer/Code/Global.cs22
-rw-r--r--samples/OAuthResourceServer/Code/OAuthAuthorizationManager.cs17
-rw-r--r--src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs38
-rw-r--r--src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs16
9 files changed, 130 insertions, 146 deletions
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs
index 0e4dc5c..2c9dc66 100644
--- a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs
@@ -49,13 +49,15 @@ namespace RelyingPartyLogic {
return;
}
- var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKeyServiceProvider, OAuthAuthorizationServer.AsymmetricKeyServiceProvider);
- var resourceServer = new ResourceServer(tokenAnalyzer);
+ using (var crypto = OAuthAuthorizationServer.CreateAsymmetricKeyServiceProvider()) {
+ var tokenAnalyzer = new SpecialAccessTokenAnalyzer(crypto, crypto);
+ var resourceServer = new ResourceServer(tokenAnalyzer);
- IPrincipal principal;
- var errorMessage = resourceServer.VerifyAccess(new HttpRequestInfo(this.application.Context.Request), out principal);
- if (errorMessage == null) {
- this.application.Context.User = principal;
+ IPrincipal principal;
+ var errorMessage = resourceServer.VerifyAccess(new HttpRequestInfo(this.application.Context.Request), out principal);
+ if (errorMessage == null) {
+ this.application.Context.User = principal;
+ }
}
}
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs
index 5266eb5..c4bcbba 100644
--- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs
@@ -32,38 +32,40 @@ namespace RelyingPartyLogic {
var httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
var requestUri = operationContext.RequestContext.RequestMessage.Properties.Via;
- var tokenAnalyzer = new SpecialAccessTokenAnalyzer(OAuthAuthorizationServer.AsymmetricKeyServiceProvider, OAuthAuthorizationServer.AsymmetricKeyServiceProvider);
- var resourceServer = new ResourceServer(tokenAnalyzer);
+ using (var crypto = OAuthAuthorizationServer.CreateAsymmetricKeyServiceProvider()) {
+ var tokenAnalyzer = new SpecialAccessTokenAnalyzer(crypto, crypto);
+ var resourceServer = new ResourceServer(tokenAnalyzer);
- try {
- IPrincipal principal;
- var errorResponse = resourceServer.VerifyAccess(httpDetails, requestUri, out principal);
- if (errorResponse == null) {
- var policy = new OAuthPrincipalAuthorizationPolicy(principal);
- var policies = new List<IAuthorizationPolicy> {
+ try {
+ IPrincipal principal;
+ var errorResponse = resourceServer.VerifyAccess(httpDetails, requestUri, out principal);
+ if (errorResponse == null) {
+ var policy = new OAuthPrincipalAuthorizationPolicy(principal);
+ var policies = new List<IAuthorizationPolicy> {
policy,
};
- var securityContext = new ServiceSecurityContext(policies.AsReadOnly());
- if (operationContext.IncomingMessageProperties.Security != null) {
- operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext;
- } else {
- operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty {
- ServiceSecurityContext = securityContext,
- };
- }
+ var securityContext = new ServiceSecurityContext(policies.AsReadOnly());
+ if (operationContext.IncomingMessageProperties.Security != null) {
+ operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext;
+ } else {
+ operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty {
+ ServiceSecurityContext = securityContext,
+ };
+ }
- securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> {
+ securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> {
principal.Identity,
};
- // Only allow this method call if the access token scope permits it.
- if (principal.IsInRole(operationContext.IncomingMessageHeaders.Action)) {
- return true;
+ // Only allow this method call if the access token scope permits it.
+ if (principal.IsInRole(operationContext.IncomingMessageHeaders.Action)) {
+ return true;
+ }
}
+ } catch (ProtocolException /*ex*/) {
+ ////Logger.Error("Error processing OAuth messages.", ex);
}
- } catch (ProtocolException /*ex*/) {
- ////Logger.Error("Error processing OAuth messages.", ex);
}
return false;
diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
index 034afeb..2e791ff 100644
--- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
+++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationServer.cs
@@ -21,29 +21,37 @@ namespace RelyingPartyLogic {
/// Provides OAuth 2.0 authorization server information to DotNetOpenAuth.
/// </summary>
public class OAuthAuthorizationServer : IAuthorizationServer {
- private static readonly RSAParameters AsymmetricKey;
+ private static readonly RSAParameters AsymmetricKey = CreateRSAKey();
- [ThreadStatic]
- internal static readonly RSACryptoServiceProvider AsymmetricKeyServiceProvider = CreateAsymmetricKeyServiceProvider();
-
- private static readonly byte[] secret;
+ private static readonly byte[] secret = CreateSecret();
private readonly INonceStore nonceStore = new NonceDbStore();
- static OAuthAuthorizationServer() {
+ /// <summary>
+ /// Creates a symmetric secret used to sign and encrypt authorization server refresh tokens.
+ /// </summary>
+ /// <returns>A cryptographically strong symmetric key.</returns>
+ private static byte[] CreateSecret() {
// TODO: Replace this sample code with real code.
// For this sample, we just generate random secrets.
RandomNumberGenerator crypto = new RNGCryptoServiceProvider();
- secret = new byte[16];
+ var secret = new byte[16];
crypto.GetBytes(secret);
+ return secret;
+ }
+ /// <summary>
+ /// Creates the RSA key used by all the crypto service provider instances we create.
+ /// </summary>
+ /// <returns>RSA data that includes the private key.</returns>
+ private static RSAParameters CreateRSAKey() {
// As we generate a new random key, we need to set the UseMachineKeyStore flag so that this doesn't
// crash on IIS. For more information:
// 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;
var asymmetricKey = new RSACryptoServiceProvider(cspParameters);
- AsymmetricKey = asymmetricKey.ExportParameters(true);
+ return asymmetricKey.ExportParameters(true);
}
/// <summary>
@@ -54,7 +62,7 @@ namespace RelyingPartyLogic {
/// 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() {
+ internal static RSACryptoServiceProvider CreateAsymmetricKeyServiceProvider() {
var serviceProvider = new RSACryptoServiceProvider();
serviceProvider.ImportParameters(AsymmetricKey);
return serviceProvider;
@@ -81,16 +89,8 @@ namespace RelyingPartyLogic {
get { return secret; }
}
- /// <summary>
- /// Gets the asymmetric private key to use for signing access tokens.
- /// </summary>
- /// <value></value>
- /// <remarks>
- /// The public key in the private/public key pair will be used by the resource
- /// servers to validate that the access token is minted by a trusted authorization server.
- /// </remarks>
- public RSACryptoServiceProvider AccessTokenSigningPrivateKey {
- get { return AsymmetricKeyServiceProvider; }
+ public RSACryptoServiceProvider CreateAccessTokenSigningCryptoServiceProvider() {
+ return CreateAsymmetricKeyServiceProvider();
}
/// <summary>
diff --git a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
index d71416e..7e4dba6 100644
--- a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
+++ b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs
@@ -11,62 +11,62 @@
using DotNetOpenAuth.OAuth2.Messages;
internal class OAuth2AuthorizationServer : IAuthorizationServer {
- private static readonly RSAParameters AsymmetricTokenSigningPrivateKey;
+ private static readonly RSAParameters AsymmetricTokenSigningPrivateKey = CreateRSAKey();
- [ThreadStatic]
- internal static readonly RSACryptoServiceProvider AsymmetricTokenSigningServiceProvider = CreateAsymmetricTokenSigningServiceProvider();
-
- private static readonly byte[] secret;
+ private static readonly byte[] secret = CreateSecret();
private readonly INonceStore nonceStore = new DatabaseNonceStore();
- static OAuth2AuthorizationServer() {
+ /// <summary>
+ /// Creates a symmetric secret used to sign and encrypt authorization server refresh tokens.
+ /// </summary>
+ /// <returns>A cryptographically strong symmetric key.</returns>
+ private static byte[] CreateSecret() {
+ // TODO: Replace this sample code with real code.
// For this sample, we just generate random secrets.
RandomNumberGenerator crypto = new RNGCryptoServiceProvider();
- secret = new byte[16];
+ var secret = new byte[16];
crypto.GetBytes(secret);
+ return secret;
+ }
+ /// <summary>
+ /// Creates the RSA key used by all the crypto service provider instances we create.
+ /// </summary>
+ /// <returns>RSA data that includes the private key.</returns>
+ private static RSAParameters CreateRSAKey() {
#if SAMPLESONLY
// Since the sample authorization server and the sample resource server must work together,
// we hard-code a FOR SAMPLE USE ONLY key pair. The matching public key information is hard-coded into the OAuthResourceServer sample.
// In a real app, the RSA parameters would typically come from a certificate that may already exist. It may simply be the HTTPS certificate for the auth server.
- AsymmetricTokenSigningPrivateKey = new RSAParameters {
+ return new RSAParameters {
Exponent = new byte[] { 1, 0, 1 },
- Modulus = new byte[] { 210, 95, 53, 12, 203, 114, 150, 23, 23, 88, 4, 200, 47, 219, 73, 54, 146, 253, 126, 121, 105, 91, 118, 217, 182, 167, 140, 6, 67, 112, 97, 183, 66, 112, 245, 103, 136, 222, 205, 28, 196, 45, 6, 223, 192, 76, 56, 180, 90, 120, 144, 19, 31, 193, 37, 129, 186, 214, 36, 53, 204, 53, 108, 133, 112, 17, 133, 244, 3, 12, 230, 29, 243, 51, 79, 253, 10, 111, 185, 23, 74, 230, 99, 94, 78, 49, 209, 39, 95, 213, 248, 212, 22, 4, 222, 145, 77, 190, 136, 230, 134, 70, 228, 241, 194, 216, 163, 234, 52, 1, 64, 181, 139, 128, 90, 255, 214, 60, 168, 233, 254, 110, 31, 102, 58, 67, 201, 33 },
- P = new byte[] { 237, 238, 79, 75, 29, 57, 145, 201, 57, 177, 215, 108, 40, 77, 232, 237, 113, 38, 157, 195, 174, 134, 188, 175, 121, 28, 11, 236, 80, 146, 12, 38, 8, 12, 104, 46, 6, 247, 14, 149, 196, 23, 130, 116, 141, 137, 225, 74, 84, 111, 44, 163, 55, 10, 246, 154, 195, 158, 186, 241, 162, 11, 217, 77 },
- Q = new byte[] { 226, 89, 29, 67, 178, 205, 30, 152, 184, 165, 15, 152, 131, 245, 141, 80, 150, 3, 224, 136, 188, 248, 149, 36, 200, 250, 207, 156, 224, 79, 150, 191, 84, 214, 233, 173, 95, 192, 55, 123, 124, 255, 53, 85, 11, 233, 156, 66, 14, 27, 27, 163, 108, 199, 90, 37, 118, 38, 78, 171, 80, 26, 101, 37 },
- DP = new byte[] { 108, 176, 122, 132, 131, 187, 50, 191, 203, 157, 84, 29, 82, 100, 20, 205, 178, 236, 195, 17, 10, 254, 253, 222, 226, 226, 79, 8, 10, 222, 76, 178, 106, 230, 208, 8, 134, 162, 1, 133, 164, 232, 96, 109, 193, 226, 132, 138, 33, 252, 15, 86, 23, 228, 232, 54, 86, 186, 130, 7, 179, 208, 217, 217 },
- DQ = new byte[] { 175, 63, 252, 46, 140, 99, 208, 138, 194, 123, 218, 101, 101, 214, 91, 65, 199, 196, 220, 182, 66, 73, 221, 128, 11, 180, 85, 198, 202, 206, 20, 147, 179, 102, 106, 170, 247, 245, 229, 127, 81, 58, 111, 218, 151, 76, 154, 213, 114, 2, 127, 21, 187, 133, 102, 64, 151, 7, 245, 229, 34, 50, 45, 153 },
+ Modulus = new byte[] { 210, 95, 53, 12, 203, 114, 150, 23, 23, 88, 4, 200, 47, 219, 73, 54, 146, 253, 126, 121, 105, 91, 118, 217, 182, 167, 140, 6, 67, 112, 97, 183, 66, 112, 245, 103, 136, 222, 205, 28, 196, 45, 6, 223, 192, 76, 56, 180, 90, 120, 144, 19, 31, 193, 37, 129, 186, 214, 36, 53, 204, 53, 108, 133, 112, 17, 133, 244, 3, 12, 230, 29, 243, 51, 79, 253, 10, 111, 185, 23, 74, 230, 99, 94, 78, 49, 209, 39, 95, 213, 248, 212, 22, 4, 222, 145, 77, 190, 136, 230, 134, 70, 228, 241, 194, 216, 163, 234, 52, 1, 64, 181, 139, 128, 90, 255, 214, 60, 168, 233, 254, 110, 31, 102, 58, 67, 201, 33 },
+ P = new byte[] { 237, 238, 79, 75, 29, 57, 145, 201, 57, 177, 215, 108, 40, 77, 232, 237, 113, 38, 157, 195, 174, 134, 188, 175, 121, 28, 11, 236, 80, 146, 12, 38, 8, 12, 104, 46, 6, 247, 14, 149, 196, 23, 130, 116, 141, 137, 225, 74, 84, 111, 44, 163, 55, 10, 246, 154, 195, 158, 186, 241, 162, 11, 217, 77 },
+ Q = new byte[] { 226, 89, 29, 67, 178, 205, 30, 152, 184, 165, 15, 152, 131, 245, 141, 80, 150, 3, 224, 136, 188, 248, 149, 36, 200, 250, 207, 156, 224, 79, 150, 191, 84, 214, 233, 173, 95, 192, 55, 123, 124, 255, 53, 85, 11, 233, 156, 66, 14, 27, 27, 163, 108, 199, 90, 37, 118, 38, 78, 171, 80, 26, 101, 37 },
+ DP = new byte[] { 108, 176, 122, 132, 131, 187, 50, 191, 203, 157, 84, 29, 82, 100, 20, 205, 178, 236, 195, 17, 10, 254, 253, 222, 226, 226, 79, 8, 10, 222, 76, 178, 106, 230, 208, 8, 134, 162, 1, 133, 164, 232, 96, 109, 193, 226, 132, 138, 33, 252, 15, 86, 23, 228, 232, 54, 86, 186, 130, 7, 179, 208, 217, 217 },
+ DQ = new byte[] { 175, 63, 252, 46, 140, 99, 208, 138, 194, 123, 218, 101, 101, 214, 91, 65, 199, 196, 220, 182, 66, 73, 221, 128, 11, 180, 85, 198, 202, 206, 20, 147, 179, 102, 106, 170, 247, 245, 229, 127, 81, 58, 111, 218, 151, 76, 154, 213, 114, 2, 127, 21, 187, 133, 102, 64, 151, 7, 245, 229, 34, 50, 45, 153 },
InverseQ = new byte[] { 137, 156, 11, 248, 118, 201, 135, 145, 134, 121, 14, 162, 149, 14, 98, 84, 108, 160, 27, 91, 230, 116, 216, 181, 200, 49, 34, 254, 119, 153, 179, 52, 231, 234, 36, 148, 71, 161, 182, 171, 35, 182, 46, 164, 179, 100, 226, 71, 119, 23, 0, 16, 240, 4, 30, 57, 76, 109, 89, 131, 56, 219, 71, 206 },
- D = new byte[] { 108, 15, 123, 176, 150, 208, 197, 72, 23, 53, 159, 63, 53, 85, 238, 197, 153, 187, 156, 187, 192, 226, 186, 170, 26, 168, 245, 196, 65, 223, 248, 81, 170, 79, 91, 191, 83, 15, 31, 77, 39, 119, 249, 143, 245, 183, 49, 105, 115, 15, 122, 242, 87, 221, 94, 230, 196, 146, 59, 7, 103, 94, 9, 223, 146, 180, 189, 86, 190, 94, 242, 59, 32, 54, 23, 181, 124, 170, 63, 172, 90, 158, 169, 140, 6, 102, 170, 0, 135, 199, 35, 196, 212, 238, 196, 56, 14, 0, 140, 197, 169, 240, 156, 43, 182, 123, 102, 79, 89, 20, 120, 171, 43, 223, 58, 190, 230, 166, 185, 162, 186, 226, 31, 206, 196, 188, 104, 1 },
+ D = new byte[] { 108, 15, 123, 176, 150, 208, 197, 72, 23, 53, 159, 63, 53, 85, 238, 197, 153, 187, 156, 187, 192, 226, 186, 170, 26, 168, 245, 196, 65, 223, 248, 81, 170, 79, 91, 191, 83, 15, 31, 77, 39, 119, 249, 143, 245, 183, 49, 105, 115, 15, 122, 242, 87, 221, 94, 230, 196, 146, 59, 7, 103, 94, 9, 223, 146, 180, 189, 86, 190, 94, 242, 59, 32, 54, 23, 181, 124, 170, 63, 172, 90, 158, 169, 140, 6, 102, 170, 0, 135, 199, 35, 196, 212, 238, 196, 56, 14, 0, 140, 197, 169, 240, 156, 43, 182, 123, 102, 79, 89, 20, 120, 171, 43, 223, 58, 190, 230, 166, 185, 162, 186, 226, 31, 206, 196, 188, 104, 1 },
};
#else
// This is how you could generate your own public/private key pair.
- var keyPair = new RSACryptoServiceProvider();
+ // As we generate a new random key, we need to set the UseMachineKeyStore flag so that this doesn't
+ // crash on IIS. For more information:
+ // 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;
+ var keyPair = new RSACryptoServiceProvider(cspParameters);
// After exporting the private/public key information, read the information out and store it somewhere
var privateKey = keyPair.ExportParameters(true);
var publicKey = keyPair.ExportParameters(false);
// Ultimately the private key information must be what is returned through the AccessTokenSigningPrivateKey property.
- AsymmetricTokenSigningPrivateKey = privateKey;
+ return privateKey;
#endif
}
- /// <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
public byte[] Secret {
@@ -77,8 +77,10 @@
get { return this.nonceStore; }
}
- public RSACryptoServiceProvider AccessTokenSigningPrivateKey {
- get { return AsymmetricTokenSigningServiceProvider; }
+ public RSACryptoServiceProvider CreateAccessTokenSigningCryptoServiceProvider() {
+ var asymmetricTokenSigningServiceProvider = new RSACryptoServiceProvider();
+ asymmetricTokenSigningServiceProvider.ImportParameters(AsymmetricTokenSigningPrivateKey);
+ return asymmetricTokenSigningServiceProvider;
}
public IConsumerDescription GetClient(string clientIdentifier) {
diff --git a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs
index b9fbe65..47c1977 100644
--- a/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs
+++ b/samples/OAuthAuthorizationServer/Controllers/OAuthController.cs
@@ -31,23 +31,14 @@
};
#else
[Obsolete("You must use a real key for a real app.", true)]
- private static readonly RSAParameters ResourceServerEncryptionPublicKey = new RSAParameters();
+ private static readonly RSAParameters ResourceServerEncryptionPublicKey;
#endif
/// <summary>
- /// The resource server's encryption service provider with private key.
- /// </summary>
- /// <remarks>
- /// Since <see cref="RSACryptoServiceProvider"/> are not thread-safe, one must be created for each thread.
- /// </remarks>
- [ThreadStatic]
- private static RSACryptoServiceProvider ResourceServerEncryptionServiceProvider = CreateResourceServerEncryptionServiceProvider();
-
- /// <summary>
/// Creates the resource server's encryption service provider with private key.
/// </summary>
/// <returns>An RSA crypto service provider.</returns>
- private static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() {
+ internal static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() {
var resourceServerEncryptionServiceProvider = new RSACryptoServiceProvider();
resourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPublicKey);
return resourceServerEncryptionServiceProvider;
@@ -71,8 +62,10 @@
// TODO: code here
// Prepare the refresh and access tokens.
- var response = this.authorizationServer.PrepareAccessTokenResponse(request, ResourceServerEncryptionServiceProvider, accessTokenLifetime);
- return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
+ using (var crypto = CreateResourceServerEncryptionServiceProvider()) {
+ var response = this.authorizationServer.PrepareAccessTokenResponse(request, crypto, accessTokenLifetime);
+ return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
+ }
}
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing OAuth 2.0 request message.");
diff --git a/samples/OAuthResourceServer/Code/Global.cs b/samples/OAuthResourceServer/Code/Global.cs
index a70930b..a48baff 100644
--- a/samples/OAuthResourceServer/Code/Global.cs
+++ b/samples/OAuthResourceServer/Code/Global.cs
@@ -32,15 +32,6 @@
#endif
/// <summary>
- /// The authorization server crypto service provider that contains a public key.
- /// </summary>
- /// <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.
/// </summary>
public static StringBuilder LogMessages = new StringBuilder();
@@ -74,19 +65,10 @@
#endif
/// <summary>
- /// The crypto service provider for this resource server that contains the private key used to decrypt an access token.
- /// </summary>
- /// <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>
/// Creates the crypto service provider for this resource server that contains the private key used to decrypt an access token.
/// </summary>
/// <returns>An RSA crypto service provider.</returns>
- private static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() {
+ internal static RSACryptoServiceProvider CreateResourceServerEncryptionServiceProvider() {
var resourceServerEncryptionServiceProvider = new RSACryptoServiceProvider();
resourceServerEncryptionServiceProvider.ImportParameters(ResourceServerEncryptionPrivateKey);
return resourceServerEncryptionServiceProvider;
@@ -96,7 +78,7 @@
/// 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() {
+ internal static RSACryptoServiceProvider CreateAuthorizationServerSigningServiceProvider() {
var authorizationServerSigningServiceProvider = new RSACryptoServiceProvider();
authorizationServerSigningServiceProvider.ImportParameters(AuthorizationServerSigningPublicKey);
return authorizationServerSigningServiceProvider;
diff --git a/samples/OAuthResourceServer/Code/OAuthAuthorizationManager.cs b/samples/OAuthResourceServer/Code/OAuthAuthorizationManager.cs
index 4b47dd5..0c1953d 100644
--- a/samples/OAuthResourceServer/Code/OAuthAuthorizationManager.cs
+++ b/samples/OAuthResourceServer/Code/OAuthAuthorizationManager.cs
@@ -64,16 +64,17 @@
private static IPrincipal VerifyOAuth2(HttpRequestMessageProperty httpDetails, Uri requestUri) {
// for this sample where the auth server and resource server are the same site,
// we use the same public/private key.
- var resourceServer = new ResourceServer(
- new StandardAccessTokenAnalyzer(
- Global.AuthorizationServerSigningServiceProvider,
- Global.ResourceServerEncryptionServiceProvider));
+ using (var signing = Global.CreateAuthorizationServerSigningServiceProvider()) {
+ using (var encrypting = Global.CreateResourceServerEncryptionServiceProvider()) {
+ var resourceServer = new ResourceServer(new StandardAccessTokenAnalyzer(signing, encrypting));
- IPrincipal result;
- var error = resourceServer.VerifyAccess(new HttpRequestInfo(httpDetails, requestUri), out result);
+ IPrincipal result;
+ var error = resourceServer.VerifyAccess(new HttpRequestInfo(httpDetails, requestUri), out result);
- // TODO: return the prepared error code.
- return error != null ? null : result;
+ // TODO: return the prepared error code.
+ return error != null ? null : result;
+ }
+ }
}
}
}
diff --git a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
index 0883b1e..1c1c88c 100644
--- a/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
+++ b/src/DotNetOpenAuth/OAuth2/AuthorizationServer.cs
@@ -124,8 +124,10 @@ namespace DotNetOpenAuth.OAuth2 {
if (request != null) {
// This convenience method only encrypts access tokens assuming that this auth server
// doubles as the resource server.
- var resourceServerPublicKey = this.AuthorizationServerServices.AccessTokenSigningPrivateKey;
- response = this.PrepareAccessTokenResponse(request, resourceServerPublicKey);
+ using (var resourceServerPublicKey = this.AuthorizationServerServices.CreateAccessTokenSigningCryptoServiceProvider()) {
+ response = this.PrepareAccessTokenResponse(request, resourceServerPublicKey);
+ }
+
return true;
}
@@ -220,22 +222,24 @@ namespace DotNetOpenAuth.OAuth2 {
Contract.Requires<ArgumentNullException>(accessTokenEncryptingPublicKey != null, "accessTokenEncryptingPublicKey");
var tokenRequest = (ITokenCarryingRequest)request;
- var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServerServices.AccessTokenSigningPrivateKey, accessTokenEncryptingPublicKey);
- var accessToken = new AccessToken(tokenRequest.AuthorizationDescription, accessTokenLifetime);
-
- var response = new AccessTokenSuccessResponse(request) {
- AccessToken = accessTokenFormatter.Serialize(accessToken),
- Lifetime = accessToken.Lifetime,
- };
- response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope);
-
- if (includeRefreshToken) {
- var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServerServices.Secret);
- var refreshToken = new RefreshToken(tokenRequest.AuthorizationDescription);
- response.RefreshToken = refreshTokenFormatter.Serialize(refreshToken);
+ using (var crypto = this.AuthorizationServerServices.CreateAccessTokenSigningCryptoServiceProvider()) {
+ var accessTokenFormatter = AccessToken.CreateFormatter(crypto, accessTokenEncryptingPublicKey);
+ var accessToken = new AccessToken(tokenRequest.AuthorizationDescription, accessTokenLifetime);
+
+ var response = new AccessTokenSuccessResponse(request) {
+ AccessToken = accessTokenFormatter.Serialize(accessToken),
+ Lifetime = accessToken.Lifetime,
+ };
+ response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope);
+
+ if (includeRefreshToken) {
+ var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServerServices.Secret);
+ var refreshToken = new RefreshToken(tokenRequest.AuthorizationDescription);
+ response.RefreshToken = refreshTokenFormatter.Serialize(refreshToken);
+ }
+
+ return response;
}
-
- return response;
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs
index 2a0c5cc..ccce0ab 100644
--- a/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs
+++ b/src/DotNetOpenAuth/OAuth2/IAuthorizationServer.cs
@@ -30,14 +30,15 @@ namespace DotNetOpenAuth.OAuth2 {
byte[] Secret { get; }
/// <summary>
- /// Gets the crypto service provider with the asymmetric private key to use for signing access tokens.
+ /// Creates a new instance of the crypto service provider with the asymmetric private key to use for signing access tokens.
/// </summary>
/// <value>Must not be null, and must contain the private key.</value>
/// <remarks>
/// The public key in the private/public key pair will be used by the resource
/// servers to validate that the access token is minted by a trusted authorization server.
+ /// The caller is responsible to dispose of the returned instance.
/// </remarks>
- RSACryptoServiceProvider AccessTokenSigningPrivateKey { get; }
+ RSACryptoServiceProvider CreateAccessTokenSigningCryptoServiceProvider();
/// <summary>
/// Gets the authorization code nonce store to use to ensure that authorization codes can only be used once.
@@ -108,17 +109,14 @@ namespace DotNetOpenAuth.OAuth2 {
/// <summary>
/// Gets the crypto service provider with the asymmetric private key to use for signing access tokens.
/// </summary>
- /// <value></value>
/// <remarks>
/// The public key in the private/public key pair will be used by the resource
/// servers to validate that the access token is minted by a trusted authorization server.
/// </remarks>
- RSACryptoServiceProvider IAuthorizationServer.AccessTokenSigningPrivateKey {
- get {
- Contract.Ensures(Contract.Result<RSACryptoServiceProvider>() != null);
- Contract.Ensures(!Contract.Result<RSACryptoServiceProvider>().PublicOnly);
- throw new NotImplementedException();
- }
+ RSACryptoServiceProvider IAuthorizationServer.CreateAccessTokenSigningCryptoServiceProvider() {
+ Contract.Ensures(Contract.Result<RSACryptoServiceProvider>() != null);
+ Contract.Ensures(!Contract.Result<RSACryptoServiceProvider>().PublicOnly);
+ throw new NotImplementedException();
}
/// <summary>