summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs')
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs216
1 files changed, 125 insertions, 91 deletions
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