From 29d897769f3e7a9568fa668836807d9a31b5fabc Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 7 Oct 2008 21:36:29 -0700 Subject: [PATCH] Added strong-typed request token message to sample. This proves that messages can be derived from and tailored to provide type-safe additions where the OAuth protocol permits it. As can be seen, several more types and members had to be made public for this to work. --- samples/Consumer/App_Code/InMemoryTokenManager.cs | 5 ++-- samples/ConsumerWpf/InMemoryTokenManager.cs | 5 ++-- .../App_Code/CustomOAuthTypeProvider.cs | 30 ++++++++++++++++++++++ .../App_Code/DatabaseTokenManager.cs | 12 +++++---- .../App_Code/RequestScopedTokenMessage.cs | 20 +++++++++++++++ samples/ServiceProvider/OAuth.ashx | 6 ++--- src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs | 7 ++--- src/DotNetOAuth/ChannelElements/ITokenManager.cs | 10 +++----- .../OAuthConsumerMessageTypeProvider.cs | 8 +++--- .../OAuthServiceProviderMessageTypeProvider.cs | 8 +++--- src/DotNetOAuth/Consumer.cs | 3 +-- .../Messages/AccessProtectedResourcesMessage.cs | 2 +- .../Messages/GrantAccessTokenMessage.cs | 2 +- .../Messages/RequestAccessTokenMessage.cs | 2 +- src/DotNetOAuth/Messages/RequestTokenMessage.cs | 2 +- .../Messages/UnauthorizedRequestTokenMessage.cs | 8 +++--- src/DotNetOAuth/Messaging/MessagePartAttribute.cs | 6 ++--- src/DotNetOAuth/Messaging/MessageSerializer.cs | 7 ++--- src/DotNetOAuth/ServiceProvider.cs | 19 +++++++++++--- 19 files changed, 114 insertions(+), 48 deletions(-) create mode 100644 samples/ServiceProvider/App_Code/CustomOAuthTypeProvider.cs create mode 100644 samples/ServiceProvider/App_Code/RequestScopedTokenMessage.cs diff --git a/samples/Consumer/App_Code/InMemoryTokenManager.cs b/samples/Consumer/App_Code/InMemoryTokenManager.cs index 83c45bd..edd3a9d 100644 --- a/samples/Consumer/App_Code/InMemoryTokenManager.cs +++ b/samples/Consumer/App_Code/InMemoryTokenManager.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using DotNetOAuth.ChannelElements; +using DotNetOAuth.Messages; public class InMemoryTokenManager : ITokenManager { private Dictionary tokensAndSecrets = new Dictionary(); @@ -35,8 +36,8 @@ public class InMemoryTokenManager : ITokenManager { return this.tokensAndSecrets[token]; } - public void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary requestParameters, IDictionary responseParameters) { - this.tokensAndSecrets[requestToken] = requestTokenSecret; + public void StoreNewRequestToken(RequestTokenMessage request, UnauthorizedRequestTokenMessage response) { + this.tokensAndSecrets[response.RequestToken] = response.TokenSecret; } /// diff --git a/samples/ConsumerWpf/InMemoryTokenManager.cs b/samples/ConsumerWpf/InMemoryTokenManager.cs index 439f1a2..45ae0b2 100644 --- a/samples/ConsumerWpf/InMemoryTokenManager.cs +++ b/samples/ConsumerWpf/InMemoryTokenManager.cs @@ -9,6 +9,7 @@ namespace DotNetOAuth.Samples.ConsumerWpf { using System.Collections.Generic; using System.Diagnostics; using DotNetOAuth.ChannelElements; + using DotNetOAuth.Messages; internal class InMemoryTokenManager : ITokenManager { private Dictionary tokensAndSecrets = new Dictionary(); @@ -34,8 +35,8 @@ namespace DotNetOAuth.Samples.ConsumerWpf { return this.tokensAndSecrets[token]; } - public void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary requestParameters, IDictionary responseParameters) { - this.tokensAndSecrets[requestToken] = requestTokenSecret; + public void StoreNewRequestToken(RequestTokenMessage request, UnauthorizedRequestTokenMessage response) { + this.tokensAndSecrets[response.RequestToken] = response.TokenSecret; } /// diff --git a/samples/ServiceProvider/App_Code/CustomOAuthTypeProvider.cs b/samples/ServiceProvider/App_Code/CustomOAuthTypeProvider.cs new file mode 100644 index 0000000..d7a9ebf --- /dev/null +++ b/samples/ServiceProvider/App_Code/CustomOAuthTypeProvider.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using DotNetOAuth.ChannelElements; +using DotNetOAuth.Messages; + +/// +/// A custom class that will cause the OAuth library to use our custom message types +/// where we have them. +/// +public class CustomOAuthTypeProvider : OAuthServiceProviderMessageTypeProvider { + /// + /// Initializes a new instance of the class. + /// + /// The token manager instance to use. + public CustomOAuthTypeProvider(ITokenManager tokenManager) : base(tokenManager) { + } + + public override Type GetRequestMessageType(IDictionary fields) { + Type type = base.GetRequestMessageType(fields); + + // inject our own type here to replace the standard one + if (type == typeof(RequestTokenMessage)) { + type = typeof(RequestScopedTokenMessage); + } + + return type; + } +} diff --git a/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs b/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs index acc8b94..b484086 100644 --- a/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs +++ b/samples/ServiceProvider/App_Code/DatabaseTokenManager.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using DotNetOAuth.ChannelElements; +using DotNetOAuth.Messages; public class DatabaseTokenManager : ITokenManager { #region ITokenManager Members @@ -33,13 +34,14 @@ public class DatabaseTokenManager : ITokenManager { return tokenRow.TokenSecret; } - public void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary requestParameters, IDictionary responseParameters) { - var consumer = Global.DataContext.OAuthConsumers.Single(consumerRow => consumerRow.ConsumerKey == consumerKey); - string scope = requestParameters["scope"]; + public void StoreNewRequestToken(RequestTokenMessage request, UnauthorizedRequestTokenMessage response) { + RequestScopedTokenMessage scopedRequest = (RequestScopedTokenMessage)request; + var consumer = Global.DataContext.OAuthConsumers.Single(consumerRow => consumerRow.ConsumerKey == request.ConsumerKey); + string scope = scopedRequest.Scope; OAuthToken newToken = new OAuthToken { OAuthConsumer = consumer, - Token = requestToken, - TokenSecret = requestTokenSecret, + Token = response.RequestToken, + TokenSecret = response.TokenSecret, IssueDate = DateTime.UtcNow, Scope = scope, }; diff --git a/samples/ServiceProvider/App_Code/RequestScopedTokenMessage.cs b/samples/ServiceProvider/App_Code/RequestScopedTokenMessage.cs new file mode 100644 index 0000000..e8dbdeb --- /dev/null +++ b/samples/ServiceProvider/App_Code/RequestScopedTokenMessage.cs @@ -0,0 +1,20 @@ +using DotNetOAuth.Messages; +using DotNetOAuth.Messaging; + +/// +/// A custom web app version of the message sent to request an unauthorized token. +/// +public class RequestScopedTokenMessage : RequestTokenMessage { + /// + /// Initializes a new instance of the class. + /// + /// The endpoint that will receive the message. + public RequestScopedTokenMessage(MessageReceivingEndpoint endpoint) : base(endpoint) { + } + + /// + /// Gets or sets the scope of the access being requested. + /// + [MessagePart("scope", IsRequired = true)] + public string Scope { get; set; } +} diff --git a/samples/ServiceProvider/OAuth.ashx b/samples/ServiceProvider/OAuth.ashx index 55cd10c..cbb27cb 100644 --- a/samples/ServiceProvider/OAuth.ashx +++ b/samples/ServiceProvider/OAuth.ashx @@ -13,15 +13,15 @@ public class OAuth : IHttpHandler, IRequiresSessionState { ServiceProvider sp; public OAuth() { - sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager); + sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager, new CustomOAuthTypeProvider(Global.TokenManager)); } public void ProcessRequest(HttpContext context) { IProtocolMessage request = sp.ReadRequest(); - RequestTokenMessage requestToken; + RequestScopedTokenMessage requestToken; DirectUserToServiceProviderMessage requestAuth; RequestAccessTokenMessage requestAccessToken; - if ((requestToken = request as RequestTokenMessage) != null) { + if ((requestToken = request as RequestScopedTokenMessage) != null) { sp.SendUnauthorizedTokenResponse(requestToken, null).Send(); } else if ((requestAuth = request as DirectUserToServiceProviderMessage) != null) { Global.PendingOAuthAuthorization = requestAuth; diff --git a/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs b/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs index 87d7608..7f8c3b7 100644 --- a/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs +++ b/src/DotNetOAuth.Test/Mocks/InMemoryTokenManager.cs @@ -9,6 +9,7 @@ namespace DotNetOAuth.Test.Mocks { using System.Collections.Generic; using System.Diagnostics; using DotNetOAuth.ChannelElements; + using DotNetOAuth.Messages; internal class InMemoryTokenManager : ITokenManager { private Dictionary consumersAndSecrets = new Dictionary(); @@ -34,9 +35,9 @@ namespace DotNetOAuth.Test.Mocks { return this.tokensAndSecrets[token]; } - public void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary requestParameters, IDictionary responseParameters) { - this.tokensAndSecrets[requestToken] = requestTokenSecret; - this.requestTokens.Add(requestToken, false); + public void StoreNewRequestToken(RequestTokenMessage request, UnauthorizedRequestTokenMessage response) { + this.tokensAndSecrets[response.RequestToken] = response.TokenSecret; + this.requestTokens.Add(response.RequestToken, false); } /// diff --git a/src/DotNetOAuth/ChannelElements/ITokenManager.cs b/src/DotNetOAuth/ChannelElements/ITokenManager.cs index 4cb6ce7..e3b218b 100644 --- a/src/DotNetOAuth/ChannelElements/ITokenManager.cs +++ b/src/DotNetOAuth/ChannelElements/ITokenManager.cs @@ -9,6 +9,7 @@ namespace DotNetOAuth.ChannelElements { using System.Collections.Generic; using System.Linq; using System.Text; + using DotNetOAuth.Messages; /// /// An interface OAuth hosts must implement for persistent storage and recall of tokens and secrets. @@ -38,13 +39,10 @@ namespace DotNetOAuth.ChannelElements { /// Stores a newly generated unauthorized request token, secret, and optional /// application-specific parameters for later recall. /// - /// The key of the Consumer that requested this token. - /// The token to store. - /// The secret to store as associated with the request token. - /// The optional application-specific parameters sent in the request message. - /// The optional application-specific parameters sent in the response message. + /// The request message that resulted in the generation of a new unauthorized request token. + /// The response message that includes the unauthorized request token. /// Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection. - void StoreNewRequestToken(string consumerKey, string requestToken, string requestTokenSecret, IDictionary requestParameters, IDictionary responseParameters); + void StoreNewRequestToken(RequestTokenMessage request, UnauthorizedRequestTokenMessage response); /// /// Checks whether a given request token has already been authorized diff --git a/src/DotNetOAuth/ChannelElements/OAuthConsumerMessageTypeProvider.cs b/src/DotNetOAuth/ChannelElements/OAuthConsumerMessageTypeProvider.cs index 12e46cf..af17527 100644 --- a/src/DotNetOAuth/ChannelElements/OAuthConsumerMessageTypeProvider.cs +++ b/src/DotNetOAuth/ChannelElements/OAuthConsumerMessageTypeProvider.cs @@ -14,7 +14,7 @@ namespace DotNetOAuth.ChannelElements { /// An OAuth-protocol specific implementation of the /// interface. /// - internal class OAuthConsumerMessageTypeProvider : IMessageTypeProvider { + public class OAuthConsumerMessageTypeProvider : IMessageTypeProvider { /// /// The token manager to use for discerning between request and access tokens. /// @@ -24,7 +24,7 @@ namespace DotNetOAuth.ChannelElements { /// Initializes a new instance of the class. /// /// The token manager instance to use. - internal OAuthConsumerMessageTypeProvider(ITokenManager tokenManager) { + protected internal OAuthConsumerMessageTypeProvider(ITokenManager tokenManager) { if (tokenManager == null) { throw new ArgumentNullException("tokenManager"); } @@ -47,7 +47,7 @@ namespace DotNetOAuth.ChannelElements { /// The -derived concrete class that this message can /// deserialize to. Null if the request isn't recognized as a valid protocol message. /// - public Type GetRequestMessageType(IDictionary fields) { + public virtual Type GetRequestMessageType(IDictionary fields) { if (fields == null) { throw new ArgumentNullException("fields"); } @@ -77,7 +77,7 @@ namespace DotNetOAuth.ChannelElements { /// UnauthorizedRequestTokenMessage /// GrantAccessTokenMessage /// - public Type GetResponseMessageType(IProtocolMessage request, IDictionary fields) { + public virtual Type GetResponseMessageType(IProtocolMessage request, IDictionary fields) { if (fields == null) { throw new ArgumentNullException("fields"); } diff --git a/src/DotNetOAuth/ChannelElements/OAuthServiceProviderMessageTypeProvider.cs b/src/DotNetOAuth/ChannelElements/OAuthServiceProviderMessageTypeProvider.cs index d47d396..ab9105f 100644 --- a/src/DotNetOAuth/ChannelElements/OAuthServiceProviderMessageTypeProvider.cs +++ b/src/DotNetOAuth/ChannelElements/OAuthServiceProviderMessageTypeProvider.cs @@ -14,7 +14,7 @@ namespace DotNetOAuth.ChannelElements { /// An OAuth-protocol specific implementation of the /// interface. /// - internal class OAuthServiceProviderMessageTypeProvider : IMessageTypeProvider { + public class OAuthServiceProviderMessageTypeProvider : IMessageTypeProvider { /// /// The token manager to use for discerning between request and access tokens. /// @@ -24,7 +24,7 @@ namespace DotNetOAuth.ChannelElements { /// Initializes a new instance of the class. /// /// The token manager instance to use. - internal OAuthServiceProviderMessageTypeProvider(ITokenManager tokenManager) { + protected internal OAuthServiceProviderMessageTypeProvider(ITokenManager tokenManager) { if (tokenManager == null) { throw new ArgumentNullException("tokenManager"); } @@ -50,7 +50,7 @@ namespace DotNetOAuth.ChannelElements { /// The -derived concrete class that this message can /// deserialize to. Null if the request isn't recognized as a valid protocol message. /// - public Type GetRequestMessageType(IDictionary fields) { + public virtual Type GetRequestMessageType(IDictionary fields) { if (fields == null) { throw new ArgumentNullException("fields"); } @@ -92,7 +92,7 @@ namespace DotNetOAuth.ChannelElements { /// The response messages are: /// None. /// - public Type GetResponseMessageType(IProtocolMessage request, IDictionary fields) { + public virtual Type GetResponseMessageType(IProtocolMessage request, IDictionary fields) { if (fields == null) { throw new ArgumentNullException("fields"); } diff --git a/src/DotNetOAuth/Consumer.cs b/src/DotNetOAuth/Consumer.cs index b8d16f3..881eec8 100644 --- a/src/DotNetOAuth/Consumer.cs +++ b/src/DotNetOAuth/Consumer.cs @@ -203,8 +203,7 @@ namespace DotNetOAuth { }; requestToken.AddNonOAuthParameters(requestParameters); var requestTokenResponse = this.Channel.Request(requestToken); - IDictionary responseParameters = ((IProtocolMessage)requestTokenResponse).ExtraData; - this.TokenManager.StoreNewRequestToken(this.ConsumerKey, requestTokenResponse.RequestToken, requestTokenResponse.TokenSecret, requestParameters, responseParameters); + this.TokenManager.StoreNewRequestToken(requestToken, requestTokenResponse); // Request user authorization. var requestAuthorization = new DirectUserToServiceProviderMessage(this.ServiceProvider.UserAuthorizationEndpoint) { diff --git a/src/DotNetOAuth/Messages/AccessProtectedResourcesMessage.cs b/src/DotNetOAuth/Messages/AccessProtectedResourcesMessage.cs index 9db6a0a..b9817f6 100644 --- a/src/DotNetOAuth/Messages/AccessProtectedResourcesMessage.cs +++ b/src/DotNetOAuth/Messages/AccessProtectedResourcesMessage.cs @@ -17,7 +17,7 @@ namespace DotNetOAuth.Messages { /// Initializes a new instance of the class. /// /// The URI of the Service Provider endpoint to send this message to. - internal AccessProtectedResourcesMessage(MessageReceivingEndpoint serviceProvider) + protected internal AccessProtectedResourcesMessage(MessageReceivingEndpoint serviceProvider) : base(MessageTransport.Direct, serviceProvider) { } diff --git a/src/DotNetOAuth/Messages/GrantAccessTokenMessage.cs b/src/DotNetOAuth/Messages/GrantAccessTokenMessage.cs index 504af4a..f1c5214 100644 --- a/src/DotNetOAuth/Messages/GrantAccessTokenMessage.cs +++ b/src/DotNetOAuth/Messages/GrantAccessTokenMessage.cs @@ -15,7 +15,7 @@ namespace DotNetOAuth.Messages { /// /// Initializes a new instance of the class. /// - internal GrantAccessTokenMessage() + protected internal GrantAccessTokenMessage() : base(MessageProtection.None, MessageTransport.Direct) { } diff --git a/src/DotNetOAuth/Messages/RequestAccessTokenMessage.cs b/src/DotNetOAuth/Messages/RequestAccessTokenMessage.cs index 6d334e7..12bd577 100644 --- a/src/DotNetOAuth/Messages/RequestAccessTokenMessage.cs +++ b/src/DotNetOAuth/Messages/RequestAccessTokenMessage.cs @@ -17,7 +17,7 @@ namespace DotNetOAuth.Messages { /// Initializes a new instance of the class. /// /// The URI of the Service Provider endpoint to send this message to. - internal RequestAccessTokenMessage(MessageReceivingEndpoint serviceProvider) + protected internal RequestAccessTokenMessage(MessageReceivingEndpoint serviceProvider) : base(MessageTransport.Direct, serviceProvider) { } diff --git a/src/DotNetOAuth/Messages/RequestTokenMessage.cs b/src/DotNetOAuth/Messages/RequestTokenMessage.cs index 727cde0..e90b63d 100644 --- a/src/DotNetOAuth/Messages/RequestTokenMessage.cs +++ b/src/DotNetOAuth/Messages/RequestTokenMessage.cs @@ -15,7 +15,7 @@ namespace DotNetOAuth.Messages { /// Initializes a new instance of the class. /// /// The URI of the Service Provider endpoint to send this message to. - internal RequestTokenMessage(MessageReceivingEndpoint serviceProvider) + protected internal RequestTokenMessage(MessageReceivingEndpoint serviceProvider) : base(MessageTransport.Direct, serviceProvider) { } } diff --git a/src/DotNetOAuth/Messages/UnauthorizedRequestTokenMessage.cs b/src/DotNetOAuth/Messages/UnauthorizedRequestTokenMessage.cs index bbeeb31..dd1203e 100644 --- a/src/DotNetOAuth/Messages/UnauthorizedRequestTokenMessage.cs +++ b/src/DotNetOAuth/Messages/UnauthorizedRequestTokenMessage.cs @@ -11,11 +11,11 @@ namespace DotNetOAuth.Messages { /// A direct message sent from Service Provider to Consumer in response to /// a Consumer's request. /// - internal class UnauthorizedRequestTokenMessage : MessageBase { + public class UnauthorizedRequestTokenMessage : MessageBase { /// /// Initializes a new instance of the class. /// - internal UnauthorizedRequestTokenMessage() + protected internal UnauthorizedRequestTokenMessage() : base(MessageProtection.None, MessageTransport.Direct) { } @@ -23,12 +23,12 @@ namespace DotNetOAuth.Messages { /// Gets or sets the Request Token. /// [MessagePart(Name = "oauth_token", IsRequired = true)] - internal string RequestToken { get; set; } + public string RequestToken { get; set; } /// /// Gets or sets the Token Secret. /// [MessagePart(Name = "oauth_token_secret", IsRequired = true)] - internal string TokenSecret { get; set; } + public string TokenSecret { get; set; } } } diff --git a/src/DotNetOAuth/Messaging/MessagePartAttribute.cs b/src/DotNetOAuth/Messaging/MessagePartAttribute.cs index ae88b61..91053b6 100644 --- a/src/DotNetOAuth/Messaging/MessagePartAttribute.cs +++ b/src/DotNetOAuth/Messaging/MessagePartAttribute.cs @@ -13,7 +13,7 @@ namespace DotNetOAuth.Messaging { /// Applied to fields and properties that form a key/value in a protocol message. /// [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true, AllowMultiple = false)] - internal sealed class MessagePartAttribute : Attribute { + public sealed class MessagePartAttribute : Attribute { /// /// The overridden name to use as the serialized name for the property. /// @@ -22,7 +22,7 @@ namespace DotNetOAuth.Messaging { /// /// Initializes a new instance of the class. /// - internal MessagePartAttribute() { + public MessagePartAttribute() { } /// @@ -32,7 +32,7 @@ namespace DotNetOAuth.Messaging { /// A special name to give the value of this member in the serialized message. /// When null or empty, the name of the member will be used in the serialized message. /// - internal MessagePartAttribute(string name) { + public MessagePartAttribute(string name) { this.Name = name; } diff --git a/src/DotNetOAuth/Messaging/MessageSerializer.cs b/src/DotNetOAuth/Messaging/MessageSerializer.cs index fd42108..1239dd0 100644 --- a/src/DotNetOAuth/Messaging/MessageSerializer.cs +++ b/src/DotNetOAuth/Messaging/MessageSerializer.cs @@ -103,24 +103,25 @@ namespace DotNetOAuth.Messaging { /// The newly created message object. private IProtocolMessage CreateMessage(MessageReceivingEndpoint recipient) { IProtocolMessage result; + BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; if (typeof(IOAuthDirectedMessage).IsAssignableFrom(this.messageType)) { // Some OAuth messages take just the recipient, while others take the whole endpoint ConstructorInfo ctor; - if ((ctor = this.messageType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(Uri) }, null)) != null) { + if ((ctor = this.messageType.GetConstructor(bindingFlags, null, new Type[] { typeof(Uri) }, null)) != null) { if (recipient == null) { // We need a recipient to deserialize directed messages. throw new ArgumentNullException("recipient"); } result = (IProtocolMessage)ctor.Invoke(new object[] { recipient.Location }); - } else if ((ctor = this.messageType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(MessageReceivingEndpoint) }, null)) != null) { + } else if ((ctor = this.messageType.GetConstructor(bindingFlags, null, new Type[] { typeof(MessageReceivingEndpoint) }, null)) != null) { if (recipient == null) { // We need a recipient to deserialize directed messages. throw new ArgumentNullException("recipient"); } result = (IProtocolMessage)ctor.Invoke(new object[] { recipient }); - } else if ((ctor = this.messageType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null)) != null) { + } else if ((ctor = this.messageType.GetConstructor(bindingFlags, null, new Type[0], null)) != null) { result = (IProtocolMessage)ctor.Invoke(new object[0]); } else { throw new InvalidOperationException("Unrecognized constructor signature on type " + this.messageType); diff --git a/src/DotNetOAuth/ServiceProvider.cs b/src/DotNetOAuth/ServiceProvider.cs index 4168846..135ecd0 100644 --- a/src/DotNetOAuth/ServiceProvider.cs +++ b/src/DotNetOAuth/ServiceProvider.cs @@ -32,19 +32,32 @@ namespace DotNetOAuth { /// /// The endpoints and behavior on the Service Provider. /// The host's method of storing and recalling tokens and secrets. - public ServiceProvider(ServiceProviderDescription serviceDescription, ITokenManager tokenManager) { + public ServiceProvider(ServiceProviderDescription serviceDescription, ITokenManager tokenManager) + : this(serviceDescription, tokenManager, new OAuthServiceProviderMessageTypeProvider(tokenManager)) { + } + + /// + /// Initializes a new instance of the class. + /// + /// The endpoints and behavior on the Service Provider. + /// The host's method of storing and recalling tokens and secrets. + /// An object that can figure out what type of message is being received for deserialization. + public ServiceProvider(ServiceProviderDescription serviceDescription, ITokenManager tokenManager, OAuthServiceProviderMessageTypeProvider messageTypeProvider) { if (serviceDescription == null) { throw new ArgumentNullException("serviceDescription"); } if (tokenManager == null) { throw new ArgumentNullException("tokenManager"); } + if (messageTypeProvider == null) { + throw new ArgumentNullException("messageTypeProvider"); + } var signingElement = serviceDescription.CreateTamperProtectionElement(); signingElement.SignatureVerificationCallback = this.TokenSignatureVerificationCallback; INonceStore store = new NonceMemoryStore(StandardExpirationBindingElement.DefaultMaximumMessageAge); this.ServiceDescription = serviceDescription; - this.Channel = new OAuthChannel(signingElement, store, tokenManager, false); + this.Channel = new OAuthChannel(signingElement, store, messageTypeProvider, new StandardWebRequestHandler()); this.TokenGenerator = new StandardTokenGenerator(); this.TokenManager = tokenManager; } @@ -118,12 +131,12 @@ namespace DotNetOAuth { public Response SendUnauthorizedTokenResponse(RequestTokenMessage request, IDictionary extraParameters) { string token = this.TokenGenerator.GenerateRequestToken(request.ConsumerKey); string secret = this.TokenGenerator.GenerateSecret(); - this.TokenManager.StoreNewRequestToken(request.ConsumerKey, token, secret, ((IProtocolMessage)request).ExtraData, extraParameters); UnauthorizedRequestTokenMessage response = new UnauthorizedRequestTokenMessage { RequestToken = token, TokenSecret = secret, }; response.AddNonOAuthParameters(extraParameters); + this.TokenManager.StoreNewRequestToken(request, response); return this.Channel.Send(response); } -- 2.11.4.GIT