summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs127
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/CookieOAuthTokenManager.cs79
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs60
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthTokenManager.cs38
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs12
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs160
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs52
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs35
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/SimpleConsumerTokenManager.cs104
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs50
-rw-r--r--src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj8
-rw-r--r--src/DotNetOpenAuth.AspNet/WebResources.Designer.cs11
-rw-r--r--src/DotNetOpenAuth.AspNet/WebResources.resx3
-rw-r--r--src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj2
-rw-r--r--src/DotNetOpenAuth.Core/MachineKeyUtil.cs (renamed from src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs)4
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/Bindings/HardCodedKeyCryptoKeyStore.cs98
-rw-r--r--src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs9
-rw-r--r--src/DotNetOpenAuth.Core/Strings.Designer.cs11
-rw-r--r--src/DotNetOpenAuth.Core/Strings.resx3
-rw-r--r--src/DotNetOpenAuth.OAuth.Common/DotNetOpenAuth.OAuth.Common.csproj1
-rw-r--r--src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthIdentity.cs64
-rw-r--r--src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthPrincipal.cs98
-rw-r--r--src/DotNetOpenAuth.OAuth.Common/Properties/AssemblyInfo.cs4
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/DotNetOpenAuth.OAuth.Consumer.csproj14
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessToken.cs39
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessTokenResponse.cs19
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/IConsumerTokenManager.cs25
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerChannel.cs67
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerMessageFactory.cs108
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/RsaSha1ConsumerSigningBindingElement.cs76
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/Consumer.cs336
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ConsumerBase.cs258
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/CookieTemporaryCredentialStorage.cs130
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/DesktopConsumer.cs79
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ITemporaryCredentialStorage.cs40
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/MemoryTemporaryCredentialStorage.cs65
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1HttpMessageHandlerBase.cs42
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1RsaSha1HttpMessageHandler.cs15
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/ServiceProviderDescription.cs85
-rw-r--r--src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs87
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj3
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuth1Principal.cs34
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs14
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs (renamed from src/DotNetOpenAuth.OAuth/OAuth/ServiceProviderDescription.cs)8
-rw-r--r--src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs (renamed from src/DotNetOpenAuth.OAuth/OAuthReporting.cs)6
-rw-r--r--src/DotNetOpenAuth.OAuth/DotNetOpenAuth.OAuth.csproj3
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBaseSimple.cs10
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Protocol.cs25
-rw-r--r--src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs33
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.cs10
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs5
-rw-r--r--src/DotNetOpenAuth.OpenIdOAuth/OAuth/ServiceProviderOpenIdProvider.cs8
-rw-r--r--src/DotNetOpenAuth.OpenIdOAuth/OAuth/WebConsumerOpenIdRelyingParty.cs41
55 files changed, 1098 insertions, 1624 deletions
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs
deleted file mode 100644
index efc382f..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="AuthenticationOnlyCookieOAuthTokenManager.cs" company="Microsoft">
-// Copyright (c) Microsoft. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.AspNet.Clients {
- using System;
- using System.Text;
- using System.Web;
- using System.Web.Security;
-
- /// <summary>
- /// Stores OAuth tokens in the current request's cookie
- /// </summary>
- public class AuthenticationOnlyCookieOAuthTokenManager : IOAuthTokenManager {
- /// <summary>
- /// Key used for token cookie
- /// </summary>
- protected const string TokenCookieKey = "OAuthTokenSecret";
-
- /// <summary>
- /// Primary request context.
- /// </summary>
- private readonly HttpContextBase primaryContext;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> class.
- /// </summary>
- public AuthenticationOnlyCookieOAuthTokenManager() {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> class.
- /// </summary>
- /// <param name="context">The current request context.</param>
- public AuthenticationOnlyCookieOAuthTokenManager(HttpContextBase context) {
- this.primaryContext = context;
- }
-
- /// <summary>
- /// Gets the effective HttpContext object to use.
- /// </summary>
- protected HttpContextBase Context {
- get {
- return this.primaryContext ?? new HttpContextWrapper(HttpContext.Current);
- }
- }
-
- /// <summary>
- /// Gets the token secret from the specified token.
- /// </summary>
- /// <param name="token">The token.</param>
- /// <returns>
- /// The token's secret
- /// </returns>
- public virtual string GetTokenSecret(string token) {
- HttpCookie cookie = this.Context.Request.Cookies[TokenCookieKey];
- if (cookie == null || string.IsNullOrEmpty(cookie.Values[token])) {
- return null;
- }
-
- string secret = DecodeAndUnprotectToken(token, cookie.Values[token]);
- return secret;
- }
-
- /// <summary>
- /// Replaces the request token with access token.
- /// </summary>
- /// <param name="requestToken">The request token.</param>
- /// <param name="accessToken">The access token.</param>
- /// <param name="accessTokenSecret">The access token secret.</param>
- public virtual void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) {
- var cookie = new HttpCookie(TokenCookieKey) {
- Value = string.Empty,
- Expires = DateTime.UtcNow.AddDays(-5)
- };
- this.Context.Response.Cookies.Set(cookie);
- }
-
- /// <summary>
- /// Stores the request token together with its secret.
- /// </summary>
- /// <param name="requestToken">The request token.</param>
- /// <param name="requestTokenSecret">The request token secret.</param>
- public virtual void StoreRequestToken(string requestToken, string requestTokenSecret) {
- var cookie = new HttpCookie(TokenCookieKey) {
- HttpOnly = true
- };
-
- if (FormsAuthentication.RequireSSL) {
- cookie.Secure = true;
- }
-
- var encryptedToken = ProtectAndEncodeToken(requestToken, requestTokenSecret);
- cookie.Values[requestToken] = encryptedToken;
-
- this.Context.Response.Cookies.Set(cookie);
- }
-
- /// <summary>
- /// Protect and url-encode the specified token secret.
- /// </summary>
- /// <param name="token">The token to be used as a key.</param>
- /// <param name="tokenSecret">The token secret to be protected</param>
- /// <returns>The encrypted and protected string.</returns>
- protected static string ProtectAndEncodeToken(string token, string tokenSecret)
- {
- byte[] cookieBytes = Encoding.UTF8.GetBytes(tokenSecret);
- var secretBytes = MachineKeyUtil.Protect(cookieBytes, TokenCookieKey, "Token:" + token);
- return HttpServerUtility.UrlTokenEncode(secretBytes);
- }
-
- /// <summary>
- /// Url-decode and unprotect the specified encrypted token string.
- /// </summary>
- /// <param name="token">The token to be used as a key.</param>
- /// <param name="encryptedToken">The encrypted token to be decrypted</param>
- /// <returns>The original token secret</returns>
- protected static string DecodeAndUnprotectToken(string token, string encryptedToken)
- {
- byte[] cookieBytes = HttpServerUtility.UrlTokenDecode(encryptedToken);
- byte[] clearBytes = MachineKeyUtil.Unprotect(cookieBytes, TokenCookieKey, "Token:" + token);
- return Encoding.UTF8.GetString(clearBytes);
- }
- }
-} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/CookieOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/CookieOAuthTokenManager.cs
deleted file mode 100644
index 398ee85..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/CookieOAuthTokenManager.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="CookieOAuthTokenManager.cs" company="Microsoft">
-// Copyright (c) Microsoft. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.AspNet.Clients {
- using System.Web;
- using System.Web.Security;
-
- /// <summary>
- /// Stores OAuth tokens in the current request's cookie.
- /// </summary>
- /// <remarks>
- /// This class is different from the <see cref="AuthenticationOnlyCookieOAuthTokenManager"/> in that
- /// it also stores the access token after the authentication has succeeded.
- /// </remarks>
- public class CookieOAuthTokenManager : AuthenticationOnlyCookieOAuthTokenManager {
- /// <summary>
- /// Initializes a new instance of the <see cref="CookieOAuthTokenManager"/> class.
- /// </summary>
- public CookieOAuthTokenManager() {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="CookieOAuthTokenManager"/> class.
- /// </summary>
- /// <param name="context">The current request context.</param>
- public CookieOAuthTokenManager(HttpContextBase context)
- : base(context) {
- }
-
- /// <summary>
- /// Gets the token secret from the specified token.
- /// </summary>
- /// <param name="token">The token.</param>
- /// <returns>
- /// The token's secret
- /// </returns>
- public override string GetTokenSecret(string token) {
- string secret = base.GetTokenSecret(token);
- if (secret != null) {
- return secret;
- }
-
- // The base class checks for cookies in the Request object.
- // Here we check in the Response object as well because we
- // may have set it earlier in the request life cycle.
- HttpCookie cookie = this.Context.Response.Cookies[TokenCookieKey];
- if (cookie == null || string.IsNullOrEmpty(cookie.Values[token])) {
- return null;
- }
-
- secret = DecodeAndUnprotectToken(token, cookie.Values[token]);
- return secret;
- }
-
- /// <summary>
- /// Replaces the request token with access token.
- /// </summary>
- /// <param name="requestToken">The request token.</param>
- /// <param name="accessToken">The access token.</param>
- /// <param name="accessTokenSecret">The access token secret.</param>
- public override void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret) {
- var cookie = new HttpCookie(TokenCookieKey) {
- HttpOnly = true
- };
-
- if (FormsAuthentication.RequireSSL) {
- cookie.Secure = true;
- }
-
- var encryptedToken = ProtectAndEncodeToken(accessToken, accessTokenSecret);
- cookie.Values[accessToken] = encryptedToken;
-
- this.Context.Response.Cookies.Set(cookie);
- }
- }
-} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs
index cc35b76..1b6318f 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+ using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
@@ -20,13 +21,13 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// The dot net open auth web consumer.
/// </summary>
- public class DotNetOpenAuthWebConsumer : IOAuthWebWorker, IDisposable {
+ public class DotNetOpenAuthWebConsumer : IOAuthWebWorker {
#region Constants and Fields
/// <summary>
/// The _web consumer.
/// </summary>
- private readonly WebConsumer webConsumer;
+ private readonly Consumer webConsumer;
#endregion
@@ -41,11 +42,15 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <param name="tokenManager">
/// The token manager.
/// </param>
- public DotNetOpenAuthWebConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager) {
+ public DotNetOpenAuthWebConsumer(ServiceProviderDescription serviceDescription, string consumerKey, string consumerSecret) {
Requires.NotNull(serviceDescription, "serviceDescription");
- Requires.NotNull(tokenManager, "tokenManager");
- this.webConsumer = new WebConsumer(serviceDescription, tokenManager);
+ this.webConsumer = new Consumer {
+ ServiceProvider = serviceDescription,
+ ConsumerKey = consumerKey,
+ ConsumerSecret = consumerSecret,
+ TemporaryCredentialStorage = new CookieTemporaryCredentialStorage(),
+ };
}
#endregion
@@ -53,7 +58,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Gets the DotNetOpenAuth <see cref="WebConsumer"/> instance that can be used to make OAuth 1.0 authorized HTTP requests.
/// </summary>
- public WebConsumer Consumer {
+ public Consumer Consumer {
get { return this.webConsumer; }
}
@@ -63,8 +68,8 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// Creates an HTTP message handler that authorizes outgoing web requests.
/// </summary>
/// <param name="accessToken">The access token.</param>
- public HttpMessageHandler CreateMessageHandler(string accessToken) {
- Requires.NotNullOrEmpty(accessToken, "accessToken");
+ public HttpMessageHandler CreateMessageHandler(AccessToken accessToken) {
+ Requires.NotNullOrEmpty(accessToken.Token, "accessToken");
return this.Consumer.CreateMessageHandler(accessToken);
}
@@ -76,8 +81,12 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <returns>
/// The response message.
/// </returns>
- public Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(CancellationToken cancellationToken = default(CancellationToken)) {
- return this.webConsumer.ProcessUserAuthorizationAsync(cancellationToken: cancellationToken);
+ public Task<AccessTokenResponse> ProcessUserAuthorizationAsync(HttpContextBase context = null, CancellationToken cancellationToken = default(CancellationToken)) {
+ if (context == null) {
+ context = new HttpContextWrapper(HttpContext.Current);
+ }
+
+ return this.webConsumer.ProcessUserAuthorizationAsync(context.Request.Url, cancellationToken: cancellationToken);
}
/// <summary>
@@ -88,37 +97,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <returns>
/// The response message.
/// </returns>
- public async Task<HttpResponseMessage> RequestAuthenticationAsync(Uri callback, CancellationToken cancellationToken = default(CancellationToken)) {
- var redirectParameters = new Dictionary<string, string>();
- UserAuthorizationRequest request = await this.webConsumer.PrepareRequestUserAuthorizationAsync(
- callback, null, redirectParameters, cancellationToken);
- var response = await this.webConsumer.Channel.PrepareResponseAsync(request, cancellationToken);
- return response;
- }
-
- #endregion
-
- #region IDisposable members
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- /// <filterpriority>2</filterpriority>
- public void Dispose() {
- this.Dispose(true);
- GC.SuppressFinalize(this);
+ public Task<Uri> RequestAuthenticationAsync(Uri callback, CancellationToken cancellationToken = default(CancellationToken)) {
+ return this.webConsumer.RequestUserAuthorizationAsync(callback, cancellationToken: cancellationToken);
}
#endregion
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing) {
- if (disposing) {
- this.webConsumer.Dispose();
- }
- }
}
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthTokenManager.cs
deleted file mode 100644
index 92f1c22..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthTokenManager.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="IOAuthTokenManager.cs" company="Microsoft">
-// Copyright (c) Microsoft. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.AspNet.Clients {
- /// <summary>
- /// A token manager for use by a web site in its role as a consumer of
- /// an individual ServiceProvider.
- /// </summary>
- /// <remarks>
- /// This interface is used by clients of the DotNetOpenAuth.AspNet classes.
- /// </remarks>
- public interface IOAuthTokenManager {
- /// <summary>
- /// Gets the token secret from the specified token.
- /// </summary>
- /// <param name="token">The token.</param>
- /// <returns>The token's secret</returns>
- string GetTokenSecret(string token);
-
- /// <summary>
- /// Stores the request token together with its secret.
- /// </summary>
- /// <param name="requestToken">The request token.</param>
- /// <param name="requestTokenSecret">The request token secret.</param>
- void StoreRequestToken(string requestToken, string requestTokenSecret);
-
- /// <summary>
- /// Replaces the request token with access token.
- /// </summary>
- /// <param name="requestToken">The request token.</param>
- /// <param name="accessToken">The access token.</param>
- /// <param name="accessTokenSecret">The access token secret.</param>
- void ReplaceRequestTokenWithAccessToken(string requestToken, string accessToken, string accessTokenSecret);
- }
-} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs
index 7763add..e3ee3e8 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs
@@ -10,7 +10,9 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+ using System.Web;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.Messages;
/// <summary>
@@ -21,23 +23,23 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// Creates an HTTP message handler that authorizes outgoing web requests.
/// </summary>
/// <param name="accessToken">The access token.</param>
- HttpMessageHandler CreateMessageHandler(string accessToken);
+ HttpMessageHandler CreateMessageHandler(AccessToken accessToken);
/// <summary>
/// The process user authorization.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// The response message.
+ /// The access token, if obtained; otherwise <c>null</c>.
/// </returns>
- Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(CancellationToken cancellationToken = default(CancellationToken));
+ Task<AccessTokenResponse> ProcessUserAuthorizationAsync(HttpContextBase context = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// The request authentication.
/// </summary>
/// <param name="callback">The callback.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>The response message</returns>
- Task<HttpResponseMessage> RequestAuthenticationAsync(Uri callback, CancellationToken cancellationToken = default(CancellationToken));
+ /// <returns>The URL to redirect the user agent to.</returns>
+ Task<Uri> RequestAuthenticationAsync(Uri callback, CancellationToken cancellationToken = default(CancellationToken));
}
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs
deleted file mode 100644
index a97e5d8..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="InMemoryOAuthTokenManager.cs" company="Microsoft">
-// Copyright (c) Microsoft. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.AspNet.Clients {
- using System;
- using System.Collections.Generic;
- using System.Threading;
- using System.Web;
- using DotNetOpenAuth.OAuth;
- using DotNetOpenAuth.OAuth.ChannelElements;
- using DotNetOpenAuth.OAuth.Messages;
- using Validation;
-
- /// <summary>
- /// An implementation of IOAuthTokenManager which stores keys in memory.
- /// </summary>
- public sealed class InMemoryOAuthTokenManager : IConsumerTokenManager {
- #region Constants and Fields
-
- /// <summary>
- /// The _tokens and secrets.
- /// </summary>
- private readonly Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();
-
- #endregion
-
- #region Constructors and Destructors
-
- /// <summary>
- /// Initializes a new instance of the <see cref="InMemoryOAuthTokenManager"/> class.
- /// </summary>
- /// <param name="consumerKey">
- /// The consumer key.
- /// </param>
- /// <param name="consumerSecret">
- /// The consumer secret.
- /// </param>
- public InMemoryOAuthTokenManager(string consumerKey, string consumerSecret) {
- Requires.NotNull(consumerKey, "consumerKey");
- Requires.NotNull(consumerSecret, "consumerSecret");
-
- this.ConsumerKey = consumerKey;
- this.ConsumerSecret = consumerSecret;
- }
-
- #endregion
-
- #region Public Properties
-
- /// <summary>
- /// Gets the consumer key.
- /// </summary>
- public string ConsumerKey { get; private set; }
-
- /// <summary>
- /// Gets the consumer secret.
- /// </summary>
- public string ConsumerSecret { get; private set; }
-
- #endregion
-
- #region Public Methods and Operators
-
- /// <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="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
- /// <see cref="WebConsumer.ProcessUserAuthorizationAsync(HttpRequestBase, CancellationToken)"/>
- /// or
- /// <see cref="DesktopConsumer.ProcessUserAuthorizationAsync(string, string, CancellationToken)"/>
- /// return the access
- /// token to associate the access token with a user account at that point.
- /// </para>
- /// </remarks>
- public void ExpireRequestTokenAndStoreNewAccessToken(
- string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
- this.tokensAndSecrets.Remove(requestToken);
- this.tokensAndSecrets[accessToken] = accessTokenSecret;
- }
-
- /// <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>
- public string GetTokenSecret(string token) {
- return this.tokensAndSecrets[token];
- }
-
- /// <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>
- public TokenType GetTokenType(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="ExpireRequestTokenAndStoreNewAccessToken"/> method.
- /// </remarks>
- public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) {
- this.tokensAndSecrets[response.Token] = response.TokenSecret;
- }
-
- #endregion
- }
-}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
index 7aa1dd4..637bbd0 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
@@ -28,21 +28,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Describes the OAuth service provider endpoints for LinkedIn.
/// </summary>
- public static readonly ServiceProviderDescription LinkedInServiceDescription = new ServiceProviderDescription {
- RequestTokenEndpoint =
- new MessageReceivingEndpoint(
- "https://api.linkedin.com/uas/oauth/requestToken",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- UserAuthorizationEndpoint =
- new MessageReceivingEndpoint(
- "https://www.linkedin.com/uas/oauth/authenticate",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- AccessTokenEndpoint =
- new MessageReceivingEndpoint(
- "https://api.linkedin.com/uas/oauth/accessToken",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
- };
+ public static readonly ServiceProviderDescription LinkedInServiceDescription = new ServiceProviderDescription(
+ "https://api.linkedin.com/uas/oauth/requestToken",
+ "https://www.linkedin.com/uas/oauth/authenticate",
+ "https://api.linkedin.com/uas/oauth/accessToken");
#endregion
@@ -51,28 +40,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Initializes a new instance of the <see cref="LinkedInClient"/> class.
/// </summary>
- /// <remarks>
- /// Tokens exchanged during the OAuth handshake are stored in cookies.
- /// </remarks>
- /// <param name="consumerKey">
- /// The LinkedIn app's consumer key.
- /// </param>
- /// <param name="consumerSecret">
- /// The LinkedIn app's consumer secret.
- /// </param>
- [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
- Justification = "We can't dispose the object because we still need it through the app lifetime.")]
- public LinkedInClient(string consumerKey, string consumerSecret)
- : this(consumerKey, consumerSecret, new CookieOAuthTokenManager()) { }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LinkedInClient"/> class.
- /// </summary>
/// <param name="consumerKey">The consumer key.</param>
/// <param name="consumerSecret">The consumer secret.</param>
- /// <param name="tokenManager">The token manager.</param>
- public LinkedInClient(string consumerKey, string consumerSecret, IOAuthTokenManager tokenManager)
- : base("linkedIn", LinkedInServiceDescription, new SimpleConsumerTokenManager(consumerKey, consumerSecret, tokenManager)) {
+ public LinkedInClient(string consumerKey, string consumerSecret)
+ : base("linkedIn", LinkedInServiceDescription, consumerKey, consumerSecret) {
}
#endregion
@@ -89,12 +60,11 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We don't care if the request fails.")]
- protected override async Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AuthorizedTokenResponse response, CancellationToken cancellationToken = default(CancellationToken)) {
+ protected override async Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AccessTokenResponse response, CancellationToken cancellationToken = default(CancellationToken)) {
// See here for Field Selectors API http://developer.linkedin.com/docs/DOC-1014
const string ProfileRequestUrl = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,industry,summary)";
- string accessToken = response.AccessToken;
-
+ var accessToken = response.AccessToken;
var authorizingHandler = this.WebWorker.CreateMessageHandler(accessToken);
try {
using (var httpClient = new HttpClient(authorizingHandler)) {
@@ -108,7 +78,8 @@ namespace DotNetOpenAuth.AspNet.Clients {
string userName = firstName + " " + lastName;
var extraData = new Dictionary<string, string>();
- extraData.Add("accesstoken", accessToken);
+ extraData.Add("accesstoken", accessToken.Token);
+ extraData.Add("accesstokensecret", accessToken.Secret);
extraData.Add("name", userName);
extraData.AddDataIfNotEmpty(document, "headline");
extraData.AddDataIfNotEmpty(document, "summary");
@@ -123,8 +94,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
}
}
}
- }
- catch (Exception exception) {
+ } catch (Exception exception) {
return new AuthenticationResult(exception);
}
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
index ffe5c07..03006f2 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
@@ -33,34 +33,14 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// Name of the provider.
/// </param>
/// <param name="serviceDescription">
- /// The service description.
- /// </param>
- /// <param name="consumerKey">
- /// The consumer key.
- /// </param>
- /// <param name="consumerSecret">
- /// The consumer secret.
- /// </param>
- protected OAuthClient(
- string providerName, ServiceProviderDescription serviceDescription, string consumerKey, string consumerSecret)
- : this(providerName, serviceDescription, new InMemoryOAuthTokenManager(consumerKey, consumerSecret)) { }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthClient"/> class.
- /// </summary>
- /// <param name="providerName">
- /// Name of the provider.
- /// </param>
- /// <param name="serviceDescription">
/// The service Description.
/// </param>
/// <param name="tokenManager">
/// The token Manager.
/// </param>
- [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "I don't know how to ensure this rule is followed given this API")]
protected OAuthClient(
- string providerName, ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
- : this(providerName, new DotNetOpenAuthWebConsumer(serviceDescription, tokenManager)) {
+ string providerName, ServiceProviderDescription serviceDescription, string consumerKey, string consumerSecret)
+ : this(providerName, new DotNetOpenAuthWebConsumer(serviceDescription, consumerKey, consumerSecret)) {
}
/// <summary>
@@ -128,7 +108,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// An instance of <see cref="AuthenticationResult" /> containing authentication result.
/// </returns>
public virtual async Task<AuthenticationResult> VerifyAuthenticationAsync(HttpContextBase context, CancellationToken cancellationToken = default(CancellationToken)) {
- AuthorizedTokenResponse response = await this.WebWorker.ProcessUserAuthorizationAsync(cancellationToken);
+ AccessTokenResponse response = await this.WebWorker.ProcessUserAuthorizationAsync(context, cancellationToken);
if (response == null) {
return AuthenticationResult.Failed;
}
@@ -139,7 +119,8 @@ namespace DotNetOpenAuth.AspNet.Clients {
var wrapExtraData = result.ExtraData.IsReadOnly
? new Dictionary<string, string>(result.ExtraData)
: result.ExtraData;
- wrapExtraData["accesstoken"] = response.AccessToken;
+ wrapExtraData["accesstoken"] = response.AccessToken.Token;
+ wrapExtraData["accesstokensecret"] = response.AccessToken.Secret;
AuthenticationResult wrapResult = new AuthenticationResult(
result.IsSuccessful,
@@ -174,14 +155,14 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
- /// <param name="response">
- /// The response token returned from service provider
+ /// <param name="accessToken">
+ /// The access token returned from service provider
/// </param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// Authentication result
/// </returns>
- protected abstract Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AuthorizedTokenResponse response, CancellationToken cancellationToken);
+ protected abstract Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AccessTokenResponse accessToken, CancellationToken cancellationToken);
#endregion
}
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/SimpleConsumerTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/SimpleConsumerTokenManager.cs
deleted file mode 100644
index 899204c..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/SimpleConsumerTokenManager.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="SimpleConsumerTokenManager.cs" company="Microsoft">
-// Copyright (c) Microsoft. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.AspNet.Clients {
- using System;
- using DotNetOpenAuth.OAuth.ChannelElements;
- using Validation;
-
- /// <summary>
- /// Simple wrapper around IConsumerTokenManager
- /// </summary>
- public class SimpleConsumerTokenManager : IConsumerTokenManager {
- /// <summary>
- /// Store the token manager.
- /// </summary>
- private readonly IOAuthTokenManager tokenManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SimpleConsumerTokenManager"/> class.
- /// </summary>
- /// <param name="consumerKey">The consumer key.</param>
- /// <param name="consumerSecret">The consumer secret.</param>
- /// <param name="tokenManager">The OAuth token manager.</param>
- public SimpleConsumerTokenManager(string consumerKey, string consumerSecret, IOAuthTokenManager tokenManager) {
- Requires.NotNullOrEmpty(consumerKey, "consumerKey");
- Requires.NotNullOrEmpty(consumerSecret, "consumerSecret");
- Requires.NotNull(tokenManager, "oAuthTokenManager");
-
- this.ConsumerKey = consumerKey;
- this.ConsumerSecret = consumerSecret;
- this.tokenManager = tokenManager;
- }
-
- /// <summary>
- /// Gets the consumer key.
- /// </summary>
- /// <value>
- /// The consumer key.
- /// </value>
- public string ConsumerKey {
- get;
- private set;
- }
-
- /// <summary>
- /// Gets the consumer secret.
- /// </summary>
- /// <value>
- /// The consumer secret.
- /// </value>
- public string ConsumerSecret {
- get;
- private set;
- }
-
- /// <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>
- public string GetTokenSecret(string token) {
- return this.tokenManager.GetTokenSecret(token);
- }
-
- /// <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>
- public void StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response) {
- this.tokenManager.StoreRequestToken(response.Token, response.TokenSecret);
- }
-
- /// <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>
- public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
- this.tokenManager.ReplaceRequestTokenWithAccessToken(requestToken, accessToken, accessTokenSecret);
- }
-
- /// <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>
- public TokenType GetTokenType(string token) {
- throw new NotSupportedException();
- }
- }
-} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
index 0f5e0db..88bb530 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
@@ -28,51 +28,23 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature.
/// </summary>
- public static readonly ServiceProviderDescription TwitterServiceDescription = new ServiceProviderDescription {
- RequestTokenEndpoint =
- new MessageReceivingEndpoint(
- "https://api.twitter.com/oauth/request_token",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- UserAuthorizationEndpoint =
- new MessageReceivingEndpoint(
- "https://api.twitter.com/oauth/authenticate",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- AccessTokenEndpoint =
- new MessageReceivingEndpoint(
- "https://api.twitter.com/oauth/access_token",
- HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
- TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
- };
+ public static readonly ServiceProviderDescription TwitterServiceDescription =
+ new ServiceProviderDescription(
+ "https://api.twitter.com/oauth/request_token",
+ "https://api.twitter.com/oauth/authenticate",
+ "https://api.twitter.com/oauth/access_token");
#endregion
#region Constructors and Destructors
/// <summary>
- /// Initializes a new instance of the <see cref="TwitterClient"/> class with the specified consumer key and consumer secret.
- /// </summary>
- /// <remarks>
- /// Tokens exchanged during the OAuth handshake are stored in cookies.
- /// </remarks>
- /// <param name="consumerKey">
- /// The consumer key.
- /// </param>
- /// <param name="consumerSecret">
- /// The consumer secret.
- /// </param>
- [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
- Justification = "We can't dispose the object because we still need it through the app lifetime.")]
- public TwitterClient(string consumerKey, string consumerSecret)
- : this(consumerKey, consumerSecret, new AuthenticationOnlyCookieOAuthTokenManager()) { }
-
- /// <summary>
/// Initializes a new instance of the <see cref="TwitterClient"/> class.
/// </summary>
/// <param name="consumerKey">The consumer key.</param>
/// <param name="consumerSecret">The consumer secret.</param>
- /// <param name="tokenManager">The token manager.</param>
- public TwitterClient(string consumerKey, string consumerSecret, IOAuthTokenManager tokenManager)
- : base("twitter", TwitterServiceDescription, new SimpleConsumerTokenManager(consumerKey, consumerSecret, tokenManager)) {
+ public TwitterClient(string consumerKey, string consumerSecret)
+ : base("twitter", TwitterServiceDescription, consumerKey, consumerSecret) {
}
#endregion
@@ -89,17 +61,17 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We don't care if the request for additional data fails.")]
- protected override async Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AuthorizedTokenResponse response, CancellationToken cancellationToken) {
- string accessToken = response.AccessToken;
+ protected override async Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AccessTokenResponse response, CancellationToken cancellationToken) {
string userId = response.ExtraData["user_id"];
string userName = response.ExtraData["screen_name"];
var profileRequestUrl = new Uri("https://api.twitter.com/1/users/show.xml?user_id="
+ MessagingUtilities.EscapeUriDataStringRfc3986(userId));
- var authorizingHandler = this.WebWorker.CreateMessageHandler(accessToken);
+ var authorizingHandler = this.WebWorker.CreateMessageHandler(response.AccessToken);
var extraData = new Dictionary<string, string>();
- extraData.Add("accesstoken", accessToken);
+ extraData.Add("accesstoken", response.AccessToken.Token);
+ extraData.Add("accesstokensecret", response.AccessToken.Secret);
try {
using (var httpClient = new HttpClient(authorizingHandler)) {
using (HttpResponseMessage profileResponse = await httpClient.GetAsync(profileRequestUrl, cancellationToken)) {
diff --git a/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj b/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj
index 7a9d49b..b3b52d9 100644
--- a/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj
+++ b/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj
@@ -50,12 +50,6 @@
<Compile Include="AuthenticationResult.cs" />
<Compile Include="Clients\DictionaryExtensions.cs" />
<Compile Include="Clients\OAuth2\WindowsLiveClient.cs" />
- <Compile Include="Clients\OAuth\AuthenticationOnlyCookieOAuthTokenManager.cs">
- <SubType>Code</SubType>
- </Compile>
- <Compile Include="Clients\OAuth\CookieOAuthTokenManager.cs" />
- <Compile Include="Clients\OAuth\IOAuthTokenManager.cs" />
- <Compile Include="Clients\OAuth\SimpleConsumerTokenManager.cs" />
<Compile Include="IAuthenticationClient.cs" />
<Compile Include="Clients\OAuth2\FacebookClient.cs" />
<Compile Include="Clients\OAuth2\FacebookGraphData.cs" />
@@ -65,7 +59,6 @@
<Compile Include="Clients\OAuth2\MicrosoftClient.cs" />
<Compile Include="Clients\OAuth2\MicrosoftClientUserData.cs" />
<Compile Include="Clients\OAuth\DotNetOpenAuthWebConsumer.cs" />
- <Compile Include="Clients\OAuth\InMemoryOAuthTokenManager.cs" />
<Compile Include="Clients\OAuth\IOAuthWebWorker.cs" />
<Compile Include="Clients\OAuth\LinkedInClient.cs" />
<Compile Include="Clients\OAuth\OAuthClient.cs" />
@@ -73,7 +66,6 @@
<Compile Include="Clients\OpenID\GoogleOpenIdClient.cs" />
<Compile Include="Clients\OpenID\OpenIdClient.cs" />
<Compile Include="Clients\OpenID\YahooOpenIdClient.cs" />
- <Compile Include="MachineKeyUtil.cs" />
<Compile Include="UriHelper.cs" />
<Compile Include="IOpenAuthDataProvider.cs" />
<Compile Include="OpenAuthAuthenticationTicketHelper.cs" />
diff --git a/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs b/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs
index fd79a73..da1d1ca 100644
--- a/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs
+++ b/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.544
+// Runtime Version:4.0.30319.18033
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -79,15 +79,6 @@ namespace DotNetOpenAuth.AspNet {
}
/// <summary>
- /// Looks up a localized string similar to The provided data could not be decrypted. If the current application is deployed in a web farm configuration, ensure that the &apos;decryptionKey&apos; and &apos;validationKey&apos; attributes are explicitly specified in the &lt;machineKey&gt; configuration section..
- /// </summary>
- internal static string Generic_CryptoFailure {
- get {
- return ResourceManager.GetString("Generic_CryptoFailure", resourceCulture);
- }
- }
-
- /// <summary>
/// Looks up a localized string similar to An OAuth data provider has already been registered for this application..
/// </summary>
internal static string OAuthDataProviderRegistered {
diff --git a/src/DotNetOpenAuth.AspNet/WebResources.resx b/src/DotNetOpenAuth.AspNet/WebResources.resx
index c1552e9..a491579 100644
--- a/src/DotNetOpenAuth.AspNet/WebResources.resx
+++ b/src/DotNetOpenAuth.AspNet/WebResources.resx
@@ -123,9 +123,6 @@
<data name="FailedToEncryptTicket" xml:space="preserve">
<value>Unable to encrypt the authentication ticket.</value>
</data>
- <data name="Generic_CryptoFailure" xml:space="preserve">
- <value>The provided data could not be decrypted. If the current application is deployed in a web farm configuration, ensure that the 'decryptionKey' and 'validationKey' attributes are explicitly specified in the &lt;machineKey&gt; configuration section.</value>
- </data>
<data name="OAuthDataProviderRegistered" xml:space="preserve">
<value>An OAuth data provider has already been registered for this application.</value>
</data>
diff --git a/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj b/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj
index 7877cf0..253528b 100644
--- a/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj
+++ b/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj
@@ -22,10 +22,12 @@
<Compile Include="Assumes.cs" />
<Compile Include="IHostFactories.cs" />
<Compile Include="IRequireHostFactories.cs" />
+ <Compile Include="MachineKeyUtil.cs" />
<Compile Include="Messaging\Base64WebEncoder.cs" />
<Compile Include="Messaging\Bindings\AsymmetricCryptoKeyStoreWrapper.cs" />
<Compile Include="Messaging\Bindings\CryptoKey.cs" />
<Compile Include="Messaging\Bindings\CryptoKeyCollisionException.cs" />
+ <Compile Include="Messaging\Bindings\HardCodedKeyCryptoKeyStore.cs" />
<Compile Include="Messaging\Bindings\ICryptoKeyStore.cs" />
<Compile Include="Messaging\Bindings\MemoryCryptoKeyStore.cs" />
<Compile Include="Messaging\BinaryDataBagFormatter.cs" />
diff --git a/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs b/src/DotNetOpenAuth.Core/MachineKeyUtil.cs
index eb2020b..eceb38c 100644
--- a/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs
+++ b/src/DotNetOpenAuth.Core/MachineKeyUtil.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.AspNet {
+namespace DotNetOpenAuth {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
@@ -183,7 +183,7 @@ namespace DotNetOpenAuth.AspNet {
}
// if we reached this point, some cryptographic operation failed
- throw new CryptographicException(WebResources.Generic_CryptoFailure);
+ throw new CryptographicException(Strings.Generic_CryptoFailure);
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Core/Messaging/Bindings/HardCodedKeyCryptoKeyStore.cs b/src/DotNetOpenAuth.Core/Messaging/Bindings/HardCodedKeyCryptoKeyStore.cs
new file mode 100644
index 0000000..c828616
--- /dev/null
+++ b/src/DotNetOpenAuth.Core/Messaging/Bindings/HardCodedKeyCryptoKeyStore.cs
@@ -0,0 +1,98 @@
+//-----------------------------------------------------------------------
+// <copyright file="HardCodedKeyCryptoKeyStore.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging.Bindings {
+ using System;
+ using System.Collections.Generic;
+ using Validation;
+
+ /// <summary>
+ /// A trivial implementation of <see cref="ICryptoKeyStore"/> that has only one fixed key.
+ /// This is meant for simple, low-security applications. Greater security requires an
+ /// implementation of <see cref="ICryptoKeyStore"/> that actually stores and retrieves
+ /// keys from a persistent store.
+ /// </summary>
+ public class HardCodedKeyCryptoKeyStore : ICryptoKeyStore {
+ /// <summary>
+ /// The handle to report for the hard-coded key.
+ /// </summary>
+ private const string HardCodedKeyHandle = "fxd";
+
+ /// <summary>
+ /// The one crypto key singleton instance.
+ /// </summary>
+ private readonly CryptoKey OneCryptoKey;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HardCodedKeyCryptoKeyStore"/> class.
+ /// </summary>
+ /// <param name="secretAsBase64">The 256-bit secret as a base64 encoded string.</param>
+ public HardCodedKeyCryptoKeyStore(string secretAsBase64)
+ : this(Convert.FromBase64String(Requires.NotNull(secretAsBase64, "secretAsBase64"))) {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HardCodedKeyCryptoKeyStore"/> class.
+ /// </summary>
+ /// <param name="secret">The 256-bit secret.</param>
+ public HardCodedKeyCryptoKeyStore(byte[] secret) {
+ Requires.NotNull(secret, "secret");
+ this.OneCryptoKey = new CryptoKey(secret, DateTime.MaxValue.AddDays(-2).ToUniversalTime());
+ }
+
+ #region ICryptoKeyStore Members
+
+ /// <summary>
+ /// Gets the key in a given bucket and handle.
+ /// </summary>
+ /// <param name="bucket">The bucket name. Case sensitive.</param>
+ /// <param name="handle">The key handle. Case sensitive.</param>
+ /// <returns>
+ /// The cryptographic key, or <c>null</c> if no matching key was found.
+ /// </returns>
+ public CryptoKey GetKey(string bucket, string handle) {
+ if (handle == HardCodedKeyHandle) {
+ return OneCryptoKey;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Gets a sequence of existing keys within a given bucket.
+ /// </summary>
+ /// <param name="bucket">The bucket name. Case sensitive.</param>
+ /// <returns>
+ /// A sequence of handles and keys, ordered by descending <see cref="CryptoKey.ExpiresUtc" />.
+ /// </returns>
+ public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
+ return new[] { new KeyValuePair<string, CryptoKey>(HardCodedKeyHandle, OneCryptoKey) };
+ }
+
+ /// <summary>
+ /// Stores a cryptographic key.
+ /// </summary>
+ /// <param name="bucket">The name of the bucket to store the key in. Case sensitive.</param>
+ /// <param name="handle">The handle to the key, unique within the bucket. Case sensitive.</param>
+ /// <param name="key">The key to store.</param>
+ /// <exception cref="System.NotSupportedException"></exception>
+ public void StoreKey(string bucket, string handle, CryptoKey key) {
+ throw new NotSupportedException();
+ }
+
+ /// <summary>
+ /// Removes the key.
+ /// </summary>
+ /// <param name="bucket">The bucket name. Case sensitive.</param>
+ /// <param name="handle">The key handle. Case sensitive.</param>
+ /// <exception cref="System.NotSupportedException"></exception>
+ public void RemoveKey(string bucket, string handle) {
+ throw new NotSupportedException();
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
index 501b5b2..38abe4a 100644
--- a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs
@@ -393,6 +393,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Gets the public facing URL for the given incoming HTTP request.
+ /// </summary>
+ /// <returns>The URI that the outside world used to create this request.</returns>
+ public static Uri GetPublicFacingUrl() {
+ ErrorUtilities.VerifyHttpContext();
+ return GetPublicFacingUrl(new HttpRequestWrapper(HttpContext.Current.Request));
+ }
+
+ /// <summary>
/// Wraps a response message as an MVC <see cref="ActionResult"/> so it can be conveniently returned from an MVC controller's action method.
/// </summary>
/// <param name="response">The response message.</param>
diff --git a/src/DotNetOpenAuth.Core/Strings.Designer.cs b/src/DotNetOpenAuth.Core/Strings.Designer.cs
index 9eefd62..b96f68a 100644
--- a/src/DotNetOpenAuth.Core/Strings.Designer.cs
+++ b/src/DotNetOpenAuth.Core/Strings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18010
+// Runtime Version:4.0.30319.18033
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -97,6 +97,15 @@ namespace DotNetOpenAuth {
}
/// <summary>
+ /// Looks up a localized string similar to The provided data could not be decrypted. If the current application is deployed in a web farm configuration, ensure that the &apos;decryptionKey&apos; and &apos;validationKey&apos; attributes are explicitly specified in the &lt;machineKey&gt; configuration section..
+ /// </summary>
+ internal static string Generic_CryptoFailure {
+ get {
+ return ResourceManager.GetString("Generic_CryptoFailure", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The HostFactories property must be set first..
/// </summary>
internal static string HostFactoriesRequired {
diff --git a/src/DotNetOpenAuth.Core/Strings.resx b/src/DotNetOpenAuth.Core/Strings.resx
index 133fe6f..1c2aee2 100644
--- a/src/DotNetOpenAuth.Core/Strings.resx
+++ b/src/DotNetOpenAuth.Core/Strings.resx
@@ -144,4 +144,7 @@
<data name="HostFactoriesRequired" xml:space="preserve">
<value>The HostFactories property must be set first.</value>
</data>
+ <data name="Generic_CryptoFailure" xml:space="preserve">
+ <value>The provided data could not be decrypted. If the current application is deployed in a web farm configuration, ensure that the 'decryptionKey' and 'validationKey' attributes are explicitly specified in the &lt;machineKey&gt; configuration section.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.OAuth.Common/DotNetOpenAuth.OAuth.Common.csproj b/src/DotNetOpenAuth.OAuth.Common/DotNetOpenAuth.OAuth.Common.csproj
index 89638d6..95549fe 100644
--- a/src/DotNetOpenAuth.OAuth.Common/DotNetOpenAuth.OAuth.Common.csproj
+++ b/src/DotNetOpenAuth.OAuth.Common/DotNetOpenAuth.OAuth.Common.csproj
@@ -21,7 +21,6 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
- <Compile Include="OAuth\ChannelElements\OAuthIdentity.cs" />
<Compile Include="OAuth\ChannelElements\OAuthPrincipal.cs" />
<Compile Include="OAuth\DefaultOAuthHostFactories.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthIdentity.cs b/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthIdentity.cs
deleted file mode 100644
index 28e0333..0000000
--- a/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthIdentity.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="OAuthIdentity.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth.ChannelElements {
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Runtime.InteropServices;
- using System.Security.Principal;
- using DotNetOpenAuth.Messaging;
- using Validation;
-
- /// <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)]
- public class OAuthIdentity : IIdentity {
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthIdentity"/> class.
- /// </summary>
- /// <param name="username">The username.</param>
- internal OAuthIdentity(string username) {
- Requires.NotNullOrEmpty(username, "username");
- this.Name = username;
- }
-
- #region IIdentity Members
-
- /// <summary>
- /// Gets the type of authentication used.
- /// </summary>
- /// <value>The constant "OAuth"</value>
- /// <returns>
- /// The type of authentication used to identify the user.
- /// </returns>
- public string AuthenticationType {
- get { return "OAuth"; }
- }
-
- /// <summary>
- /// Gets a value indicating whether the user has been authenticated.
- /// </summary>
- /// <value>The value <c>true</c></value>
- /// <returns>true if the user was authenticated; otherwise, false.
- /// </returns>
- public bool IsAuthenticated {
- get { return true; }
- }
-
- /// <summary>
- /// Gets the name of the user who authorized the OAuth token the consumer is using for authorization.
- /// </summary>
- /// <returns>
- /// The name of the user on whose behalf the code is running.
- /// </returns>
- public string Name { get; private set; }
-
- #endregion
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthPrincipal.cs b/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthPrincipal.cs
index 65d7042..988d727 100644
--- a/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthPrincipal.cs
+++ b/src/DotNetOpenAuth.OAuth.Common/OAuth/ChannelElements/OAuthPrincipal.cs
@@ -1,6 +1,6 @@
//-----------------------------------------------------------------------
-// <copyright file="OAuthPrincipal.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
+// <copyright file="OAuthPrincipal.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -11,87 +11,35 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
+ using System.Security.Claims;
using System.Security.Principal;
+ using Validation;
+
/// <summary>
- /// Represents an OAuth consumer that is impersonating a known user on the system.
+ /// Utilities for dealing with OAuth claims and principals.
/// </summary>
- [SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "Not cocreatable.")]
- [Serializable]
- [ComVisible(true)]
- public class OAuthPrincipal : IPrincipal {
- /// <summary>
- /// The roles this user belongs to.
- /// </summary>
- private ICollection<string> roles;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthPrincipal"/> class.
- /// </summary>
- /// <param name="userName">The username.</param>
- /// <param name="roles">The roles this user belongs to.</param>
- public OAuthPrincipal(string userName, string[] roles)
- : this(new OAuthIdentity(userName), roles) {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthPrincipal"/> class.
- /// </summary>
- /// <param name="identity">The identity.</param>
- /// <param name="roles">The roles this user belongs to.</param>
- internal OAuthPrincipal(OAuthIdentity identity, string[] roles) {
- this.Identity = identity;
- this.roles = roles;
- }
-
- /// <summary>
- /// Gets or sets the access token used to create this principal.
- /// </summary>
- /// <value>A non-empty string.</value>
- public string AccessToken { get; protected set; }
-
+ internal static class OAuthPrincipal {
/// <summary>
- /// Gets the roles that this principal has as a ReadOnlyCollection.
+ /// Creates a new instance of ClaimsPrincipal.
/// </summary>
- public ReadOnlyCollection<string> Roles
- {
- get { return new ReadOnlyCollection<string>(this.roles.ToList()); }
- }
-
- #region IPrincipal Members
-
- /// <summary>
- /// Gets the identity of the current principal.
- /// </summary>
- /// <value></value>
+ /// <param name="userName">Name of the user.</param>
+ /// <param name="roles">The roles.</param>
/// <returns>
- /// The <see cref="T:System.Security.Principal.IIdentity"/> object associated with the current principal.
+ /// A new instance of GenericPrincipal with a GenericIdentity, having the same username and roles as this OAuthPrincipal and OAuthIdentity
/// </returns>
- public IIdentity Identity { get; private set; }
-
- /// <summary>
- /// Determines whether the current principal belongs to the specified role.
- /// </summary>
- /// <param name="role">The name of the role for which to check membership.</param>
- /// <returns>
- /// true if the current principal is a member of the specified role; otherwise, false.
- /// </returns>
- /// <remarks>
- /// The role membership check uses <see cref="StringComparer.OrdinalIgnoreCase"/>.
- /// </remarks>
- public bool IsInRole(string role) {
- return this.roles.Contains(role, StringComparer.OrdinalIgnoreCase);
- }
-
- #endregion
-
- /// <summary>
- /// Creates a new instance of GenericPrincipal based on this OAuthPrincipal.
- /// </summary>
- /// <returns>A new instance of GenericPrincipal with a GenericIdentity, having the same username and roles as this OAuthPrincipal and OAuthIdentity</returns>
- public GenericPrincipal CreateGenericPrincipal()
- {
- return new GenericPrincipal(new GenericIdentity(this.Identity.Name), this.roles.ToArray());
+ internal static ClaimsPrincipal CreatePrincipal(string userName, IEnumerable<string> roles = null) {
+ Requires.NotNullOrEmpty(userName, "userName");
+
+ var claims = new List<Claim>();
+ claims.Add(new Claim(ClaimsIdentity.DefaultNameClaimType, userName));
+ if (roles != null) {
+ claims.AddRange(roles.Select(scope => new Claim(ClaimsIdentity.DefaultRoleClaimType, scope)));
+ }
+
+ var claimsIdentity = new ClaimsIdentity(claims, "OAuth 2 Bearer");
+ var principal = new ClaimsPrincipal(claimsIdentity);
+ return principal;
}
}
}
diff --git a/src/DotNetOpenAuth.OAuth.Common/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OAuth.Common/Properties/AssemblyInfo.cs
index a3afcd7..ee7b802 100644
--- a/src/DotNetOpenAuth.OAuth.Common/Properties/AssemblyInfo.cs
+++ b/src/DotNetOpenAuth.OAuth.Common/Properties/AssemblyInfo.cs
@@ -35,9 +35,13 @@ using System.Web.UI;
// keep this assembly from being useful to shared host (medium trust) web sites.
[assembly: AllowPartiallyTrustedCallers]
+[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")]
+[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth.ServiceProvider, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")]
[assembly: InternalsVisibleTo("DotNetOpenAuth.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
#else
+[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer")]
+[assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth.ServiceProvider")]
[assembly: InternalsVisibleTo("DotNetOpenAuth.Test")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/DotNetOpenAuth.OAuth.Consumer.csproj b/src/DotNetOpenAuth.OAuth.Consumer/DotNetOpenAuth.OAuth.Consumer.csproj
index 922b860..173bb3e 100644
--- a/src/DotNetOpenAuth.OAuth.Consumer/DotNetOpenAuth.OAuth.Consumer.csproj
+++ b/src/DotNetOpenAuth.OAuth.Consumer/DotNetOpenAuth.OAuth.Consumer.csproj
@@ -19,17 +19,17 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
- <Compile Include="OAuth\ChannelElements\IConsumerTokenManager.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthConsumerChannel.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthConsumerMessageFactory.cs" />
- <Compile Include="OAuth\ChannelElements\RsaSha1ConsumerSigningBindingElement.cs" />
- <Compile Include="OAuth\ConsumerBase.cs" />
- <Compile Include="OAuth\DesktopConsumer.cs" />
+ <Compile Include="OAuth\AccessToken.cs" />
+ <Compile Include="OAuth\AccessTokenResponse.cs" />
+ <Compile Include="OAuth\ITemporaryCredentialStorage.cs" />
+ <Compile Include="OAuth\Consumer.cs" />
+ <Compile Include="OAuth\CookieTemporaryCredentialStorage.cs" />
+ <Compile Include="OAuth\MemoryTemporaryCredentialStorage.cs" />
<Compile Include="OAuth\OAuth1HmacSha1HttpMessageHandler.cs" />
<Compile Include="OAuth\OAuth1HttpMessageHandlerBase.cs" />
<Compile Include="OAuth\OAuth1PlainTextMessageHandler.cs" />
<Compile Include="OAuth\OAuth1RsaSha1HttpMessageHandler.cs" />
- <Compile Include="OAuth\WebConsumer.cs" />
+ <Compile Include="OAuth\ServiceProviderDescription.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>
</SubType>
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessToken.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessToken.cs
new file mode 100644
index 0000000..20e3ec4
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessToken.cs
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="AccessToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ /// <summary>
+ /// An OAuth 1.0 access token and secret.
+ /// </summary>
+ public struct AccessToken {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AccessToken"/> struct.
+ /// </summary>
+ /// <param name="token">The token.</param>
+ /// <param name="secret">The secret.</param>
+ public AccessToken(string token, string secret)
+ : this() {
+ this.Token = token;
+ this.Secret = secret;
+ }
+
+ /// <summary>
+ /// Gets or sets the token.
+ /// </summary>
+ /// <value>
+ /// The token.
+ /// </value>
+ public string Token { get; set; }
+
+ /// <summary>
+ /// Gets or sets the token secret.
+ /// </summary>
+ /// <value>
+ /// The secret.
+ /// </value>
+ public string Secret { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessTokenResponse.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessTokenResponse.cs
new file mode 100644
index 0000000..dd35400
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/AccessTokenResponse.cs
@@ -0,0 +1,19 @@
+namespace DotNetOpenAuth.OAuth {
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Specialized;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ public class AccessTokenResponse {
+ public AccessTokenResponse(string accessToken, string tokenSecret, NameValueCollection extraData) {
+ this.AccessToken = new AccessToken(accessToken, tokenSecret);
+ this.ExtraData = extraData;
+ }
+
+ public AccessToken AccessToken { get; set; }
+
+ public NameValueCollection ExtraData { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/IConsumerTokenManager.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/IConsumerTokenManager.cs
deleted file mode 100644
index 74ec3be..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/IConsumerTokenManager.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="IConsumerTokenManager.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth.ChannelElements {
- /// <summary>
- /// A token manager for use by a web site in its role as a consumer of
- /// an individual ServiceProvider.
- /// </summary>
- public interface IConsumerTokenManager : ITokenManager {
- /// <summary>
- /// Gets the consumer key.
- /// </summary>
- /// <value>The consumer key.</value>
- string ConsumerKey { get; }
-
- /// <summary>
- /// Gets the consumer secret.
- /// </summary>
- /// <value>The consumer secret.</value>
- string ConsumerSecret { get; }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerChannel.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerChannel.cs
deleted file mode 100644
index a10ff09..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerChannel.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="OAuthConsumerChannel.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.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.Messaging.Bindings;
- using Validation;
-
- /// <summary>
- /// The messaging channel for OAuth 1.0(a) Consumers.
- /// </summary>
- internal class OAuthConsumerChannel : OAuthChannel {
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthConsumerChannel" /> 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="messageFactory">The message factory.</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 OAuthConsumerChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IConsumerTokenManager tokenManager, ConsumerSecuritySettings securitySettings, IMessageFactory messageFactory = null, IHostFactories hostFactories = null)
- : base(
- signingBindingElement,
- tokenManager,
- securitySettings,
- messageFactory ?? new OAuthConsumerMessageFactory(),
- InitializeBindingElements(signingBindingElement, store),
- hostFactories) {
- Requires.NotNull(tokenManager, "tokenManager");
- Requires.NotNull(securitySettings, "securitySettings");
- Requires.NotNull(signingBindingElement, "signingBindingElement");
- }
-
- /// <summary>
- /// Gets the consumer secret for a given consumer key.
- /// </summary>
- /// <param name="consumerKey">The consumer key.</param>
- /// <returns>The consumer secret.</returns>
- protected override string GetConsumerSecret(string consumerKey) {
- var consumerTokenManager = (IConsumerTokenManager)this.TokenManager;
- ErrorUtilities.VerifyInternal(consumerKey == consumerTokenManager.ConsumerKey, "The token manager consumer key and the consumer key set earlier do not match!");
- return consumerTokenManager.ConsumerSecret;
- }
-
- /// <summary>
- /// Initializes the binding elements for the OAuth channel.
- /// </summary>
- /// <param name="signingBindingElement">The signing binding element.</param>
- /// <param name="store">The nonce store.</param>
- /// <returns>
- /// An array of binding elements used to initialize the channel.
- /// </returns>
- private static new IChannelBindingElement[] InitializeBindingElements(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store) {
- return OAuthChannel.InitializeBindingElements(signingBindingElement, store).ToArray();
- }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerMessageFactory.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerMessageFactory.cs
deleted file mode 100644
index e79749f..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/OAuthConsumerMessageFactory.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="OAuthConsumerMessageFactory.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth.ChannelElements {
- using System;
- using System.Collections.Generic;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OAuth.Messages;
-
- /// <summary>
- /// An OAuth-protocol specific implementation of the <see cref="IMessageFactory"/>
- /// interface.
- /// </summary>
- public class OAuthConsumerMessageFactory : IMessageFactory {
- /// <summary>
- /// Initializes a new instance of the <see cref="OAuthConsumerMessageFactory"/> class.
- /// </summary>
- protected internal OAuthConsumerMessageFactory() {
- }
-
- #region IMessageFactory Members
-
- /// <summary>
- /// Analyzes an incoming request message payload to discover what kind of
- /// message is embedded in it and returns the type, or null if no match is found.
- /// </summary>
- /// <param name="recipient">The intended or actual recipient of the request message.</param>
- /// <param name="fields">The name/value pairs that make up the message payload.</param>
- /// <returns>
- /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
- /// deserialize to. Null if the request isn't recognized as a valid protocol message.
- /// </returns>
- /// <remarks>
- /// The request messages are:
- /// UserAuthorizationResponse
- /// </remarks>
- public virtual IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary<string, string> fields) {
- MessageBase message = null;
-
- if (fields.ContainsKey("oauth_token")) {
- Protocol protocol = fields.ContainsKey("oauth_verifier") ? Protocol.V10a : Protocol.V10;
- message = new UserAuthorizationResponse(recipient.Location, protocol.Version);
- }
-
- if (message != null) {
- message.SetAsIncoming();
- }
-
- return message;
- }
-
- /// <summary>
- /// Analyzes an incoming request message payload to discover what kind of
- /// message is embedded in it and returns the type, or null if no match is found.
- /// </summary>
- /// <param name="request">
- /// The message that was sent as a request that resulted in the response.
- /// Null on a Consumer site that is receiving an indirect message from the Service Provider.
- /// </param>
- /// <param name="fields">The name/value pairs that make up the message payload.</param>
- /// <returns>
- /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
- /// deserialize to. Null if the request isn't recognized as a valid protocol message.
- /// </returns>
- /// <remarks>
- /// The response messages are:
- /// UnauthorizedTokenResponse
- /// AuthorizedTokenResponse
- /// </remarks>
- public virtual IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary<string, string> fields) {
- MessageBase message = null;
-
- // All response messages have the oauth_token field.
- if (!fields.ContainsKey("oauth_token")) {
- return null;
- }
-
- // All direct message responses should have the oauth_token_secret field.
- if (!fields.ContainsKey("oauth_token_secret")) {
- Logger.OAuth.Error("An OAuth message was expected to contain an oauth_token_secret but didn't.");
- return null;
- }
-
- var unauthorizedTokenRequest = request as UnauthorizedTokenRequest;
- var authorizedTokenRequest = request as AuthorizedTokenRequest;
- if (unauthorizedTokenRequest != null) {
- Protocol protocol = fields.ContainsKey("oauth_callback_confirmed") ? Protocol.V10a : Protocol.V10;
- message = new UnauthorizedTokenResponse(unauthorizedTokenRequest, protocol.Version);
- } else if (authorizedTokenRequest != null) {
- message = new AuthorizedTokenResponse(authorizedTokenRequest);
- } else {
- Logger.OAuth.ErrorFormat("Unexpected response message given the request type {0}", request.GetType().Name);
- throw new ProtocolException(OAuthStrings.InvalidIncomingMessage);
- }
-
- if (message != null) {
- message.SetAsIncoming();
- }
-
- return message;
- }
-
- #endregion
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/RsaSha1ConsumerSigningBindingElement.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/RsaSha1ConsumerSigningBindingElement.cs
deleted file mode 100644
index d492e33..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ChannelElements/RsaSha1ConsumerSigningBindingElement.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="RsaSha1ConsumerSigningBindingElement.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth.ChannelElements {
- using System;
- using System.Diagnostics.CodeAnalysis;
- 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.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Justification = "Acronym")]
- public class RsaSha1ConsumerSigningBindingElement : RsaSha1SigningBindingElement {
- /// <summary>
- /// Initializes a new instance of the <see cref="RsaSha1ConsumerSigningBindingElement"/> class.
- /// </summary>
- /// <param name="signingCertificate">The certificate used to sign outgoing messages.</param>
- public RsaSha1ConsumerSigningBindingElement(X509Certificate2 signingCertificate) {
- Requires.NotNull(signingCertificate, "signingCertificate");
-
- this.SigningCertificate = signingCertificate;
- }
-
- /// <summary>
- /// Gets or sets the certificate used to sign outgoing messages. Used only by Consumers.
- /// </summary>
- public X509Certificate2 SigningCertificate { get; set; }
-
- /// <summary>
- /// Determines whether the signature on some message is valid.
- /// </summary>
- /// <param name="message">The message to check the signature on.</param>
- /// <returns>
- /// <c>true</c> if the signature on the message is valid; otherwise, <c>false</c>.
- /// </returns>
- protected override bool IsSignatureValid(ITamperResistantOAuthMessage message) {
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Calculates a signature for a given message.
- /// </summary>
- /// <param name="message">The message to sign.</param>
- /// <returns>The signature for the message.</returns>
- /// <remarks>
- /// This method signs the message per OAuth 1.0 section 9.3.
- /// </remarks>
- protected override string GetSignature(ITamperResistantOAuthMessage message) {
- ErrorUtilities.VerifyOperation(this.SigningCertificate != null, OAuthStrings.X509CertificateNotProvidedForSigning);
-
- string signatureBaseString = ConstructSignatureBaseString(message, this.Channel.MessageDescriptions.GetAccessor(message));
- byte[] data = Encoding.ASCII.GetBytes(signatureBaseString);
- var provider = (RSACryptoServiceProvider)this.SigningCertificate.PrivateKey;
- byte[] binarySignature = provider.SignData(data, "SHA1");
- string base64Signature = Convert.ToBase64String(binarySignature);
- return base64Signature;
- }
-
- /// <summary>
- /// Creates a new object that is a copy of the current instance.
- /// </summary>
- /// <returns>
- /// A new object that is a copy of this instance.
- /// </returns>
- protected override ITamperProtectionChannelBindingElement Clone() {
- return new RsaSha1ConsumerSigningBindingElement(this.SigningCertificate);
- }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/Consumer.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/Consumer.cs
new file mode 100644
index 0000000..560e536
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/Consumer.cs
@@ -0,0 +1,336 @@
+//-----------------------------------------------------------------------
+// <copyright file="Consumer.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+ using System.Security.Cryptography.X509Certificates;
+ 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>
+ /// Base class for <see cref="WebConsumer"/> and <see cref="DesktopConsumer"/> types.
+ /// </summary>
+ public class Consumer {
+ /// <summary>
+ /// The host factories.
+ /// </summary>
+ private IHostFactories hostFactories;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Consumer"/> class.
+ /// </summary>
+ public Consumer() {
+ this.HostFactories = new DefaultOAuthHostFactories();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Consumer"/> class.
+ /// </summary>
+ /// <param name="consumerKey">The consumer key.</param>
+ /// <param name="consumerSecret">The consumer secret.</param>
+ /// <param name="serviceProvider">The service provider.</param>
+ /// <param name="temporaryCredentialStorage">The temporary credential storage.</param>
+ public Consumer(
+ string consumerKey,
+ string consumerSecret,
+ ServiceProviderDescription serviceProvider,
+ ITemporaryCredentialStorage temporaryCredentialStorage) {
+ this.ConsumerKey = consumerKey;
+ this.ConsumerSecret = consumerSecret;
+ this.ServiceProvider = serviceProvider;
+ this.TemporaryCredentialStorage = temporaryCredentialStorage;
+ }
+
+ /// <summary>
+ /// Gets or sets the object with factories for host-customizable services.
+ /// </summary>
+ public IHostFactories HostFactories {
+ get {
+ return this.hostFactories;
+ }
+
+ set {
+ Requires.NotNull(value, "value");
+ this.hostFactories = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the Consumer Key used to communicate with the Service Provider.
+ /// </summary>
+ public string ConsumerKey { get; set; }
+
+ /// <summary>
+ /// Gets or sets the consumer secret.
+ /// </summary>
+ /// <value>
+ /// The consumer secret.
+ /// </value>
+ public string ConsumerSecret { get; set; }
+
+ /// <summary>
+ /// Gets or sets the consumer certificate.
+ /// </summary>
+ /// <value>
+ /// The consumer certificate.
+ /// </value>
+ /// <remarks>
+ /// If set, this causes all outgoing messages to be signed with the certificate instead of the consumer secret.
+ /// </remarks>
+ public X509Certificate2 ConsumerCertificate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Service Provider that will be accessed.
+ /// </summary>
+ public ServiceProviderDescription ServiceProvider { get; set; }
+
+ /// <summary>
+ /// Gets the persistence store for tokens and secrets.
+ /// </summary>
+ public ITemporaryCredentialStorage TemporaryCredentialStorage { get; set; }
+
+ /// <summary>
+ /// Obtains an access token for a new account at the Service Provider via 2-legged OAuth.
+ /// </summary>
+ /// <param name="requestParameters">Any applicable parameters to include in the query string of the token request.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>The access token.</returns>
+ public async Task<AccessTokenResponse> RequestNewClientAccountAsync(IEnumerable<KeyValuePair<string, string>> requestParameters = null, CancellationToken cancellationToken = default(CancellationToken)) {
+ Verify.Operation(this.ConsumerKey != null, Strings.RequiredPropertyNotYetPreset, "ConsumerKey");
+ Verify.Operation(this.ServiceProvider != null, Strings.RequiredPropertyNotYetPreset, "ServiceProvider");
+
+ using (var handler = this.CreateMessageHandler()) {
+ using (var client = this.CreateHttpClient(handler)) {
+ string identifier, secret;
+
+ var requestUri = new UriBuilder(this.ServiceProvider.TemporaryCredentialsRequestEndpoint);
+ requestUri.AppendQueryArgument(Protocol.CallbackParameter, "oob");
+ requestUri.AppendQueryArgs(requestParameters);
+ var request = new HttpRequestMessage(this.ServiceProvider.TemporaryCredentialsRequestEndpointMethod, requestUri.Uri);
+ using (var response = await client.SendAsync(request, cancellationToken)) {
+ response.EnsureSuccessStatusCode();
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
+ string content = await response.Content.ReadAsStringAsync();
+ var responseData = HttpUtility.ParseQueryString(content);
+ identifier = responseData[Protocol.TokenParameter];
+ secret = responseData[Protocol.TokenSecretParameter];
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(identifier), MessagingStrings.RequiredParametersMissing, typeof(UnauthorizedTokenResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(secret != null, MessagingStrings.RequiredParametersMissing, typeof(UnauthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
+ }
+
+ // Immediately exchange the temporary credential for an access token.
+ handler.AccessToken = identifier;
+ handler.AccessTokenSecret = secret;
+ request = new HttpRequestMessage(this.ServiceProvider.TokenRequestEndpointMethod, this.ServiceProvider.TokenRequestEndpoint);
+ using (var response = await client.SendAsync(request, cancellationToken)) {
+ response.EnsureSuccessStatusCode();
+
+ // Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
+ string content = await response.Content.ReadAsStringAsync();
+ var responseData = HttpUtility.ParseQueryString(content);
+ string accessToken = responseData[Protocol.TokenParameter];
+ string tokenSecret = responseData[Protocol.TokenSecretParameter];
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(accessToken), MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(tokenSecret != null, MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
+
+ responseData.Remove(Protocol.TokenParameter);
+ responseData.Remove(Protocol.TokenSecretParameter);
+ return new AccessTokenResponse(accessToken, tokenSecret, responseData);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Prepares an OAuth message that begins an authorization request that will
+ /// redirect the user to the Service Provider to provide that authorization.
+ /// </summary>
+ /// <param name="callback">The absolute URI that the Service Provider should redirect the
+ /// User Agent to upon successful authorization, or <c>null</c> to signify an out of band return.</param>
+ /// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The URL to direct the user agent to for user authorization.
+ /// </returns>
+ public async Task<Uri> RequestUserAuthorizationAsync(Uri callback = null, IEnumerable<KeyValuePair<string, string>> requestParameters = null, CancellationToken cancellationToken = default(CancellationToken)) {
+ Requires.NotNull(callback, "callback");
+ Verify.Operation(this.ConsumerKey != null, Strings.RequiredPropertyNotYetPreset, "ConsumerKey");
+ Verify.Operation(this.TemporaryCredentialStorage != null, Strings.RequiredPropertyNotYetPreset, "TemporaryCredentialStorage");
+ Verify.Operation(this.ServiceProvider != null, Strings.RequiredPropertyNotYetPreset, "ServiceProvider");
+
+ // Obtain temporary credentials before the redirect.
+ using (var client = this.CreateHttpClient(new AccessToken())) {
+ var requestUri = new UriBuilder(this.ServiceProvider.TemporaryCredentialsRequestEndpoint);
+ requestUri.AppendQueryArgument(Protocol.CallbackParameter, callback != null ? callback.AbsoluteUri : "oob");
+ requestUri.AppendQueryArgs(requestParameters);
+ var request = new HttpRequestMessage(this.ServiceProvider.TemporaryCredentialsRequestEndpointMethod, requestUri.Uri);
+ using (var response = await client.SendAsync(request, cancellationToken)) {
+ response.EnsureSuccessStatusCode();
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
+ string content = await response.Content.ReadAsStringAsync();
+ var responseData = HttpUtility.ParseQueryString(content);
+ ErrorUtilities.VerifyProtocol(string.Equals(responseData[Protocol.CallbackConfirmedParameter], "true", StringComparison.Ordinal), MessagingStrings.RequiredParametersMissing, typeof(UnauthorizedTokenResponse).Name, Protocol.CallbackConfirmedParameter);
+ string identifier = responseData[Protocol.TokenParameter];
+ string secret = responseData[Protocol.TokenSecretParameter];
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(identifier), MessagingStrings.RequiredParametersMissing, typeof(UnauthorizedTokenResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(secret != null, MessagingStrings.RequiredParametersMissing, typeof(UnauthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
+
+ // Save the temporary credential we received so that after user authorization
+ // we can use it to obtain the access token.
+ cancellationToken.ThrowIfCancellationRequested();
+ this.TemporaryCredentialStorage.SaveTemporaryCredential(identifier, secret);
+
+ // Construct the user authorization URL so our caller can direct a browser to it.
+ var authorizationEndpoint = new UriBuilder(this.ServiceProvider.ResourceOwnerAuthorizationEndpoint);
+ authorizationEndpoint.AppendQueryArgument(Protocol.TokenParameter, identifier);
+ return authorizationEndpoint.Uri;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Obtains an access token after a successful user authorization.
+ /// </summary>
+ /// <param name="authorizationCompleteUri">The URI used to redirect back to the consumer that contains a message from the service provider.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The access token assigned by the Service Provider, or <c>null</c> if no response was detected in the specified URL.
+ /// </returns>
+ public async Task<AccessTokenResponse> ProcessUserAuthorizationAsync(Uri authorizationCompleteUri, CancellationToken cancellationToken = default(CancellationToken)) {
+ Requires.NotNull(authorizationCompleteUri, "authorizationCompleteUri");
+ Verify.Operation(this.TemporaryCredentialStorage != null, Strings.RequiredPropertyNotYetPreset, "TemporaryCredentialStorage");
+
+ // Parse the response and verify that it meets spec requirements.
+ var queryString = HttpUtility.ParseQueryString(authorizationCompleteUri.Query);
+ string identifier = queryString[Protocol.TokenParameter];
+ string verifier = queryString[Protocol.VerifierParameter];
+
+ if (identifier == null) {
+ // We assume there is no response message here at all, and return null to indicate that.
+ return null;
+ }
+
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(identifier), MessagingStrings.RequiredNonEmptyParameterWasEmpty, typeof(UserAuthorizationResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(verifier), MessagingStrings.RequiredNonEmptyParameterWasEmpty, typeof(UserAuthorizationResponse).Name, Protocol.VerifierParameter);
+
+ var temporaryCredential = this.TemporaryCredentialStorage.RetrieveTemporaryCredential();
+ Verify.Operation(string.Equals(temporaryCredential.Key, identifier, StringComparison.Ordinal), "Temporary credential identifiers do not match.");
+
+ return await this.ProcessUserAuthorizationAsync(verifier, cancellationToken);
+ }
+
+ /// <summary>
+ /// Obtains an access token after a successful user authorization.
+ /// </summary>
+ /// <param name="verifier">The verifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The access token assigned by the Service Provider.
+ /// </returns>
+ public async Task<AccessTokenResponse> ProcessUserAuthorizationAsync(string verifier, CancellationToken cancellationToken = default(CancellationToken)) {
+ Requires.NotNull(verifier, "verifier");
+ Verify.Operation(this.ConsumerKey != null, Strings.RequiredPropertyNotYetPreset, "ConsumerKey");
+ Verify.Operation(this.TemporaryCredentialStorage != null, Strings.RequiredPropertyNotYetPreset, "TemporaryCredentialStorage");
+ Verify.Operation(this.ServiceProvider != null, Strings.RequiredPropertyNotYetPreset, "ServiceProvider");
+
+ var temporaryCredential = this.TemporaryCredentialStorage.RetrieveTemporaryCredential();
+
+ using (var client = this.CreateHttpClient(new AccessToken(temporaryCredential.Key, temporaryCredential.Value))) {
+ var requestUri = new UriBuilder(this.ServiceProvider.TokenRequestEndpoint);
+ requestUri.AppendQueryArgument(Protocol.VerifierParameter, verifier);
+ var request = new HttpRequestMessage(this.ServiceProvider.TokenRequestEndpointMethod, requestUri.Uri);
+ using (var response = await client.SendAsync(request, cancellationToken)) {
+ response.EnsureSuccessStatusCode();
+
+ // Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
+ string content = await response.Content.ReadAsStringAsync();
+ var responseData = HttpUtility.ParseQueryString(content);
+ string accessToken = responseData[Protocol.TokenParameter];
+ string tokenSecret = responseData[Protocol.TokenSecretParameter];
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(accessToken), MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(tokenSecret != null, MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
+
+ responseData.Remove(Protocol.TokenParameter);
+ responseData.Remove(Protocol.TokenSecretParameter);
+ return new AccessTokenResponse(accessToken, tokenSecret, responseData);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates a message handler that signs outbound requests with a previously obtained authorization.
+ /// </summary>
+ /// <param name="accessToken">The access token to authorize outbound HTTP requests with.</param>
+ /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
+ /// <returns>
+ /// A message handler.
+ /// </returns>
+ /// <remarks>
+ /// Overrides of this method may allow various derived types of handlers to be returned,
+ /// enabling consumers that use RSA or other signing methods.
+ /// </remarks>
+ public virtual OAuth1HttpMessageHandlerBase CreateMessageHandler(AccessToken accessToken = default(AccessToken), HttpMessageHandler innerHandler = null) {
+ Verify.Operation(this.ConsumerKey != null, Strings.RequiredPropertyNotYetPreset, "ConsumerKey");
+
+ innerHandler = innerHandler ?? this.HostFactories.CreateHttpMessageHandler();
+ OAuth1HttpMessageHandlerBase handler;
+ if (this.ConsumerCertificate != null) {
+ handler = new OAuth1RsaSha1HttpMessageHandler(innerHandler) {
+ SigningCertificate = this.ConsumerCertificate,
+ };
+ } else {
+ handler = new OAuth1HmacSha1HttpMessageHandler(innerHandler);
+ }
+
+ handler.ConsumerKey = this.ConsumerKey;
+ handler.ConsumerSecret = this.ConsumerSecret;
+ handler.AccessToken = accessToken.Token;
+ handler.AccessTokenSecret = accessToken.Secret;
+
+ return handler;
+ }
+
+ /// <summary>
+ /// Creates the HTTP client.
+ /// </summary>
+ /// <param name="accessToken">The access token to authorize outbound HTTP requests with.</param>
+ /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
+ /// <returns>The HttpClient to use.</returns>
+ public HttpClient CreateHttpClient(AccessToken accessToken, HttpMessageHandler innerHandler = null) {
+ var handler = this.CreateMessageHandler(accessToken, innerHandler);
+ var client = this.HostFactories.CreateHttpClient(handler);
+ return client;
+ }
+
+ /// <summary>
+ /// Creates the HTTP client.
+ /// </summary>
+ /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
+ /// <returns>The HttpClient to use.</returns>
+ public HttpClient CreateHttpClient(OAuth1HttpMessageHandlerBase innerHandler) {
+ Requires.NotNull(innerHandler, "innerHandler");
+
+ var client = this.HostFactories.CreateHttpClient(innerHandler);
+ return client;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ConsumerBase.cs
deleted file mode 100644
index 1bea2c5..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ConsumerBase.cs
+++ /dev/null
@@ -1,258 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="ConsumerBase.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using DotNetOpenAuth.Configuration;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.Messaging.Bindings;
- using DotNetOpenAuth.OAuth.ChannelElements;
- using DotNetOpenAuth.OAuth.Messages;
- using Validation;
-
- /// <summary>
- /// Base class for <see cref="WebConsumer"/> and <see cref="DesktopConsumer"/> types.
- /// </summary>
- public class ConsumerBase : IDisposable {
- /// <summary>
- /// Initializes a new instance of the <see cref="ConsumerBase"/> class.
- /// </summary>
- /// <param name="serviceDescription">The endpoints and behavior of the Service Provider.</param>
- /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
- protected ConsumerBase(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager) {
- Requires.NotNull(serviceDescription, "serviceDescription");
- Requires.NotNull(tokenManager, "tokenManager");
-
- ITamperProtectionChannelBindingElement signingElement = serviceDescription.CreateTamperProtectionElement();
- INonceStore store = new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge);
- this.SecuritySettings = OAuthElement.Configuration.Consumer.SecuritySettings.CreateSecuritySettings();
- this.OAuthChannel = new OAuthConsumerChannel(signingElement, store, tokenManager, this.SecuritySettings);
- this.ServiceProvider = serviceDescription;
-
- OAuthReporting.RecordFeatureAndDependencyUse(this, serviceDescription, tokenManager, null);
- }
-
- /// <summary>
- /// Gets the Consumer Key used to communicate with the Service Provider.
- /// </summary>
- public string ConsumerKey {
- get { return this.TokenManager.ConsumerKey; }
- }
-
- /// <summary>
- /// Gets the Service Provider that will be accessed.
- /// </summary>
- public ServiceProviderDescription ServiceProvider { get; private set; }
-
- /// <summary>
- /// Gets the persistence store for tokens and secrets.
- /// </summary>
- public IConsumerTokenManager TokenManager {
- get { return (IConsumerTokenManager)this.OAuthChannel.TokenManager; }
- }
-
- /// <summary>
- /// Gets the channel to use for sending/receiving messages.
- /// </summary>
- public Channel Channel {
- get { return this.OAuthChannel; }
- }
-
- /// <summary>
- /// Gets the security settings for this consumer.
- /// </summary>
- internal ConsumerSecuritySettings SecuritySettings { get; private set; }
-
- /// <summary>
- /// Gets or sets the channel to use for sending/receiving messages.
- /// </summary>
- internal OAuthChannel OAuthChannel { get; set; }
-
- /// <summary>
- /// Creates a message handler that signs outbound requests with a previously obtained authorization.
- /// </summary>
- /// <param name="accessToken">The access token to authorize outbound HTTP requests with.</param>
- /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
- /// <returns>
- /// A message handler.
- /// </returns>
- public OAuth1HttpMessageHandlerBase CreateMessageHandler(string accessToken = null, HttpMessageHandler innerHandler = null) {
- return new OAuth1HmacSha1HttpMessageHandler() {
- ConsumerKey = this.ConsumerKey,
- ConsumerSecret = this.TokenManager.ConsumerSecret,
- AccessToken = accessToken,
- AccessTokenSecret = accessToken != null ? this.TokenManager.GetTokenSecret(accessToken) : null,
- InnerHandler = innerHandler ?? this.Channel.HostFactories.CreateHttpMessageHandler(),
- };
- }
-
- /// <summary>
- /// Creates the HTTP client.
- /// </summary>
- /// <param name="accessToken">The access token to authorize outbound HTTP requests with.</param>
- /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
- /// <returns>The HttpClient to use.</returns>
- public HttpClient CreateHttpClient(string accessToken, HttpMessageHandler innerHandler = null) {
- Requires.NotNullOrEmpty(accessToken, "accessToken");
-
- var handler = this.CreateMessageHandler(accessToken, innerHandler);
- var client = this.Channel.HostFactories.CreateHttpClient(handler);
- return client;
- }
-
- /// <summary>
- /// Creates the HTTP client.
- /// </summary>
- /// <param name="innerHandler">The inner handler that actually sends the HTTP message on the network.</param>
- /// <returns>The HttpClient to use.</returns>
- public HttpClient CreateHttpClient(OAuth1HttpMessageHandlerBase innerHandler) {
- Requires.NotNull(innerHandler, "innerHandler");
-
- var client = this.Channel.HostFactories.CreateHttpClient(innerHandler);
- return client;
- }
-
- /// <summary>
- /// Obtains an access token for a new account at the Service Provider via 2-legged OAuth.
- /// </summary>
- /// <param name="requestParameters">Any applicable parameters to include in the query string of the token request.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>The access token.</returns>
- /// <remarks>
- /// The token secret is stored in the <see cref="TokenManager"/>.
- /// </remarks>
- public async Task<string> RequestNewClientAccountAsync(IDictionary<string, string> requestParameters = null, CancellationToken cancellationToken = default(CancellationToken)) {
- // Obtain an unauthorized request token. Force use of OAuth 1.0 (not 1.0a) so that
- // we are not expected to provide an oauth_verifier which doesn't apply in 2-legged OAuth.
- var token = new UnauthorizedTokenRequest(this.ServiceProvider.RequestTokenEndpoint, Protocol.V10.Version) {
- ConsumerKey = this.ConsumerKey,
- };
- var tokenAccessor = this.Channel.MessageDescriptions.GetAccessor(token);
- tokenAccessor.AddExtraParameters(requestParameters);
- var requestTokenResponse = await this.Channel.RequestAsync<UnauthorizedTokenResponse>(token, cancellationToken);
- this.TokenManager.StoreNewRequestToken(token, requestTokenResponse);
-
- var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, Protocol.V10.Version) {
- RequestToken = requestTokenResponse.RequestToken,
- ConsumerKey = this.ConsumerKey,
- };
- var grantAccess = await this.Channel.RequestAsync<AuthorizedTokenResponse>(requestAccess, cancellationToken);
- this.TokenManager.ExpireRequestTokenAndStoreNewAccessToken(this.ConsumerKey, requestTokenResponse.RequestToken, grantAccess.AccessToken, grantAccess.TokenSecret);
- return grantAccess.AccessToken;
- }
-
- #region IDisposable Members
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose() {
- this.Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- #endregion
-
- /// <summary>
- /// Creates a web request prepared with OAuth authorization
- /// that may be further tailored by adding parameters by the caller.
- /// </summary>
- /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
- /// <param name="accessToken">The access token that permits access to the protected resource.</param>
- /// <returns>The initialized WebRequest object.</returns>
- protected internal AccessProtectedResourceRequest CreateAuthorizingMessage(MessageReceivingEndpoint endpoint, string accessToken) {
- Requires.NotNull(endpoint, "endpoint");
- Requires.NotNullOrEmpty(accessToken, "accessToken");
-
- AccessProtectedResourceRequest message = new AccessProtectedResourceRequest(endpoint, this.ServiceProvider.Version) {
- AccessToken = accessToken,
- ConsumerKey = this.ConsumerKey,
- };
-
- return message;
- }
-
- /// <summary>
- /// Prepares an OAuth message that begins an authorization request that will
- /// redirect the user to the Service Provider to provide that authorization.
- /// </summary>
- /// <param name="callback">An optional Consumer URL that the Service Provider should redirect the
- /// User Agent to upon successful authorization.</param>
- /// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
- /// <param name="redirectParameters">Extra parameters to add to the redirect to Service Provider message. Optional.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>
- /// The pending user agent redirect based message to be sent as an HttpResponse.
- /// </returns>
- [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#", Justification = "Two results")]
- protected internal async Task<UserAuthorizationRequest> PrepareRequestUserAuthorizationAsync(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, CancellationToken cancellationToken = default(CancellationToken)) {
- // Obtain an unauthorized request token. Assume the OAuth version given in the service description.
- var token = new UnauthorizedTokenRequest(this.ServiceProvider.RequestTokenEndpoint, this.ServiceProvider.Version) {
- ConsumerKey = this.ConsumerKey,
- Callback = callback,
- };
- var tokenAccessor = this.Channel.MessageDescriptions.GetAccessor(token);
- tokenAccessor.AddExtraParameters(requestParameters);
- var requestTokenResponse = await this.Channel.RequestAsync<UnauthorizedTokenResponse>(token, cancellationToken);
- this.TokenManager.StoreNewRequestToken(token, requestTokenResponse);
-
- // Fine-tune our understanding of the SP's supported OAuth version if it's wrong.
- if (this.ServiceProvider.Version != requestTokenResponse.Version) {
- Logger.OAuth.WarnFormat("Expected OAuth service provider at endpoint {0} to use OAuth {1} but {2} was detected. Adjusting service description to new version.", this.ServiceProvider.RequestTokenEndpoint.Location, this.ServiceProvider.Version, requestTokenResponse.Version);
- this.ServiceProvider.ProtocolVersion = Protocol.Lookup(requestTokenResponse.Version).ProtocolVersion;
- }
-
- // Request user authorization. The OAuth version will automatically include
- // or drop the callback that we're setting here.
- ITokenContainingMessage assignedRequestToken = requestTokenResponse;
- var requestAuthorization = new UserAuthorizationRequest(this.ServiceProvider.UserAuthorizationEndpoint, assignedRequestToken.Token, requestTokenResponse.Version) {
- Callback = callback,
- };
- var requestAuthorizationAccessor = this.Channel.MessageDescriptions.GetAccessor(requestAuthorization);
- requestAuthorizationAccessor.AddExtraParameters(redirectParameters);
- return requestAuthorization;
- }
-
- /// <summary>
- /// Exchanges a given request token for access token.
- /// </summary>
- /// <param name="requestToken">The request token that the user has authorized.</param>
- /// <param name="verifier">The verifier code.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>
- /// The access token assigned by the Service Provider.
- /// </returns>
- protected async Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(string requestToken, string verifier, CancellationToken cancellationToken = default(CancellationToken)) {
- Requires.NotNullOrEmpty(requestToken, "requestToken");
-
- var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, this.ServiceProvider.Version) {
- RequestToken = requestToken,
- VerificationCode = verifier,
- ConsumerKey = this.ConsumerKey,
- };
- var grantAccess = await this.Channel.RequestAsync<AuthorizedTokenResponse>(requestAccess, cancellationToken);
- this.TokenManager.ExpireRequestTokenAndStoreNewAccessToken(this.ConsumerKey, requestToken, grantAccess.AccessToken, grantAccess.TokenSecret);
- return grantAccess;
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing) {
- if (disposing) {
- this.Channel.Dispose();
- }
- }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/CookieTemporaryCredentialStorage.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/CookieTemporaryCredentialStorage.cs
new file mode 100644
index 0000000..25941e6
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/CookieTemporaryCredentialStorage.cs
@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------
+// <copyright file="CookieTemporaryCredentialStorage.cs" company="Microsoft">
+// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+ using System.Web;
+ using System.Web.Security;
+ using Validation;
+
+ /// <summary>
+ /// Provides temporary credential storage by persisting them in a protected cookie on the
+ /// user agent (i.e. browser).
+ /// </summary>
+ public class CookieTemporaryCredentialStorage : ITemporaryCredentialStorage {
+ /// <summary>
+ /// Key used for token cookie
+ /// </summary>
+ protected const string TokenCookieKey = "DNOAOAuth1TempCredential";
+
+ /// <summary>
+ /// Primary request context.
+ /// </summary>
+ private readonly HttpContextBase httpContext;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CookieTemporaryCredentialsStorage"/> class
+ /// using <see cref="HttpContext.Current"/> as the source for the context to read and write cookies to.
+ /// </summary>
+ public CookieTemporaryCredentialStorage()
+ : this(new HttpContextWrapper(HttpContext.Current)) {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CookieTemporaryCredentialsStorage"/> class.
+ /// </summary>
+ /// <param name="httpContext">The HTTP context from and to which to access cookies.</param>
+ public CookieTemporaryCredentialStorage(HttpContextBase httpContext) {
+ Requires.NotNull(httpContext, "httpContext");
+ this.httpContext = httpContext;
+ }
+
+ #region ITemporaryCredentialsStorage Members
+
+ /// <summary>
+ /// Saves the temporary credential.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="secret">The secret.</param>
+ public void SaveTemporaryCredential(string identifier, string secret) {
+ var cookie = new HttpCookie(TokenCookieKey) {
+ HttpOnly = true
+ };
+
+ if (FormsAuthentication.RequireSSL) {
+ cookie.Secure = true;
+ }
+
+ var encryptedToken = ProtectAndEncodeToken(identifier, secret);
+ cookie.Values[identifier] = encryptedToken;
+
+ this.httpContext.Response.Cookies.Set(cookie);
+ }
+
+ /// <summary>
+ /// Obtains the temporary credential identifier and secret, if available.
+ /// </summary>
+ /// <returns>
+ /// An initialized key value pair if credentials are available; otherwise both key and value are <c>null</c>.
+ /// </returns>
+ /// <exception cref="System.NotImplementedException"></exception>
+ public KeyValuePair<string, string> RetrieveTemporaryCredential() {
+ HttpCookie cookie = this.httpContext.Request.Cookies[TokenCookieKey];
+ if (cookie == null || cookie.Values.Count == 0) {
+ return new KeyValuePair<string, string>();
+ }
+
+ string identifier = cookie.Values.GetKey(0);
+ string secret = DecodeAndUnprotectToken(identifier, cookie.Values[identifier]);
+ return new KeyValuePair<string, string>(identifier, secret);
+ }
+
+ /// <summary>
+ /// Clears the temporary credentials from storage.
+ /// </summary>
+ /// <remarks>
+ /// DotNetOpenAuth calls this when the credentials are no longer needed.
+ /// </remarks>
+ public void ClearTemporaryCredential() {
+ var cookie = new HttpCookie(TokenCookieKey) {
+ Value = string.Empty,
+ Expires = DateTime.UtcNow.AddDays(-5),
+ };
+ this.httpContext.Response.Cookies.Set(cookie);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Protect and url-encode the specified token secret.
+ /// </summary>
+ /// <param name="token">The token to be used as a key.</param>
+ /// <param name="tokenSecret">The token secret to be protected</param>
+ /// <returns>The encrypted and protected string.</returns>
+ protected static string ProtectAndEncodeToken(string token, string tokenSecret) {
+ byte[] cookieBytes = Encoding.UTF8.GetBytes(tokenSecret);
+ var secretBytes = MachineKeyUtil.Protect(cookieBytes, TokenCookieKey, "Token:" + token);
+ return HttpServerUtility.UrlTokenEncode(secretBytes);
+ }
+
+ /// <summary>
+ /// Url-decode and unprotect the specified encrypted token string.
+ /// </summary>
+ /// <param name="token">The token to be used as a key.</param>
+ /// <param name="encryptedToken">The encrypted token to be decrypted</param>
+ /// <returns>The original token secret</returns>
+ protected static string DecodeAndUnprotectToken(string token, string encryptedToken) {
+ byte[] cookieBytes = HttpServerUtility.UrlTokenDecode(encryptedToken);
+ byte[] clearBytes = MachineKeyUtil.Unprotect(cookieBytes, TokenCookieKey, "Token:" + token);
+ return Encoding.UTF8.GetString(clearBytes);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/DesktopConsumer.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/DesktopConsumer.cs
deleted file mode 100644
index a1bfd2d..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/DesktopConsumer.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="DesktopConsumer.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.Threading;
- using System.Threading.Tasks;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OAuth;
- using DotNetOpenAuth.OAuth.ChannelElements;
- using DotNetOpenAuth.OAuth.Messages;
-
- /// <summary>
- /// Used by a desktop application to use OAuth to access the Service Provider on behalf of the User.
- /// </summary>
- /// <remarks>
- /// The methods on this class are thread-safe. Provided the properties are set and not changed
- /// afterward, a single instance of this class may be used by an entire desktop application safely.
- /// </remarks>
- public class DesktopConsumer : ConsumerBase {
- /// <summary>
- /// Initializes a new instance of the <see cref="DesktopConsumer"/> class.
- /// </summary>
- /// <param name="serviceDescription">The endpoints and behavior of the Service Provider.</param>
- /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
- public DesktopConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
- : base(serviceDescription, tokenManager) {
- }
-
- /// <summary>
- /// Begins an OAuth authorization request.
- /// </summary>
- /// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
- /// <param name="redirectParameters">Extra parameters to add to the redirect to Service Provider message. Optional.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>
- /// The URL to open a browser window to allow the user to provide authorization and the request token.
- /// </returns>
- [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Two results")]
- public async Task<Tuple<Uri, string>> RequestUserAuthorizationAsync(IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, CancellationToken cancellationToken = default(CancellationToken)) {
- var message = await this.PrepareRequestUserAuthorizationAsync(null, requestParameters, redirectParameters, cancellationToken);
- var response = await this.Channel.PrepareResponseAsync(message, cancellationToken);
- return Tuple.Create(response.GetDirectUriRequest(), message.RequestToken);
- }
-
- /// <summary>
- /// Exchanges a given request token for access token.
- /// </summary>
- /// <param name="requestToken">The request token that the user has authorized.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>The access token assigned by the Service Provider.</returns>
- [Obsolete("Use the ProcessUserAuthorization method that takes a verifier parameter instead.")]
- public Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(string requestToken, CancellationToken cancellationToken = default(CancellationToken)) {
- return this.ProcessUserAuthorizationAsync(requestToken, null, cancellationToken);
- }
-
- /// <summary>
- /// Exchanges a given request token for access token.
- /// </summary>
- /// <param name="requestToken">The request token that the user has authorized.</param>
- /// <param name="verifier">The verifier code typed in by the user. Must not be <c>Null</c> for OAuth 1.0a service providers and later.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>
- /// The access token assigned by the Service Provider.
- /// </returns>
- public new Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(string requestToken, string verifier, CancellationToken cancellationToken = default(CancellationToken)) {
- if (this.ServiceProvider.Version >= Protocol.V10a.Version) {
- ErrorUtilities.VerifyNonZeroLength(verifier, "verifier");
- }
-
- return base.ProcessUserAuthorizationAsync(requestToken, verifier, cancellationToken);
- }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ITemporaryCredentialStorage.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ITemporaryCredentialStorage.cs
new file mode 100644
index 0000000..428749a
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ITemporaryCredentialStorage.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="ITemporaryCredentialStorage.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ using System.Collections.Generic;
+
+ /// <summary>
+ /// A token manager for use by an OAuth Consumer to store a temporary credential
+ /// (previously known as "unauthorized request token and secret").
+ /// </summary>
+ /// <remarks>
+ /// The credentials stored here are obtained as described in:
+ /// http://tools.ietf.org/html/rfc5849#section-2.1
+ /// </remarks>
+ public interface ITemporaryCredentialStorage {
+ /// <summary>
+ /// Saves the specified temporary credential for later retrieval.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="secret">The secret.</param>
+ void SaveTemporaryCredential(string identifier, string secret);
+
+ /// <summary>
+ /// Obtains a temporary credential secret, if available.
+ /// </summary>
+ /// <returns>The temporary credential identifier secret if available; otherwise a key value pair whose strings are left in their uninitialized <c>null</c> state.</returns>
+ KeyValuePair<string, string> RetrieveTemporaryCredential();
+
+ /// <summary>
+ /// Clears the temporary credentials from storage.
+ /// </summary>
+ /// <remarks>
+ /// DotNetOpenAuth calls this when the credentials are no longer needed.
+ /// </remarks>
+ void ClearTemporaryCredential();
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/MemoryTemporaryCredentialStorage.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/MemoryTemporaryCredentialStorage.cs
new file mode 100644
index 0000000..832084d
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/MemoryTemporaryCredentialStorage.cs
@@ -0,0 +1,65 @@
+//-----------------------------------------------------------------------
+// <copyright file="MemoryTemporaryCredentialStorage.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ /// <summary>
+ /// Non-persistent memory storage for temporary credentials.
+ /// Useful for installed apps (not redirection based web apps).
+ /// </summary>
+ public class MemoryTemporaryCredentialStorage : ITemporaryCredentialStorage {
+ /// <summary>
+ /// The identifier.
+ /// </summary>
+ private string identifier;
+
+ /// <summary>
+ /// The secret.
+ /// </summary>
+ private string secret;
+
+ #region ITemporaryCredentialStorage Members
+
+ /// <summary>
+ /// Saves the specified temporary credential for later retrieval.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="secret">The secret.</param>
+ public void SaveTemporaryCredential(string identifier, string secret) {
+ this.identifier = identifier;
+ this.secret = secret;
+ }
+
+ /// <summary>
+ /// Obtains a temporary credential secret, if available.
+ /// </summary>
+ /// <returns>
+ /// The temporary credential secret if available; otherwise <c>null</c>.
+ /// </returns>
+ public KeyValuePair<string, string> RetrieveTemporaryCredential() {
+ return new KeyValuePair<string, string>(this.identifier, this.secret);
+ }
+
+ /// <summary>
+ /// Clears the temporary credentials from storage.
+ /// </summary>
+ /// <param name="identifier">The identifier of the credentials to clear.</param>
+ /// <remarks>
+ /// DotNetOpenAuth calls this when the credentials are no longer needed.
+ /// </remarks>
+ public void ClearTemporaryCredential() {
+ this.identifier = null;
+ this.secret = null;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1HttpMessageHandlerBase.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1HttpMessageHandlerBase.cs
index 17d7b7a..aa462f3 100644
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1HttpMessageHandlerBase.cs
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1HttpMessageHandlerBase.cs
@@ -154,6 +154,10 @@ namespace DotNetOpenAuth.OAuth {
// Add parameters and signature to request.
switch (this.Location) {
case OAuthParametersLocation.AuthorizationHttpHeader:
+ // Some oauth parameters may have been put in the query string of the original message.
+ // We want to move any that we find into the authorization header.
+ oauthParameters.Add(ExtractOAuthParametersFromQueryString(request));
+
request.Headers.Authorization = new AuthenticationHeaderValue(Protocol.AuthorizationHeaderScheme, MessagingUtilities.AssembleAuthorizationHeader(oauthParameters.AsKeyValuePairs()));
break;
case OAuthParametersLocation.QueryString:
@@ -258,6 +262,38 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
+ /// Collects and removes all query string parameters beginning with "oauth_" from the specified request,
+ /// and returns them as a collection.
+ /// </summary>
+ /// <param name="request">The request whose query string should be searched for "oauth_" parameters.</param>
+ /// <returns>The collection of parameters that were removed from the query string.</returns>
+ private static NameValueCollection ExtractOAuthParametersFromQueryString(HttpRequestMessage request) {
+ Requires.NotNull(request, "request");
+
+ var extracted = new NameValueCollection();
+ if (!string.IsNullOrEmpty(request.RequestUri.Query)) {
+ var queryString = HttpUtility.ParseQueryString(request.RequestUri.Query);
+ foreach (var pair in queryString.AsKeyValuePairs()) {
+ if (pair.Key.StartsWith(Protocol.ParameterPrefix, StringComparison.Ordinal)) {
+ extracted.Add(pair.Key, pair.Value);
+ }
+ }
+
+ if (extracted.Count > 0) {
+ foreach (string key in extracted) {
+ queryString.Remove(key);
+ }
+
+ var modifiedRequestUri = new UriBuilder(request.RequestUri);
+ modifiedRequestUri.Query = MessagingUtilities.CreateQueryString(queryString.AsKeyValuePairs());
+ request.RequestUri = modifiedRequestUri.Uri;
+ }
+ }
+
+ return extracted;
+ }
+
+ /// <summary>
/// Constructs the "Signature Base String" as described in http://tools.ietf.org/html/rfc5849#section-3.4.1
/// </summary>
/// <param name="request">The HTTP request message.</param>
@@ -319,12 +355,6 @@ namespace DotNetOpenAuth.OAuth {
if (request.RequestUri.Query != null) {
// NameValueCollection does support non-unique keys, as long as you use it carefully.
nvc = HttpUtility.ParseQueryString(request.RequestUri.Query);
-
- // Remove any parameters beginning with "oauth_"
- var keysToRemove = nvc.Cast<string>().Where(k => k.StartsWith(Protocol.ParameterPrefix, StringComparison.Ordinal)).ToList();
- foreach (string key in keysToRemove) {
- nvc.Remove(key);
- }
} else {
nvc = new NameValueCollection(8);
}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1RsaSha1HttpMessageHandler.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1RsaSha1HttpMessageHandler.cs
index fd2ad65..129ebc2 100644
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1RsaSha1HttpMessageHandler.cs
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/OAuth1RsaSha1HttpMessageHandler.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth {
using System;
using System.Collections.Generic;
using System.Linq;
+ using System.Net.Http;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
@@ -20,6 +21,20 @@ namespace DotNetOpenAuth.OAuth {
/// </summary>
public class OAuth1RsaSha1HttpMessageHandler : OAuth1HttpMessageHandlerBase {
/// <summary>
+ /// Initializes a new instance of the <see cref="OAuth1RsaSha1HttpMessageHandler"/> class.
+ /// </summary>
+ public OAuth1RsaSha1HttpMessageHandler() {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OAuth1RsaSha1HttpMessageHandler"/> class.
+ /// </summary>
+ /// <param name="innerHandler">The inner handler which is responsible for processing the HTTP response messages.</param>
+ public OAuth1RsaSha1HttpMessageHandler(HttpMessageHandler innerHandler)
+ : base(innerHandler) {
+ }
+
+ /// <summary>
/// Gets or sets the certificate used to sign outgoing messages. Used only by Consumers.
/// </summary>
public X509Certificate2 SigningCertificate { get; set; }
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ServiceProviderDescription.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ServiceProviderDescription.cs
new file mode 100644
index 0000000..2d07af4
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/ServiceProviderDescription.cs
@@ -0,0 +1,85 @@
+//-----------------------------------------------------------------------
+// <copyright file="ServiceProviderDescription.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net.Http;
+ using System.Text;
+ using System.Threading.Tasks;
+ using Validation;
+
+ /// <summary>
+ /// Describes an OAuth 1.0 service provider.
+ /// </summary>
+ public class ServiceProviderDescription {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServiceProviderDescription" /> class.
+ /// </summary>
+ public ServiceProviderDescription() {
+ this.TemporaryCredentialsRequestEndpointMethod = HttpMethod.Post;
+ this.TokenRequestEndpointMethod = HttpMethod.Post;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServiceProviderDescription"/> class.
+ /// </summary>
+ /// <param name="temporaryCredentialsRequestEndpoint">The temporary credentials request endpoint.</param>
+ /// <param name="resourceOwnerAuthorizationEndpoint">The resource owner authorization endpoint.</param>
+ /// <param name="tokenRequestEndpoint">The token request endpoint.</param>
+ public ServiceProviderDescription(
+ string temporaryCredentialsRequestEndpoint, string resourceOwnerAuthorizationEndpoint, string tokenRequestEndpoint)
+ : this() {
+ if (temporaryCredentialsRequestEndpoint != null) {
+ this.TemporaryCredentialsRequestEndpoint = new Uri(temporaryCredentialsRequestEndpoint, UriKind.Absolute);
+ }
+
+ if (resourceOwnerAuthorizationEndpoint != null) {
+ this.ResourceOwnerAuthorizationEndpoint = new Uri(resourceOwnerAuthorizationEndpoint, UriKind.Absolute);
+ }
+
+ if (tokenRequestEndpoint != null) {
+ this.TokenRequestEndpoint = new Uri(tokenRequestEndpoint, UriKind.Absolute);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the temporary credentials request endpoint.
+ /// </summary>
+ /// <value>
+ /// The temporary credentials request endpoint.
+ /// </value>
+ public Uri TemporaryCredentialsRequestEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets or sets the HTTP method to use with the temporary credentials request endpoint.
+ /// </summary>
+ public HttpMethod TemporaryCredentialsRequestEndpointMethod { get; set; }
+
+ /// <summary>
+ /// Gets the resource owner authorization endpoint.
+ /// </summary>
+ /// <value>
+ /// The resource owner authorization endpoint.
+ /// May be <c>null</c> for 2-legged OAuth.
+ /// </value>
+ public Uri ResourceOwnerAuthorizationEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets the token request endpoint.
+ /// </summary>
+ /// <value>
+ /// The token request endpoint.
+ /// </value>
+ public Uri TokenRequestEndpoint { get; set; }
+
+ /// <summary>
+ /// Gets or sets the HTTP method to use with the token request endpoint.
+ /// </summary>
+ public HttpMethod TokenRequestEndpointMethod { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs
deleted file mode 100644
index 49a54a0..0000000
--- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="WebConsumer.cs" company="Outercurve Foundation">
-// Copyright (c) Outercurve Foundation. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OAuth {
- using System;
- using System.Collections.Generic;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Web;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OAuth.ChannelElements;
- using DotNetOpenAuth.OAuth.Messages;
- using Validation;
-
- /// <summary>
- /// A website or application that uses OAuth to access the Service Provider on behalf of the User.
- /// </summary>
- /// <remarks>
- /// The methods on this class are thread-safe. Provided the properties are set and not changed
- /// afterward, a single instance of this class may be used by an entire web application safely.
- /// </remarks>
- public class WebConsumer : ConsumerBase {
- /// <summary>
- /// Initializes a new instance of the <see cref="WebConsumer"/> class.
- /// </summary>
- /// <param name="serviceDescription">The endpoints and behavior of the Service Provider.</param>
- /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
- public WebConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
- : base(serviceDescription, tokenManager) {
- }
-
- /// <summary>
- /// Begins an OAuth authorization request and redirects the user to the Service Provider
- /// to provide that authorization. Upon successful authorization, the user is redirected
- /// back to the current page.
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
- /// <remarks>
- /// Requires HttpContext.Current.
- /// </remarks>
- public Task<UserAuthorizationRequest> PrepareRequestUserAuthorizationAsync(CancellationToken cancellationToken = default(CancellationToken)) {
- Uri callback = this.Channel.GetRequestFromContext().GetPublicFacingUrl().StripQueryArgumentsWithPrefix(Protocol.ParameterPrefix);
- return this.PrepareRequestUserAuthorizationAsync(callback, null, null, cancellationToken);
- }
-
- /// <summary>
- /// Prepares an OAuth message that begins an authorization request that will
- /// redirect the user to the Service Provider to provide that authorization.
- /// </summary>
- /// <param name="callback">
- /// An optional Consumer URL that the Service Provider should redirect the
- /// User Agent to upon successful authorization.
- /// </param>
- /// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
- /// <param name="redirectParameters">Extra parameters to add to the redirect to Service Provider message. Optional.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
- public new Task<UserAuthorizationRequest> PrepareRequestUserAuthorizationAsync(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, CancellationToken cancellationToken = default(CancellationToken)) {
- return base.PrepareRequestUserAuthorizationAsync(callback, requestParameters, redirectParameters, cancellationToken);
- }
-
- /// <summary>
- /// Processes an incoming authorization-granted message from an SP and obtains an access token.
- /// </summary>
- /// <param name="request">The incoming HTTP request.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>
- /// The access token, or null if no incoming authorization message was recognized.
- /// </returns>
- public async Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(HttpRequestBase request = null, CancellationToken cancellationToken = default(CancellationToken)) {
- request = request ?? this.Channel.GetRequestFromContext();
-
- var authorizationMessage = await this.Channel.TryReadFromRequestAsync<UserAuthorizationResponse>(cancellationToken, request);
- if (authorizationMessage != null) {
- string requestToken = authorizationMessage.RequestToken;
- string verifier = authorizationMessage.VerificationCode;
- return await this.ProcessUserAuthorizationAsync(requestToken, verifier, cancellationToken);
- } else {
- return null;
- }
- }
- }
-}
diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj b/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj
index 815a341..8e87ad4 100644
--- a/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj
+++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/DotNetOpenAuth.OAuth.ServiceProvider.csproj
@@ -19,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>
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 ff44a45..0000000
--- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ChannelElements/OAuth1Principal.cs
+++ /dev/null
@@ -1,34 +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;
- using Validation;
-
- /// <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/ServiceProvider.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs
index de7ff7c..5e6cfb3 100644
--- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs
+++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs
@@ -55,7 +55,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)) {
}
@@ -65,7 +65,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="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)
+ 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");
@@ -78,7 +78,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)) {
}
@@ -89,7 +89,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");
@@ -107,7 +107,7 @@ namespace DotNetOpenAuth.OAuth {
/// <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.
@@ -412,11 +412,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/OAuth/ServiceProviderDescription.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs
index 6dbe6ea..33834eb 100644
--- a/src/DotNetOpenAuth.OAuth/OAuth/ServiceProviderDescription.cs
+++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProviderHostDescription.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="ServiceProviderDescription.cs" company="Outercurve Foundation">
+// <copyright file="ServiceProviderHostDescription.cs" company="Outercurve Foundation">
// Copyright (c) Outercurve Foundation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -15,7 +15,7 @@ namespace DotNetOpenAuth.OAuth {
/// <summary>
/// A description of the endpoints on a Service Provider.
/// </summary>
- public class ServiceProviderDescription {
+ public class ServiceProviderHostDescription {
/// <summary>
/// The field used to store the value of the <see cref="RequestTokenEndpoint"/> property.
/// </summary>
@@ -23,9 +23,9 @@ namespace DotNetOpenAuth.OAuth {
private MessageReceivingEndpoint requestTokenEndpoint;
/// <summary>
- /// Initializes a new instance of the <see cref="ServiceProviderDescription"/> class.
+ /// Initializes a new instance of the <see cref="ServiceProviderHostDescription"/> class.
/// </summary>
- public ServiceProviderDescription() {
+ public ServiceProviderHostDescription() {
this.ProtocolVersion = Protocol.Default.ProtocolVersion;
}
diff --git a/src/DotNetOpenAuth.OAuth/OAuthReporting.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs
index e2c0aab..8171e1a 100644
--- a/src/DotNetOpenAuth.OAuth/OAuthReporting.cs
+++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuthReporting.cs
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth {
/// <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, ServiceProviderDescription service, ITokenManager tokenManager, INonceStore nonceStore) {
+ internal static void RecordFeatureAndDependencyUse(object value, ServiceProviderHostDescription service, ITokenManager tokenManager, INonceStore nonceStore) {
Requires.NotNull(value, "value");
Requires.NotNull(service, "service");
Requires.NotNull(tokenManager, "tokenManager");
@@ -45,9 +45,7 @@ namespace DotNetOpenAuth {
builder.Append(nonceStore.GetType().Name);
}
builder.Append(" ");
- builder.Append(service.Version);
- builder.Append(" ");
- builder.Append(service.UserAuthorizationEndpoint);
+ builder.Append(service.UserAuthorizationEndpoint.Location);
Reporting.ObservedFeatures.Add(builder.ToString());
Reporting.Touch();
}
diff --git a/src/DotNetOpenAuth.OAuth/DotNetOpenAuth.OAuth.csproj b/src/DotNetOpenAuth.OAuth/DotNetOpenAuth.OAuth.csproj
index 58e09b0..af9aea9 100644
--- a/src/DotNetOpenAuth.OAuth/DotNetOpenAuth.OAuth.csproj
+++ b/src/DotNetOpenAuth.OAuth/DotNetOpenAuth.OAuth.csproj
@@ -25,7 +25,6 @@
<Compile Include="Configuration\OAuthServiceProviderElement.cs" />
<Compile Include="Configuration\OAuthServiceProviderSecuritySettingsElement.cs" />
<Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" />
- <Compile Include="OAuthReporting.cs" />
<Compile Include="OAuth\ChannelElements\ITokenManager.cs" />
<Compile Include="OAuth\ChannelElements\OAuthHttpMethodBindingElement.cs" />
<Compile Include="OAuth\ChannelElements\PlaintextSigningBindingElement.cs" />
@@ -35,13 +34,13 @@
<Compile Include="OAuth\ChannelElements\UriOrOobEncoding.cs" />
<Compile Include="OAuth\ConsumerSecuritySettings.cs" />
<Compile Include="OAuth\Messages\ITokenSecretContainingMessage.cs" />
+ <Compile Include="OAuth\Messages\MessageBaseSimple.cs" />
<Compile Include="OAuth\OAuthStrings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>OAuthStrings.resx</DependentUpon>
</Compile>
<Compile Include="OAuth\SecuritySettings.cs" />
- <Compile Include="OAuth\ServiceProviderDescription.cs" />
<Compile Include="OAuth\Messages\ITokenContainingMessage.cs" />
<Compile Include="OAuth\Messages\SignedMessageBase.cs" />
<Compile Include="OAuth\ChannelElements\SigningBindingElementBase.cs" />
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBaseSimple.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBaseSimple.cs
new file mode 100644
index 0000000..23822d3
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBaseSimple.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ class MessageBaseSimple {
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Protocol.cs b/src/DotNetOpenAuth.OAuth/OAuth/Protocol.cs
index 72f0ff4..049fd58 100644
--- a/src/DotNetOpenAuth.OAuth/OAuth/Protocol.cs
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Protocol.cs
@@ -60,6 +60,31 @@ namespace DotNetOpenAuth.OAuth {
internal const string AuthorizationHeaderScheme = "OAuth";
/// <summary>
+ /// The name of the 'oauth_callback' parameter.
+ /// </summary>
+ internal const string CallbackParameter = "oauth_callback";
+
+ /// <summary>
+ /// The name of the 'oauth_callback_confirmed' parameter.
+ /// </summary>
+ internal const string CallbackConfirmedParameter = "oauth_callback_confirmed";
+
+ /// <summary>
+ /// The name of the 'oauth_token' parameter.
+ /// </summary>
+ internal const string TokenParameter = "oauth_token";
+
+ /// <summary>
+ /// The name of the 'oauth_token_secret' parameter.
+ /// </summary>
+ internal const string TokenSecretParameter = "oauth_token_secret";
+
+ /// <summary>
+ /// The name of the 'oauth_verifier' parameter.
+ /// </summary>
+ internal const string VerifierParameter = "oauth_verifier";
+
+ /// <summary>
/// Gets the <see cref="Protocol"/> instance with values initialized for V1.0 of the protocol.
/// </summary>
internal static readonly Protocol V10 = new Protocol {
diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs
index a10e1aa..6d77f14 100644
--- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs
+++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/ClientDescription.cs
@@ -22,15 +22,36 @@ namespace DotNetOpenAuth.OAuth2 {
private readonly string secret;
/// <summary>
- /// Initializes a new instance of the <see cref="ClientDescription"/> class.
+ /// Initializes a new instance of the <see cref="ClientDescription"/> class
+ /// to represent a confidential client (one that has an authenticating secret.)
/// </summary>
/// <param name="secret">The secret.</param>
/// <param name="defaultCallback">The default callback.</param>
- /// <param name="clientType">Type of the client.</param>
- public ClientDescription(string secret, Uri defaultCallback, ClientType clientType) {
+ public ClientDescription(string secret, Uri defaultCallback) {
+ Requires.NotNullOrEmpty(secret, "secret");
+ Requires.NotNull(defaultCallback, "defaultCallback");
+
this.secret = secret;
this.DefaultCallback = defaultCallback;
- this.ClientType = clientType;
+ this.ClientType = ClientType.Confidential;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientDescription"/> class
+ /// to represent a public client (one that does not have an authenticating secret.)
+ /// </summary>
+ /// <param name="defaultCallback">The default callback.</param>
+ public ClientDescription(Uri defaultCallback) {
+ Requires.NotNull(defaultCallback, "defaultCallback");
+
+ this.DefaultCallback = defaultCallback;
+ this.ClientType = ClientType.Public;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClientDescription"/> class.
+ /// </summary>
+ protected ClientDescription() {
}
#region IClientDescription Members
@@ -42,12 +63,12 @@ namespace DotNetOpenAuth.OAuth2 {
/// <value>
/// An absolute URL; or <c>null</c> if none is registered.
/// </value>
- public Uri DefaultCallback { get; private set; }
+ public Uri DefaultCallback { get; protected set; }
/// <summary>
/// Gets the type of the client.
/// </summary>
- public ClientType ClientType { get; private set; }
+ public ClientType ClientType { get; protected set; }
/// <summary>
/// Gets a value indicating whether a non-empty secret is registered for this client.
diff --git a/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.cs b/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.cs
index 002202e..8f1c5f6 100644
--- a/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.cs
@@ -95,6 +95,14 @@ namespace DotNetOpenAuth.OAuth2 {
}
/// <summary>
+ /// Gets or sets a value indicating whether the implicit grant type should be used instead of the authorization code grant.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if [request implicit grant]; otherwise, <c>false</c>.
+ /// </value>
+ public bool RequestImplicitGrant { get; set; }
+
+ /// <summary>
/// Called when the authorization flow has been completed.
/// </summary>
protected virtual void OnCompleted() {
@@ -113,7 +121,7 @@ namespace DotNetOpenAuth.OAuth2 {
protected override async void OnLoad(EventArgs e) {
base.OnLoad(e);
- Uri authorizationUrl = await this.Client.RequestUserAuthorizationAsync(this.Authorization);
+ Uri authorizationUrl = await this.Client.RequestUserAuthorizationAsync(this.Authorization, implicitResponseType: this.RequestImplicitGrant);
this.webBrowser1.Navigate(authorizationUrl.AbsoluteUri); // use AbsoluteUri to workaround bug in WebBrowser that calls Uri.ToString instead of Uri.AbsoluteUri leading to escaping errors.
}
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs
index 9ebca32..92f882f 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/BearerTokenHttpMessageHandler.cs
@@ -75,7 +75,7 @@ namespace DotNetOpenAuth.OAuth2 {
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
string bearerToken = this.BearerToken;
if (bearerToken == null) {
- ErrorUtilities.VerifyProtocol(!this.Authorization.AccessTokenExpirationUtc.HasValue || this.Authorization.AccessTokenExpirationUtc < DateTime.UtcNow || this.Authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
+ ErrorUtilities.VerifyProtocol(!this.Authorization.AccessTokenExpirationUtc.HasValue || this.Authorization.AccessTokenExpirationUtc >= DateTime.UtcNow || this.Authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
if (this.Authorization.AccessTokenExpirationUtc.HasValue && this.Authorization.AccessTokenExpirationUtc.Value < DateTime.UtcNow) {
ErrorUtilities.VerifyProtocol(this.Authorization.RefreshToken != null, ClientStrings.AccessTokenRefreshFailed);
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
index 62dc311..65f3e1d 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
@@ -121,7 +121,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
// Typically the fragment is not available because the browser doesn't send it to a web server
// but this request may have been fabricated by an installed desktop app, in which case
// the fragment is available.
- string fragment = request.GetPublicFacingUrl().Fragment;
+ string fragment = request.Url.Fragment;
if (!string.IsNullOrEmpty(fragment)) {
foreach (var pair in HttpUtility.ParseQueryString(fragment.Substring(1)).ToDictionary()) {
fields.Add(pair.Key, pair.Value);
diff --git a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs
index 7bc7c91..88ce451 100644
--- a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs
+++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.OAuth2 {
using System.Linq;
using System.Net;
using System.Net.Http;
+ using System.Security.Claims;
using System.Security.Principal;
using System.ServiceModel.Channels;
using System.Text;
@@ -167,10 +168,8 @@ namespace DotNetOpenAuth.OAuth2 {
string principalUserName = !string.IsNullOrEmpty(accessToken.User)
? this.ResourceOwnerPrincipalPrefix + accessToken.User
: this.ClientPrincipalPrefix + accessToken.ClientIdentifier;
- string[] principalScope = accessToken.Scope != null ? accessToken.Scope.ToArray() : new string[0];
- var principal = new OAuthPrincipal(principalUserName, principalScope);
- return principal;
+ return OAuthPrincipal.CreatePrincipal(principalUserName, accessToken.Scope);
}
/// <summary>
diff --git a/src/DotNetOpenAuth.OpenIdOAuth/OAuth/ServiceProviderOpenIdProvider.cs b/src/DotNetOpenAuth.OpenIdOAuth/OAuth/ServiceProviderOpenIdProvider.cs
index f827857..1c0c5fb 100644
--- a/src/DotNetOpenAuth.OpenIdOAuth/OAuth/ServiceProviderOpenIdProvider.cs
+++ b/src/DotNetOpenAuth.OpenIdOAuth/OAuth/ServiceProviderOpenIdProvider.cs
@@ -41,7 +41,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 ServiceProviderOpenIdProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager)
+ public ServiceProviderOpenIdProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager)
: base(serviceDescription, tokenManager) {
}
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.OAuth {
/// <param name="serviceDescription">The service description.</param>
/// <param name="tokenManager">The token manager.</param>
/// <param name="messageTypeProvider">The message type provider.</param>
- public ServiceProviderOpenIdProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider)
+ public ServiceProviderOpenIdProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider)
: base(serviceDescription, tokenManager, messageTypeProvider) {
}
@@ -61,7 +61,7 @@ namespace DotNetOpenAuth.OAuth {
/// <param name="serviceDescription">The service description.</param>
/// <param name="tokenManager">The token manager.</param>
/// <param name="nonceStore">The nonce store.</param>
- public ServiceProviderOpenIdProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore)
+ public ServiceProviderOpenIdProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore)
: base(serviceDescription, tokenManager, nonceStore) {
}
@@ -72,7 +72,7 @@ namespace DotNetOpenAuth.OAuth {
/// <param name="tokenManager">The token manager.</param>
/// <param name="nonceStore">The nonce store.</param>
/// <param name="messageTypeProvider">The message type provider.</param>
- public ServiceProviderOpenIdProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore, OAuthServiceProviderMessageFactory messageTypeProvider)
+ public ServiceProviderOpenIdProvider(ServiceProviderHostDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore, OAuthServiceProviderMessageFactory messageTypeProvider)
: base(serviceDescription, tokenManager, nonceStore, messageTypeProvider) {
}
diff --git a/src/DotNetOpenAuth.OpenIdOAuth/OAuth/WebConsumerOpenIdRelyingParty.cs b/src/DotNetOpenAuth.OpenIdOAuth/OAuth/WebConsumerOpenIdRelyingParty.cs
index a19d505..dce51c2 100644
--- a/src/DotNetOpenAuth.OpenIdOAuth/OAuth/WebConsumerOpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth.OpenIdOAuth/OAuth/WebConsumerOpenIdRelyingParty.cs
@@ -8,9 +8,11 @@ namespace DotNetOpenAuth.OAuth {
using System;
using System.Collections.Generic;
using System.Linq;
+ using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+ using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
@@ -26,14 +28,13 @@ namespace DotNetOpenAuth.OAuth {
/// The methods on this class are thread-safe. Provided the properties are set and not changed
/// afterward, a single instance of this class may be used by an entire web application safely.
/// </remarks>
- public class WebConsumerOpenIdRelyingParty : WebConsumer {
+ public class WebConsumerOpenIdRelyingParty : Consumer {
/// <summary>
/// Initializes a new instance of the <see cref="WebConsumerOpenIdRelyingParty"/> class.
/// </summary>
/// <param name="serviceDescription">The endpoints and behavior of the Service Provider.</param>
/// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
- public WebConsumerOpenIdRelyingParty(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager)
- : base(serviceDescription, tokenManager) {
+ public WebConsumerOpenIdRelyingParty() {
}
/// <summary>
@@ -64,11 +65,8 @@ namespace DotNetOpenAuth.OAuth {
/// The access token, if granted, is automatically stored in the <see cref="ConsumerBase.TokenManager" />.
/// The token manager instance must implement <see cref="IOpenIdOAuthTokenManager" />.
/// </remarks>
- public async Task<AuthorizedTokenResponse> ProcessUserAuthorizationAsync(IAuthenticationResponse openIdAuthenticationResponse, CancellationToken cancellationToken = default(CancellationToken)) {
+ public async Task<AccessTokenResponse> ProcessUserAuthorizationAsync(IAuthenticationResponse openIdAuthenticationResponse, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(openIdAuthenticationResponse, "openIdAuthenticationResponse");
- RequiresEx.ValidState(this.TokenManager is IOpenIdOAuthTokenManager);
- var openidTokenManager = this.TokenManager as IOpenIdOAuthTokenManager;
- ErrorUtilities.VerifyOperation(openidTokenManager != null, OAuthStrings.OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface, typeof(IOpenIdOAuthTokenManager).FullName);
// The OAuth extension is only expected in positive assertion responses.
if (openIdAuthenticationResponse.Status != AuthenticationStatus.Authenticated) {
@@ -81,21 +79,24 @@ namespace DotNetOpenAuth.OAuth {
return null;
}
- // Prepare a message to exchange the request token for an access token.
- // We are careful to use a v1.0 message version so that the oauth_verifier is not required.
- var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, Protocol.V10.Version) {
- RequestToken = positiveAuthorization.RequestToken,
- ConsumerKey = this.ConsumerKey,
- };
+ using (var client = this.CreateHttpClient(new AccessToken(positiveAuthorization.RequestToken, string.Empty))) {
+ var request = new HttpRequestMessage(this.ServiceProvider.TokenRequestEndpointMethod, this.ServiceProvider.TokenRequestEndpoint);
+ using (var response = await client.SendAsync(request, cancellationToken)) {
+ response.EnsureSuccessStatusCode();
- // Retrieve the access token and store it in the token manager.
- openidTokenManager.StoreOpenIdAuthorizedRequestToken(this.ConsumerKey, positiveAuthorization);
- var grantAccess = await this.Channel.RequestAsync<AuthorizedTokenResponse>(requestAccess, cancellationToken);
- this.TokenManager.ExpireRequestTokenAndStoreNewAccessToken(this.ConsumerKey, positiveAuthorization.RequestToken, grantAccess.AccessToken, grantAccess.TokenSecret);
+ // Parse the response and ensure that it meets the requirements of the OAuth 1.0 spec.
+ string content = await response.Content.ReadAsStringAsync();
+ var responseData = HttpUtility.ParseQueryString(content);
+ string accessToken = responseData[Protocol.TokenParameter];
+ string tokenSecret = responseData[Protocol.TokenSecretParameter];
+ ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(accessToken), MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenParameter);
+ ErrorUtilities.VerifyProtocol(tokenSecret != null, MessagingStrings.RequiredParametersMissing, typeof(AuthorizedTokenResponse).Name, Protocol.TokenSecretParameter);
- // Provide the caller with the access token so it may be associated with the user
- // that is logging in.
- return grantAccess;
+ responseData.Remove(Protocol.TokenParameter);
+ responseData.Remove(Protocol.TokenSecretParameter);
+ return new AccessTokenResponse(accessToken, tokenSecret, responseData);
+ }
+ }
}
}
}