diff options
Diffstat (limited to 'src/DotNetOpenAuth.OAuth.ServiceProvider')
12 files changed, 322 insertions, 314 deletions
diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj b/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj index 689d08a..8e87ad4 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj @@ -4,6 +4,7 @@ <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> </PropertyGroup> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" /> <PropertyGroup> @@ -18,18 +19,19 @@ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> </PropertyGroup> <ItemGroup> + <Compile Include="OAuthReporting.cs" /> <Compile Include="OAuth\ChannelElements\IConsumerDescription.cs" /> <Compile Include="OAuth\ChannelElements\IServiceProviderAccessToken.cs" /> <Compile Include="OAuth\ChannelElements\IServiceProviderRequestToken.cs" /> <Compile Include="OAuth\ChannelElements\IServiceProviderTokenManager.cs" /> <Compile Include="OAuth\ChannelElements\ITokenGenerator.cs" /> - <Compile Include="OAuth\ChannelElements\OAuth1Principal.cs" /> <Compile Include="OAuth\ChannelElements\OAuthServiceProviderChannel.cs" /> <Compile Include="OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs" /> <Compile Include="OAuth\ChannelElements\RsaSha1ServiceProviderSigningBindingElement.cs" /> <Compile Include="OAuth\ChannelElements\StandardTokenGenerator.cs" /> <Compile Include="OAuth\ChannelElements\TokenHandlingBindingElement.cs" /> <Compile Include="OAuth\ServiceProvider.cs" /> + <Compile Include="OAuth\ServiceProviderHostDescription.cs" /> <Compile Include="OAuth\VerificationCodeFormat.cs" /> <Compile Include="Properties\AssemblyInfo.cs"> <SubType> @@ -50,7 +52,19 @@ <Name>DotNetOpenAuth.OAuth</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Net.Http.WebRequest" /> + <Reference Include="Validation, Version=2.0.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Validation.2.0.2.13022\lib\portable-windows8+net40+sl5+windowsphone8\Validation.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> + <Import Project="$(SolutionDir)\.nuget\nuget.targets" /> </Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/IServiceProviderTokenManager.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/IServiceProviderTokenManager.cs index 2d47d00..1c413a3 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/IServiceProviderTokenManager.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/IServiceProviderTokenManager.cs @@ -7,15 +7,14 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System; using System.Collections.Generic; - using System.Diagnostics.Contracts; using System.Linq; using System.Text; + using Validation; /// <summary> /// A token manager for use by a web site in its role as a /// service provider. /// </summary> - [ContractClass(typeof(IServiceProviderTokenManagerContract))] public interface IServiceProviderTokenManager : ITokenManager { /// <summary> /// Gets the Consumer description for a given a Consumer Key. @@ -79,173 +78,4 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// </remarks> void UpdateToken(IServiceProviderRequestToken token); } - - /// <summary> - /// Code contract class for the <see cref="IServiceProviderTokenManager"/> interface. - /// </summary> - [ContractClassFor(typeof(IServiceProviderTokenManager))] - internal abstract class IServiceProviderTokenManagerContract : IServiceProviderTokenManager { - /// <summary> - /// Prevents a default instance of the <see cref="IServiceProviderTokenManagerContract"/> class from being created. - /// </summary> - private IServiceProviderTokenManagerContract() { - } - - #region IServiceProviderTokenManager Members - - /// <summary> - /// Gets the Consumer description for a given a Consumer Key. - /// </summary> - /// <param name="consumerKey">The Consumer Key.</param> - /// <returns> - /// A description of the consumer. Never null. - /// </returns> - /// <exception cref="KeyNotFoundException">Thrown if the consumer key cannot be found.</exception> - IConsumerDescription IServiceProviderTokenManager.GetConsumer(string consumerKey) { - Requires.NotNullOrEmpty(consumerKey, "consumerKey"); - Contract.Ensures(Contract.Result<IConsumerDescription>() != null); - throw new NotImplementedException(); - } - - /// <summary> - /// Checks whether a given request token has already been authorized - /// by some user for use by the Consumer that requested it. - /// </summary> - /// <param name="requestToken">The Consumer's request token.</param> - /// <returns> - /// True if the request token has already been fully authorized by the user - /// who owns the relevant protected resources. False if the token has not yet - /// been authorized, has expired or does not exist. - /// </returns> - bool IServiceProviderTokenManager.IsRequestTokenAuthorized(string requestToken) { - Requires.NotNullOrEmpty(requestToken, "requestToken"); - throw new NotImplementedException(); - } - - /// <summary> - /// Gets details on the named request token. - /// </summary> - /// <param name="token">The request token.</param> - /// <returns>A description of the token. Never null.</returns> - /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception> - /// <remarks> - /// It is acceptable for implementations to find the token, see that it has expired, - /// delete it from the database and then throw <see cref="KeyNotFoundException"/>, - /// or alternatively it can return the expired token anyway and the OAuth channel will - /// log and throw the appropriate error. - /// </remarks> - IServiceProviderRequestToken IServiceProviderTokenManager.GetRequestToken(string token) { - Requires.NotNullOrEmpty(token, "token"); - Contract.Ensures(Contract.Result<IServiceProviderRequestToken>() != null); - throw new NotImplementedException(); - } - - /// <summary> - /// Gets details on the named access token. - /// </summary> - /// <param name="token">The access token.</param> - /// <returns>A description of the token. Never null.</returns> - /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception> - /// <remarks> - /// It is acceptable for implementations to find the token, see that it has expired, - /// delete it from the database and then throw <see cref="KeyNotFoundException"/>, - /// or alternatively it can return the expired token anyway and the OAuth channel will - /// log and throw the appropriate error. - /// </remarks> - IServiceProviderAccessToken IServiceProviderTokenManager.GetAccessToken(string token) { - Requires.NotNullOrEmpty(token, "token"); - Contract.Ensures(Contract.Result<IServiceProviderAccessToken>() != null); - throw new NotImplementedException(); - } - - /// <summary> - /// Persists any changes made to the token. - /// </summary> - /// <param name="token">The token whose properties have been changed.</param> - /// <remarks> - /// This library will invoke this method after making a set - /// of changes to the token as part of a web request to give the host - /// the opportunity to persist those changes to a database. - /// Depending on the object persistence framework the host site uses, - /// this method MAY not need to do anything (if changes made to the token - /// will automatically be saved without any extra handling). - /// </remarks> - void IServiceProviderTokenManager.UpdateToken(IServiceProviderRequestToken token) { - Requires.NotNull(token, "token"); - throw new NotImplementedException(); - } - - #endregion - - #region ITokenManager Members - - /// <summary> - /// Gets the Token Secret given a request or access token. - /// </summary> - /// <param name="token">The request or access token.</param> - /// <returns> - /// The secret associated with the given token. - /// </returns> - /// <exception cref="ArgumentException">Thrown if the secret cannot be found for the given token.</exception> - string ITokenManager.GetTokenSecret(string token) { - throw new NotImplementedException(); - } - - /// <summary> - /// Stores a newly generated unauthorized request token, secret, and optional - /// application-specific parameters for later recall. - /// </summary> - /// <param name="request">The request message that resulted in the generation of a new unauthorized request token.</param> - /// <param name="response">The response message that includes the unauthorized request token.</param> - /// <exception cref="ArgumentException">Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection.</exception> - /// <remarks> - /// Request tokens stored by this method SHOULD NOT associate any user account with this token. - /// It usually opens up security holes in your application to do so. Instead, you associate a user - /// account with access tokens (not request tokens) in the <see cref="ITokenManager.ExpireRequestTokenAndStoreNewAccessToken"/> - /// method. - /// </remarks> - void ITokenManager.StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response) { - throw new NotImplementedException(); - } - - /// <summary> - /// Deletes a request token and its associated secret and stores a new access token and secret. - /// </summary> - /// <param name="consumerKey">The Consumer that is exchanging its request token for an access token.</param> - /// <param name="requestToken">The Consumer's request token that should be deleted/expired.</param> - /// <param name="accessToken">The new access token that is being issued to the Consumer.</param> - /// <param name="accessTokenSecret">The secret associated with the newly issued access token.</param> - /// <remarks> - /// <para> - /// Any scope of granted privileges associated with the request token from the - /// original call to <see cref="ITokenManager.StoreNewRequestToken"/> should be carried over - /// to the new Access Token. - /// </para> - /// <para> - /// To associate a user account with the new access token, - /// <see cref="System.Web.HttpContext.User">HttpContext.Current.User</see> may be - /// useful in an ASP.NET web application within the implementation of this method. - /// Alternatively you may store the access token here without associating with a user account, - /// and wait until WebConsumer.ProcessUserAuthorization or - /// DesktopConsumer.ProcessUserAuthorization return the access - /// token to associate the access token with a user account at that point. - /// </para> - /// </remarks> - void ITokenManager.ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { - throw new NotImplementedException(); - } - - /// <summary> - /// Classifies a token as a request token or an access token. - /// </summary> - /// <param name="token">The token to classify.</param> - /// <returns> - /// Request or Access token, or invalid if the token is not recognized. - /// </returns> - TokenType ITokenManager.GetTokenType(string token) { - throw new NotImplementedException(); - } - - #endregion - } } diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuth1Principal.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuth1Principal.cs deleted file mode 100644 index 03f8030..0000000 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuth1Principal.cs +++ /dev/null @@ -1,33 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OAuth1Principal.cs" company="Outercurve Foundation"> -// Copyright (c) Outercurve Foundation. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OAuth.ChannelElements { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using System.Runtime.InteropServices; - using System.Text; - - /// <summary> - /// Represents an OAuth consumer that is impersonating a known user on the system. - /// </summary> - [SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "Not cocreatable.")] - [Serializable] - [ComVisible(true)] - internal class OAuth1Principal : OAuthPrincipal { - /// <summary> - /// Initializes a new instance of the <see cref="OAuth1Principal"/> class. - /// </summary> - /// <param name="token">The access token.</param> - internal OAuth1Principal(IServiceProviderAccessToken token) - : base(token.Username, token.Roles) { - Requires.NotNull(token, "token"); - - this.AccessToken = token.Token; - } - } -} diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderChannel.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderChannel.cs index 0d6450f..cb9a91b 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderChannel.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderChannel.cs @@ -8,32 +8,34 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; + using Validation; /// <summary> /// The messaging channel for OAuth 1.0(a) Service Providers. /// </summary> internal class OAuthServiceProviderChannel : OAuthChannel { /// <summary> - /// Initializes a new instance of the <see cref="OAuthServiceProviderChannel"/> class. + /// Initializes a new instance of the <see cref="OAuthServiceProviderChannel" /> class. /// </summary> /// <param name="signingBindingElement">The binding element to use for signing.</param> /// <param name="store">The web application store to use for nonces.</param> /// <param name="tokenManager">The token manager instance to use.</param> /// <param name="securitySettings">The security settings.</param> /// <param name="messageTypeProvider">The message type provider.</param> + /// <param name="hostFactories">The host factories.</param> [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")] - internal OAuthServiceProviderChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings, IMessageFactory messageTypeProvider = null) + internal OAuthServiceProviderChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings, IMessageFactory messageTypeProvider = null, IHostFactories hostFactories = null) : base( signingBindingElement, tokenManager, securitySettings, messageTypeProvider ?? new OAuthServiceProviderMessageFactory(tokenManager), - InitializeBindingElements(signingBindingElement, store, tokenManager, securitySettings)) { + InitializeBindingElements(signingBindingElement, store, tokenManager, securitySettings), + hostFactories) { Requires.NotNull(tokenManager, "tokenManager"); Requires.NotNull(securitySettings, "securitySettings"); Requires.NotNull(signingBindingElement, "signingBindingElement"); @@ -59,7 +61,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// An array of binding elements used to initialize the channel. /// </returns> private static IChannelBindingElement[] InitializeBindingElements(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, ITokenManager tokenManager, SecuritySettings securitySettings) { - Contract.Requires(securitySettings != null); + Requires.NotNull(securitySettings, "securitySettings"); var bindingElements = OAuthChannel.InitializeBindingElements(signingBindingElement, store); diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs index 3dcee04..38a1f56 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs @@ -7,9 +7,9 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System; using System.Collections.Generic; - using System.Diagnostics.Contracts; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth.Messages; + using Validation; /// <summary> /// An OAuth-protocol specific implementation of the <see cref="IMessageFactory"/> diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/RsaSha1ServiceProviderSigningBindingElement.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/RsaSha1ServiceProviderSigningBindingElement.cs index d1324d4..fd0d3ad 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/RsaSha1ServiceProviderSigningBindingElement.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/RsaSha1ServiceProviderSigningBindingElement.cs @@ -7,11 +7,11 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System; using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using DotNetOpenAuth.Messaging; + using Validation; /// <summary> /// A binding element that signs outgoing messages and verifies the signature on incoming messages. diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/TokenHandlingBindingElement.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/TokenHandlingBindingElement.cs index e37cc2f..5875650 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/TokenHandlingBindingElement.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/TokenHandlingBindingElement.cs @@ -8,12 +8,14 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; using System.Linq; using System.Text; + using System.Threading; + using System.Threading.Tasks; using DotNetOpenAuth.Configuration; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth.Messages; + using Validation; /// <summary> /// A binding element for Service Providers to manage the @@ -68,6 +70,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// Prepares a message for sending based on the rules of this channel binding element. /// </summary> /// <param name="message">The message to prepare for sending.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// The protections (if any) that this binding element applied to the message. /// Null if this binding element did not even apply to this binding element. @@ -76,13 +79,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// Implementations that provide message protection must honor the /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. /// </remarks> - public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) { + public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) { var userAuthResponse = message as UserAuthorizationResponse; if (userAuthResponse != null && userAuthResponse.Version >= Protocol.V10a.Version) { var requestToken = this.tokenManager.GetRequestToken(userAuthResponse.RequestToken); requestToken.VerificationCode = userAuthResponse.VerificationCode; this.tokenManager.UpdateToken(requestToken); - return MessageProtections.None; + return MessageProtectionTasks.None; } // Hook to store the token and secret on its way down to the Consumer. @@ -98,10 +101,10 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { } this.tokenManager.UpdateToken(requestToken); - return MessageProtections.None; + return MessageProtectionTasks.None; } - return null; + return MessageProtectionTasks.Null; } /// <summary> @@ -109,6 +112,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// validates an incoming message based on the rules of this channel binding element. /// </summary> /// <param name="message">The incoming message to process.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// The protections (if any) that this binding element applied to the message. /// Null if this binding element did not even apply to this binding element. @@ -121,13 +125,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// Implementations that provide message protection must honor the /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable. /// </remarks> - public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) { + public Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) { var authorizedTokenRequest = message as AuthorizedTokenRequest; if (authorizedTokenRequest != null) { if (authorizedTokenRequest.Version >= Protocol.V10a.Version) { string expectedVerifier = this.tokenManager.GetRequestToken(authorizedTokenRequest.RequestToken).VerificationCode; ErrorUtilities.VerifyProtocol(string.Equals(authorizedTokenRequest.VerificationCode, expectedVerifier, StringComparison.Ordinal), OAuthStrings.IncorrectVerifier); - return MessageProtections.None; + return MessageProtectionTasks.None; } this.VerifyThrowTokenTimeToLive(authorizedTokenRequest); @@ -143,7 +147,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { this.VerifyThrowTokenNotExpired(accessResourceRequest); } - return null; + return MessageProtectionTasks.Null; } #endregion diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs index ecfd191..b1deb74 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs @@ -9,16 +9,19 @@ namespace DotNetOpenAuth.OAuth { using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; using System.Globalization; + using System.Net.Http; using System.Security.Principal; using System.ServiceModel.Channels; + using System.Threading; + using System.Threading.Tasks; using System.Web; using DotNetOpenAuth.Configuration; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth.ChannelElements; using DotNetOpenAuth.OAuth.Messages; + using Validation; /// <summary> /// A web application that allows access via OAuth. @@ -34,7 +37,7 @@ namespace DotNetOpenAuth.OAuth { public class ServiceProvider : IDisposable { /// <summary> /// The name of the key to use in the HttpApplication cache to store the - /// instance of <see cref="NonceMemoryStore"/> to use. + /// instance of <see cref="MemoryNonceStore"/> to use. /// </summary> private const string ApplicationStoreKey = "DotNetOpenAuth.OAuth.ServiceProvider.HttpApplicationStore"; @@ -53,7 +56,7 @@ namespace DotNetOpenAuth.OAuth { /// </summary> /// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param> /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param> - public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager) + public ServiceProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager) : this(serviceDescription, tokenManager, new OAuthServiceProviderMessageFactory(tokenManager)) { } @@ -63,8 +66,8 @@ namespace DotNetOpenAuth.OAuth { /// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param> /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param> /// <param name="messageTypeProvider">An object that can figure out what type of message is being received for deserialization.</param> - public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider) - : this(serviceDescription, tokenManager, OAuthElement.Configuration.ServiceProvider.ApplicationStore.CreateInstance(HttpApplicationStore), messageTypeProvider) { + public ServiceProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider) + : this(serviceDescription, tokenManager, OAuthElement.Configuration.ServiceProvider.ApplicationStore.CreateInstance(GetHttpApplicationStore(), null), messageTypeProvider) { Requires.NotNull(serviceDescription, "serviceDescription"); Requires.NotNull(tokenManager, "tokenManager"); Requires.NotNull(messageTypeProvider, "messageTypeProvider"); @@ -76,7 +79,7 @@ namespace DotNetOpenAuth.OAuth { /// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param> /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param> /// <param name="nonceStore">The nonce store.</param> - public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore) + public ServiceProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore) : this(serviceDescription, tokenManager, nonceStore, new OAuthServiceProviderMessageFactory(tokenManager)) { } @@ -87,7 +90,7 @@ namespace DotNetOpenAuth.OAuth { /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param> /// <param name="nonceStore">The nonce store.</param> /// <param name="messageTypeProvider">An object that can figure out what type of message is being received for deserialization.</param> - public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore, OAuthServiceProviderMessageFactory messageTypeProvider) { + public ServiceProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore, OAuthServiceProviderMessageFactory messageTypeProvider) { Requires.NotNull(serviceDescription, "serviceDescription"); Requires.NotNull(tokenManager, "tokenManager"); Requires.NotNull(nonceStore, "nonceStore"); @@ -103,36 +106,9 @@ namespace DotNetOpenAuth.OAuth { } /// <summary> - /// Gets the standard state storage mechanism that uses ASP.NET's - /// HttpApplication state dictionary to store associations and nonces. - /// </summary> - [EditorBrowsable(EditorBrowsableState.Advanced)] - public static INonceStore HttpApplicationStore { - get { - Contract.Ensures(Contract.Result<INonceStore>() != null); - - HttpContext context = HttpContext.Current; - ErrorUtilities.VerifyOperation(context != null, Strings.StoreRequiredWhenNoHttpContextAvailable, typeof(INonceStore).Name); - var store = (INonceStore)context.Application[ApplicationStoreKey]; - if (store == null) { - context.Application.Lock(); - try { - if ((store = (INonceStore)context.Application[ApplicationStoreKey]) == null) { - context.Application[ApplicationStoreKey] = store = new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge); - } - } finally { - context.Application.UnLock(); - } - } - - return store; - } - } - - /// <summary> /// Gets the description of this Service Provider. /// </summary> - public ServiceProviderDescription ServiceDescription { get; private set; } + public ServiceProviderHostDescription ServiceDescription { get; private set; } /// <summary> /// Gets or sets the generator responsible for generating new tokens and secrets. @@ -173,6 +149,33 @@ namespace DotNetOpenAuth.OAuth { } /// <summary> + /// Gets the standard state storage mechanism that uses ASP.NET's + /// HttpApplication state dictionary to store associations and nonces. + /// </summary> + /// <param name="context">The HTTP context. If <c>null</c>, this method must be called while <see cref="HttpContext.Current"/> is non-null.</param> + /// <returns>The nonce store.</returns> + public static INonceStore GetHttpApplicationStore(HttpContextBase context = null) { + if (context == null) { + ErrorUtilities.VerifyOperation(HttpContext.Current != null, Strings.StoreRequiredWhenNoHttpContextAvailable, typeof(INonceStore).Name); + context = new HttpContextWrapper(HttpContext.Current); + } + + var store = (INonceStore)context.Application[ApplicationStoreKey]; + if (store == null) { + context.Application.Lock(); + try { + if ((store = (INonceStore)context.Application[ApplicationStoreKey]) == null) { + context.Application[ApplicationStoreKey] = store = new MemoryNonceStore(StandardExpirationBindingElement.MaximumMessageAge); + } + } finally { + context.Application.UnLock(); + } + } + + return store; + } + + /// <summary> /// Creates a cryptographically strong random verification code. /// </summary> /// <param name="format">The desired format of the verification code.</param> @@ -182,7 +185,7 @@ namespace DotNetOpenAuth.OAuth { /// length of the final string.</param> /// <returns>The verification code.</returns> public static string CreateVerificationCode(VerificationCodeFormat format, int length) { - Requires.InRange(length >= 0, "length"); + Requires.Range(length >= 0, "length"); switch (format) { case VerificationCodeFormat.IncludedInCallback: @@ -203,46 +206,65 @@ namespace DotNetOpenAuth.OAuth { /// <summary> /// Reads any incoming OAuth message. /// </summary> - /// <returns>The deserialized message.</returns> + /// <param name="request">The request.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The deserialized message. + /// </returns> /// <remarks> /// Requires HttpContext.Current. /// </remarks> - public IDirectedProtocolMessage ReadRequest() { - return this.Channel.ReadFromRequest(); + public Task<IDirectedProtocolMessage> ReadRequestAsync(HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) { + return this.ReadRequestAsync((request ?? this.Channel.GetRequestFromContext()).AsHttpRequestMessage(), cancellationToken); } /// <summary> /// Reads any incoming OAuth message. /// </summary> - /// <param name="request">The HTTP request to read the message from.</param> - /// <returns>The deserialized message.</returns> - public IDirectedProtocolMessage ReadRequest(HttpRequestBase request) { - return this.Channel.ReadFromRequest(request); + /// <param name="request">The request.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The deserialized message. + /// </returns> + /// <remarks> + /// Requires HttpContext.Current. + /// </remarks> + public Task<IDirectedProtocolMessage> ReadRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken)) { + Requires.NotNull(request, "request"); + return this.Channel.ReadFromRequestAsync(request, cancellationToken); } /// <summary> - /// Gets the incoming request for an unauthorized token, if any. + /// Reads a request for an unauthorized token from the incoming HTTP request. /// </summary> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="request">The HTTP request to read from.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - /// <remarks> - /// Requires HttpContext.Current. - /// </remarks> - public UnauthorizedTokenRequest ReadTokenRequest() { - return this.ReadTokenRequest(this.Channel.GetRequestFromContext()); + public Task<UnauthorizedTokenRequest> ReadTokenRequestAsync( + HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) { + return this.ReadTokenRequestAsync((request ?? this.channel.GetRequestFromContext()).AsHttpRequestMessage(), cancellationToken); } /// <summary> /// Reads a request for an unauthorized token from the incoming HTTP request. /// </summary> /// <param name="request">The HTTP request to read from.</param> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public UnauthorizedTokenRequest ReadTokenRequest(HttpRequestBase request) { - UnauthorizedTokenRequest message; - if (this.Channel.TryReadFromRequest(request, out message)) { + public async Task<UnauthorizedTokenRequest> ReadTokenRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken)) { + Requires.NotNull(request, "request"); + + var message = await this.Channel.TryReadFromRequestAsync<UnauthorizedTokenRequest>(request, cancellationToken); + if (message != null) { ErrorUtilities.VerifyProtocol(message.Version >= Protocol.Lookup(this.SecuritySettings.MinimumRequiredOAuthVersion).Version, OAuthStrings.MinimumConsumerVersionRequirementNotMet, this.SecuritySettings.MinimumRequiredOAuthVersion, message.Version); } + return message; } @@ -263,16 +285,18 @@ namespace DotNetOpenAuth.OAuth { } /// <summary> - /// Gets the incoming request for the Service Provider to authorize a Consumer's - /// access to some protected resources. + /// Reads in a Consumer's request for the Service Provider to obtain permission from + /// the user to authorize the Consumer's access of some protected resource(s). /// </summary> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="request">The HTTP request to read from.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - /// <remarks> - /// Requires HttpContext.Current. - /// </remarks> - public UserAuthorizationRequest ReadAuthorizationRequest() { - return this.ReadAuthorizationRequest(this.Channel.GetRequestFromContext()); + public Task<UserAuthorizationRequest> ReadAuthorizationRequestAsync(HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) { + request = request ?? this.channel.GetRequestFromContext(); + return this.ReadAuthorizationRequestAsync(request.AsHttpRequestMessage(), cancellationToken); } /// <summary> @@ -280,12 +304,14 @@ namespace DotNetOpenAuth.OAuth { /// the user to authorize the Consumer's access of some protected resource(s). /// </summary> /// <param name="request">The HTTP request to read from.</param> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public UserAuthorizationRequest ReadAuthorizationRequest(HttpRequestBase request) { - UserAuthorizationRequest message; - this.Channel.TryReadFromRequest(request, out message); - return message; + public Task<UserAuthorizationRequest> ReadAuthorizationRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken)) { + Requires.NotNull(request, "request"); + return this.Channel.TryReadFromRequestAsync<UserAuthorizationRequest>(request, cancellationToken); } /// <summary> @@ -351,27 +377,31 @@ namespace DotNetOpenAuth.OAuth { } /// <summary> - /// Gets the incoming request to exchange an authorized token for an access token. + /// Reads in a Consumer's request to exchange an authorized request token for an access token. /// </summary> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="request">The HTTP request to read from.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - /// <remarks> - /// Requires HttpContext.Current. - /// </remarks> - public AuthorizedTokenRequest ReadAccessTokenRequest() { - return this.ReadAccessTokenRequest(this.Channel.GetRequestFromContext()); + public Task<AuthorizedTokenRequest> ReadAccessTokenRequestAsync(HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) { + request = request ?? this.Channel.GetRequestFromContext(); + return this.ReadAccessTokenRequestAsync(request.AsHttpRequestMessage(), cancellationToken); } /// <summary> /// Reads in a Consumer's request to exchange an authorized request token for an access token. /// </summary> /// <param name="request">The HTTP request to read from.</param> - /// <returns>The incoming request, or null if no OAuth message was attached.</returns> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns> + /// The incoming request, or null if no OAuth message was attached. + /// </returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public AuthorizedTokenRequest ReadAccessTokenRequest(HttpRequestBase request) { - AuthorizedTokenRequest message; - this.Channel.TryReadFromRequest(request, out message); - return message; + public Task<AuthorizedTokenRequest> ReadAccessTokenRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken)) { + Requires.NotNull(request, "request"); + return this.Channel.TryReadFromRequestAsync<AuthorizedTokenRequest>(request, cancellationToken); } /// <summary> @@ -398,6 +428,9 @@ namespace DotNetOpenAuth.OAuth { /// <summary> /// Gets the authorization (access token) for accessing some protected resource. /// </summary> + /// <param name="request">HTTP details from an incoming WCF message.</param> + /// <param name="requestUri">The URI of the WCF service endpoint.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The authorization message sent by the Consumer, or null if no authorization message is attached.</returns> /// <remarks> /// This method verifies that the access token and token secret are valid. @@ -405,15 +438,15 @@ namespace DotNetOpenAuth.OAuth { /// to access the resources being requested. /// </remarks> /// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception> - public AccessProtectedResourceRequest ReadProtectedResourceAuthorization() { - return this.ReadProtectedResourceAuthorization(this.Channel.GetRequestFromContext()); + public Task<AccessProtectedResourceRequest> ReadProtectedResourceAuthorizationAsync(HttpRequestMessageProperty request, Uri requestUri, CancellationToken cancellationToken = default(CancellationToken)) { + return this.ReadProtectedResourceAuthorizationAsync(new HttpRequestInfo(request, requestUri), cancellationToken); } /// <summary> /// Gets the authorization (access token) for accessing some protected resource. /// </summary> - /// <param name="request">HTTP details from an incoming WCF message.</param> - /// <param name="requestUri">The URI of the WCF service endpoint.</param> + /// <param name="request">The incoming HTTP request.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The authorization message sent by the Consumer, or null if no authorization message is attached.</returns> /// <remarks> /// This method verifies that the access token and token secret are valid. @@ -421,14 +454,16 @@ namespace DotNetOpenAuth.OAuth { /// to access the resources being requested. /// </remarks> /// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception> - public AccessProtectedResourceRequest ReadProtectedResourceAuthorization(HttpRequestMessageProperty request, Uri requestUri) { - return this.ReadProtectedResourceAuthorization(new HttpRequestInfo(request, requestUri)); + public Task<AccessProtectedResourceRequest> ReadProtectedResourceAuthorizationAsync(HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) { + request = request ?? this.channel.GetRequestFromContext(); + return this.ReadProtectedResourceAuthorizationAsync(request.AsHttpRequestMessage(), cancellationToken); } /// <summary> /// Gets the authorization (access token) for accessing some protected resource. /// </summary> /// <param name="request">The incoming HTTP request.</param> + /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The authorization message sent by the Consumer, or null if no authorization message is attached.</returns> /// <remarks> /// This method verifies that the access token and token secret are valid. @@ -436,11 +471,10 @@ namespace DotNetOpenAuth.OAuth { /// to access the resources being requested. /// </remarks> /// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception> - public AccessProtectedResourceRequest ReadProtectedResourceAuthorization(HttpRequestBase request) { + public async Task<AccessProtectedResourceRequest> ReadProtectedResourceAuthorizationAsync(HttpRequestMessage request, CancellationToken cancellationToken = default(CancellationToken)) { Requires.NotNull(request, "request"); - - AccessProtectedResourceRequest accessMessage; - if (this.Channel.TryReadFromRequest<AccessProtectedResourceRequest>(request, out accessMessage)) { + var accessMessage = await this.Channel.TryReadFromRequestAsync<AccessProtectedResourceRequest>(request, cancellationToken); + if (accessMessage != null) { if (this.TokenManager.GetTokenType(accessMessage.AccessToken) != TokenType.AccessToken) { throw new ProtocolException( string.Format( @@ -458,11 +492,11 @@ namespace DotNetOpenAuth.OAuth { /// </summary> /// <param name="request">The request.</param> /// <returns>The <see cref="IPrincipal"/> instance that can be used for access control of resources.</returns> - public OAuthPrincipal CreatePrincipal(AccessProtectedResourceRequest request) { + public IPrincipal CreatePrincipal(AccessProtectedResourceRequest request) { Requires.NotNull(request, "request"); IServiceProviderAccessToken accessToken = this.TokenManager.GetAccessToken(request.AccessToken); - return new OAuth1Principal(accessToken); + return OAuthPrincipal.CreatePrincipal(accessToken.Username, accessToken.Roles); } #region IDisposable Members diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs new file mode 100644 index 0000000..33834eb --- /dev/null +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------- +// <copyright file="ServiceProviderHostDescription.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OAuth { + using System; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth.ChannelElements; + + /// <summary> + /// A description of the endpoints on a Service Provider. + /// </summary> + public class ServiceProviderHostDescription { + /// <summary> + /// The field used to store the value of the <see cref="RequestTokenEndpoint"/> property. + /// </summary> + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private MessageReceivingEndpoint requestTokenEndpoint; + + /// <summary> + /// Initializes a new instance of the <see cref="ServiceProviderHostDescription"/> class. + /// </summary> + public ServiceProviderHostDescription() { + this.ProtocolVersion = Protocol.Default.ProtocolVersion; + } + + /// <summary> + /// Gets or sets the OAuth version supported by the Service Provider. + /// </summary> + public ProtocolVersion ProtocolVersion { get; set; } + + /// <summary> + /// Gets or sets the URL used to obtain an unauthorized Request Token, + /// described in Section 6.1 (Obtaining an Unauthorized Request Token). + /// </summary> + /// <remarks> + /// The request URL query MUST NOT contain any OAuth Protocol Parameters. + /// This is the URL that <see cref="OAuth.Messages.UnauthorizedTokenRequest"/> messages are directed to. + /// </remarks> + /// <exception cref="ArgumentException">Thrown if this property is set to a URI with OAuth protocol parameters.</exception> + public MessageReceivingEndpoint RequestTokenEndpoint { + get { + return this.requestTokenEndpoint; + } + + set { + if (value != null && UriUtil.QueryStringContainPrefixedParameters(value.Location, OAuth.Protocol.ParameterPrefix)) { + throw new ArgumentException(OAuthStrings.RequestUrlMustNotHaveOAuthParameters); + } + + this.requestTokenEndpoint = value; + } + } + + /// <summary> + /// Gets or sets the URL used to obtain User authorization for Consumer access, + /// described in Section 6.2 (Obtaining User Authorization). + /// </summary> + /// <remarks> + /// This is the URL that <see cref="OAuth.Messages.UserAuthorizationRequest"/> messages are + /// indirectly (via the user agent) sent to. + /// </remarks> + public MessageReceivingEndpoint UserAuthorizationEndpoint { get; set; } + + /// <summary> + /// Gets or sets the URL used to exchange the User-authorized Request Token + /// for an Access Token, described in Section 6.3 (Obtaining an Access Token). + /// </summary> + /// <remarks> + /// This is the URL that <see cref="OAuth.Messages.AuthorizedTokenRequest"/> messages are directed to. + /// </remarks> + public MessageReceivingEndpoint AccessTokenEndpoint { get; set; } + + /// <summary> + /// Gets or sets the signing policies that apply to this Service Provider. + /// </summary> + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Type initializers require this format.")] + public ITamperProtectionChannelBindingElement[] TamperProtectionElements { get; set; } + + /// <summary> + /// Gets the OAuth version supported by the Service Provider. + /// </summary> + internal Version Version { + get { return Protocol.Lookup(this.ProtocolVersion).Version; } + } + + /// <summary> + /// Creates a signing element that includes all the signing elements this service provider supports. + /// </summary> + /// <returns>The created signing element.</returns> + internal ITamperProtectionChannelBindingElement CreateTamperProtectionElement() { + RequiresEx.ValidState(this.TamperProtectionElements != null); + return new SigningBindingElementChain(this.TamperProtectionElements.Select(el => (ITamperProtectionChannelBindingElement)el.Clone()).ToArray()); + } + } +} diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs new file mode 100644 index 0000000..5b00c1a --- /dev/null +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthReporting.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging.Bindings; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using Validation; + + /// <summary> + /// Utility methods specific to OAuth feature reporting. + /// </summary> + internal class OAuthReporting : Reporting { + /// <summary> + /// Records the feature and dependency use. + /// </summary> + /// <param name="value">The consumer or service provider.</param> + /// <param name="service">The service.</param> + /// <param name="tokenManager">The token manager.</param> + /// <param name="nonceStore">The nonce store.</param> + internal static void RecordFeatureAndDependencyUse(object value, ServiceProviderHostDescription service, ITokenManager tokenManager, INonceStore nonceStore) { + Requires.NotNull(value, "value"); + Requires.NotNull(service, "service"); + Requires.NotNull(tokenManager, "tokenManager"); + + // In release builds, just quietly return. + if (value == null || service == null || tokenManager == null) { + return; + } + + if (Reporting.Enabled && Reporting.Configuration.IncludeFeatureUsage) { + StringBuilder builder = new StringBuilder(); + builder.Append(value.GetType().Name); + builder.Append(" "); + builder.Append(tokenManager.GetType().Name); + if (nonceStore != null) { + builder.Append(" "); + builder.Append(nonceStore.GetType().Name); + } + builder.Append(" "); + builder.Append(service.UserAuthorizationEndpoint != null ? service.UserAuthorizationEndpoint.Location.AbsoluteUri : string.Empty); + Reporting.ObservedFeatures.Add(builder.ToString()); + Reporting.Touch(); + } + } + } +} diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/Properties/AssemblyInfo.cs index aa99a01..63af312 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/Properties/AssemblyInfo.cs @@ -7,7 +7,6 @@ // We DON'T put an AssemblyVersionAttribute in here because it is generated in the build. using System; -using System.Diagnostics.Contracts; using System.Net; using System.Reflection; using System.Resources; @@ -31,8 +30,6 @@ using System.Web.UI; // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("7d73990c-47c0-4256-9f20-a893add9e289")] -[assembly: ContractVerification(true)] - #if StrongNameSigned // See comment at top of this file. We need this so that strong-naming doesn't // keep this assembly from being useful to shared host (medium trust) web sites. diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/packages.config b/src/DotNetOpenAuth.OAuth.ServiceProvider/packages.config new file mode 100644 index 0000000..d32d62f --- /dev/null +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" /> + <package id="Validation" version="2.0.2.13022" targetFramework="net45" /> +</packages>
\ No newline at end of file |