summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.AspNet/Clients
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.AspNet/Clients')
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs7
-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.cs92
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthTokenManager.cs38
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs38
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs158
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs107
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs68
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/SimpleConsumerTokenManager.cs104
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs80
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs5
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth2/MicrosoftClient.cs5
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs48
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs5
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs43
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs5
17 files changed, 219 insertions, 790 deletions
diff --git a/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs b/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs
index f441c07..a84fdcf 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
+ using System.Collections.Specialized;
using System.Xml.Linq;
/// <summary>
@@ -25,8 +26,8 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <param name="elementName">
/// Name of the element.
/// </param>
- public static void AddDataIfNotEmpty(
- this Dictionary<string, string> dictionary, XDocument document, string elementName) {
+ internal static void AddDataIfNotEmpty(
+ this NameValueCollection dictionary, XDocument document, string elementName) {
var element = document.Root.Element(elementName);
if (element != null) {
dictionary.AddItemIfNotEmpty(elementName, element.Value);
@@ -45,7 +46,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <param name="value">
/// The value.
/// </param>
- public static void AddItemIfNotEmpty(this IDictionary<string, string> dictionary, string key, string value) {
+ internal static void AddItemIfNotEmpty(this NameValueCollection dictionary, string key, string value) {
if (key == null) {
throw new ArgumentNullException("key");
}
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 e216906..1b6318f 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs
@@ -8,6 +8,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
using System.Net;
+ using System.Net.Http;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
@@ -17,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
@@ -38,75 +42,65 @@ 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
- #region Public Methods and Operators
-
/// <summary>
- /// The prepare authorized request.
+ /// Gets the DotNetOpenAuth <see cref="WebConsumer"/> instance that can be used to make OAuth 1.0 authorized HTTP requests.
/// </summary>
- /// <param name="profileEndpoint">
- /// The profile endpoint.
- /// </param>
- /// <param name="accessToken">
- /// The access token.
- /// </param>
- /// <returns>An HTTP request.</returns>
- public HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint profileEndpoint, string accessToken) {
- return this.webConsumer.PrepareAuthorizedRequest(profileEndpoint, accessToken);
+ public Consumer Consumer {
+ get { return this.webConsumer; }
}
+ #region Public Methods and Operators
+
/// <summary>
- /// The process user authorization.
+ /// Creates an HTTP message handler that authorizes outgoing web requests.
/// </summary>
- /// <returns>The response message.</returns>
- public AuthorizedTokenResponse ProcessUserAuthorization() {
- return this.webConsumer.ProcessUserAuthorization();
+ /// <param name="accessToken">The access token.</param>
+ public HttpMessageHandler CreateMessageHandler(AccessToken accessToken) {
+ Requires.NotNullOrEmpty(accessToken.Token, "accessToken");
+
+ return this.Consumer.CreateMessageHandler(accessToken);
}
/// <summary>
- /// The request authentication.
+ /// The process user authorization.
/// </summary>
- /// <param name="callback">
- /// The callback.
- /// </param>
- public void RequestAuthentication(Uri callback) {
- var redirectParameters = new Dictionary<string, string>();
- UserAuthorizationRequest request = this.webConsumer.PrepareRequestUserAuthorization(
- callback, null, redirectParameters);
- this.webConsumer.Channel.PrepareResponse(request).Send();
- }
-
- #endregion
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The response message.
+ /// </returns>
+ public Task<AccessTokenResponse> ProcessUserAuthorizationAsync(HttpContextBase context = null, CancellationToken cancellationToken = default(CancellationToken)) {
+ if (context == null) {
+ context = new HttpContextWrapper(HttpContext.Current);
+ }
- #region IDisposable members
+ return this.webConsumer.ProcessUserAuthorizationAsync(context.Request.Url, cancellationToken: cancellationToken);
+ }
/// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// The request authentication.
/// </summary>
- /// <filterpriority>2</filterpriority>
- public void Dispose() {
- this.Dispose(true);
- GC.SuppressFinalize(this);
+ /// <param name="callback">The callback.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The response message.
+ /// </returns>
+ 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 a054a1c..e3ee3e8 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs
@@ -7,41 +7,39 @@
namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Net;
+ 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>
- /// The io auth web worker.
+ /// The interface implemented by all OAuth web authentication modules in this assembly.
/// </summary>
public interface IOAuthWebWorker {
- #region Public Methods and Operators
-
/// <summary>
- /// The prepare authorized request.
+ /// Creates an HTTP message handler that authorizes outgoing web requests.
/// </summary>
- /// <param name="profileEndpoint">
- /// The profile endpoint.
- /// </param>
- /// <param name="accessToken">
- /// The access token.
- /// </param>
- /// <returns>An HTTP request.</returns>
- HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint profileEndpoint, string accessToken);
+ /// <param name="accessToken">The access token.</param>
+ HttpMessageHandler CreateMessageHandler(AccessToken accessToken);
/// <summary>
/// The process user authorization.
/// </summary>
- /// <returns>The response message.</returns>
- AuthorizedTokenResponse ProcessUserAuthorization();
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The access token, if obtained; otherwise <c>null</c>.
+ /// </returns>
+ Task<AccessTokenResponse> ProcessUserAuthorizationAsync(HttpContextBase context = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// The request authentication.
/// </summary>
- /// <param name="callback">
- /// The callback.
- /// </param>
- void RequestAuthentication(Uri callback);
-
- #endregion
+ /// <param name="callback">The callback.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <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 a7b641c..0000000
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs
+++ /dev/null
@@ -1,158 +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 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.ProcessUserAuthorization()"/>
- /// or
- /// <see cref="DesktopConsumer.ProcessUserAuthorization(string, string)"/>
- /// 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 3c157f3..daf3441 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
@@ -10,11 +10,15 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
+ using System.Net.Http;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Xml.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
+ using System.Collections.Specialized;
/// <summary>
/// Represents LinkedIn authentication client.
@@ -25,21 +29,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
@@ -48,28 +41,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
@@ -79,46 +54,48 @@ 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>
+ /// <param name="response">The response token returned from service provider</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// Authentication result.
+ /// Authentication result.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We don't care if the request fails.")]
- protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response) {
+ 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 profileEndpoint = new MessageReceivingEndpoint(ProfileRequestUrl, HttpDeliveryMethods.GetRequest);
- HttpWebRequest request = this.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);
-
+ var accessToken = response.AccessToken;
+ var authorizingHandler = this.WebWorker.CreateMessageHandler(accessToken);
try {
- using (WebResponse profileResponse = request.GetResponse()) {
- using (Stream responseStream = profileResponse.GetResponseStream()) {
- XDocument document = LoadXDocumentFromStream(responseStream);
- string userId = document.Root.Element("id").Value;
-
- string firstName = document.Root.Element("first-name").Value;
- string lastName = document.Root.Element("last-name").Value;
- string userName = firstName + " " + lastName;
-
- var extraData = new Dictionary<string, string>();
- extraData.Add("accesstoken", accessToken);
- extraData.Add("name", userName);
- extraData.AddDataIfNotEmpty(document, "headline");
- extraData.AddDataIfNotEmpty(document, "summary");
- extraData.AddDataIfNotEmpty(document, "industry");
-
- return new AuthenticationResult(
- isSuccessful: true, provider: this.ProviderName, providerUserId: userId, userName: userName, extraData: extraData);
+ using (var httpClient = new HttpClient(authorizingHandler)) {
+ using (HttpResponseMessage profileResponse = await httpClient.GetAsync(ProfileRequestUrl, cancellationToken)) {
+ using (Stream responseStream = await profileResponse.Content.ReadAsStreamAsync()) {
+ XDocument document = LoadXDocumentFromStream(responseStream);
+ string userId = document.Root.Element("id").Value;
+
+ string firstName = document.Root.Element("first-name").Value;
+ string lastName = document.Root.Element("last-name").Value;
+ string userName = firstName + " " + lastName;
+
+ var extraData = new NameValueCollection();
+ extraData.Add("accesstoken", accessToken.Token);
+ extraData.Add("accesstokensecret", accessToken.Secret);
+ extraData.Add("name", userName);
+ extraData.AddDataIfNotEmpty(document, "headline");
+ extraData.AddDataIfNotEmpty(document, "summary");
+ extraData.AddDataIfNotEmpty(document, "industry");
+
+ return new AuthenticationResult(
+ isSuccessful: true,
+ provider: this.ProviderName,
+ providerUserId: userId,
+ userName: userName,
+ extraData: extraData);
+ }
}
}
- }
- 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 a0afeca..1841ef3 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
@@ -9,6 +9,8 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using System.Xml;
using System.Xml.Linq;
@@ -17,6 +19,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
using Validation;
+ using System.Collections.Specialized;
/// <summary>
/// Represents base class for OAuth 1.0 clients
@@ -31,34 +34,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>
@@ -103,42 +86,40 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url.
/// </summary>
- /// <param name="context">
- /// The context.
- /// </param>
- /// <param name="returnUrl">
- /// The return url after users have completed authenticating against external website.
- /// </param>
- public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) {
+ /// <param name="context">The context.</param>
+ /// <param name="returnUrl">The return url after users have completed authenticating against external website.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// A task that completes with the asynchronous operation.
+ /// </returns>
+ public virtual Task RequestAuthenticationAsync(HttpContextBase context, Uri returnUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(returnUrl, "returnUrl");
Requires.NotNull(context, "context");
Uri callback = returnUrl.StripQueryArgumentsWithPrefix("oauth_");
- this.WebWorker.RequestAuthentication(callback);
+ return this.WebWorker.RequestAuthenticationAsync(callback, cancellationToken);
}
/// <summary>
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
- /// <param name="context">
- /// The context.
- /// </param>
+ /// <param name="context">The context.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// An instance of <see cref="AuthenticationResult"/> containing authentication result.
+ /// An instance of <see cref="AuthenticationResult" /> containing authentication result.
/// </returns>
- public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) {
- AuthorizedTokenResponse response = this.WebWorker.ProcessUserAuthorization();
+ public virtual async Task<AuthenticationResult> VerifyAuthenticationAsync(HttpContextBase context, CancellationToken cancellationToken = default(CancellationToken)) {
+ AccessTokenResponse response = await this.WebWorker.ProcessUserAuthorizationAsync(context, cancellationToken);
if (response == null) {
return AuthenticationResult.Failed;
}
- AuthenticationResult result = this.VerifyAuthenticationCore(response);
+ AuthenticationResult result = await this.VerifyAuthenticationCoreAsync(response, cancellationToken);
if (result.IsSuccessful && result.ExtraData != null) {
// add the access token to the user data dictionary just in case page developers want to use it
- var wrapExtraData = result.ExtraData.IsReadOnly
- ? new Dictionary<string, string>(result.ExtraData)
- : result.ExtraData;
- wrapExtraData["accesstoken"] = response.AccessToken;
+ var wrapExtraData = new NameValueCollection(result.ExtraData);
+ wrapExtraData["accesstoken"] = response.AccessToken.Token;
+ wrapExtraData["accesstokensecret"] = response.AccessToken.Secret;
AuthenticationResult wrapResult = new AuthenticationResult(
result.IsSuccessful,
@@ -174,12 +155,13 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
/// <param name="response">
- /// The response token returned from service provider
+ /// The access token returned from service provider
/// </param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// Authentication result
/// </returns>
- protected abstract AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response);
+ protected abstract Task<AuthenticationResult> VerifyAuthenticationCoreAsync(AccessTokenResponse response, 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 886917a..0c17ed3 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
@@ -10,11 +10,15 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
+ using System.Net.Http;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Xml.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
+ using System.Collections.Specialized;
/// <summary>
/// Represents a Twitter client
@@ -25,51 +29,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
@@ -79,34 +55,34 @@ 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>
+ /// <param name="response">The response token returned from service provider</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// Authentication result
+ /// Authentication result
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We don't care if the request for additional data fails.")]
- protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response) {
- 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 profileEndpoint = new MessageReceivingEndpoint(profileRequestUrl, HttpDeliveryMethods.GetRequest);
- HttpWebRequest request = this.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);
+ var authorizingHandler = this.WebWorker.CreateMessageHandler(response.AccessToken);
- var extraData = new Dictionary<string, string>();
- extraData.Add("accesstoken", accessToken);
+ var extraData = new NameValueCollection();
+ extraData.Add("accesstoken", response.AccessToken.Token);
+ extraData.Add("accesstokensecret", response.AccessToken.Secret);
try {
- using (WebResponse profileResponse = request.GetResponse()) {
- using (Stream responseStream = profileResponse.GetResponseStream()) {
- XDocument document = LoadXDocumentFromStream(responseStream);
- extraData.AddDataIfNotEmpty(document, "name");
- extraData.AddDataIfNotEmpty(document, "location");
- extraData.AddDataIfNotEmpty(document, "description");
- extraData.AddDataIfNotEmpty(document, "url");
+ using (var httpClient = new HttpClient(authorizingHandler)) {
+ using (HttpResponseMessage profileResponse = await httpClient.GetAsync(profileRequestUrl, cancellationToken)) {
+ using (Stream responseStream = await profileResponse.Content.ReadAsStreamAsync()) {
+ XDocument document = LoadXDocumentFromStream(responseStream);
+ extraData.AddDataIfNotEmpty(document, "name");
+ extraData.AddDataIfNotEmpty(document, "location");
+ extraData.AddDataIfNotEmpty(document, "description");
+ extraData.AddDataIfNotEmpty(document, "url");
+ }
}
}
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs
index d20e452..c06c1dc 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs
@@ -12,6 +12,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Web;
using DotNetOpenAuth.Messaging;
using Validation;
+ using System.Collections.Specialized;
/// <summary>
/// The facebook client.
@@ -92,7 +93,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// The access token.
/// </param>
/// <returns>A dictionary of profile data.</returns>
- protected override IDictionary<string, string> GetUserData(string accessToken) {
+ protected override NameValueCollection GetUserData(string accessToken) {
FacebookGraphData graphData;
var request =
WebRequest.Create(
@@ -104,7 +105,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
}
// this dictionary must contains
- var userData = new Dictionary<string, string>();
+ var userData = new NameValueCollection();
userData.AddItemIfNotEmpty("id", graphData.Id);
userData.AddItemIfNotEmpty("username", graphData.Email);
userData.AddItemIfNotEmpty("name", graphData.Name);
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/MicrosoftClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/MicrosoftClient.cs
index 3e5f71f..b9c4941 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/MicrosoftClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/MicrosoftClient.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Net;
using DotNetOpenAuth.Messaging;
using Validation;
+ using System.Collections.Specialized;
/// <summary>
/// The Microsoft account client.
@@ -110,7 +111,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <returns>
/// A dictionary contains key-value pairs of user data
/// </returns>
- protected override IDictionary<string, string> GetUserData(string accessToken) {
+ protected override NameValueCollection GetUserData(string accessToken) {
MicrosoftClientUserData graph;
var request =
WebRequest.Create(
@@ -121,7 +122,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
}
}
- var userData = new Dictionary<string, string>();
+ var userData = new NameValueCollection();
userData.AddItemIfNotEmpty("id", graph.Id);
userData.AddItemIfNotEmpty("username", graph.Name);
userData.AddItemIfNotEmpty("name", graph.Name);
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs
index 014f459..8e6b5f3 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs
@@ -8,8 +8,14 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
+
+ using DotNetOpenAuth.Messaging;
+
using Validation;
+ using System.Collections.Specialized;
/// <summary>
/// Represents the base class for OAuth 2.0 clients
@@ -57,30 +63,31 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url.
/// </summary>
- /// <param name="context">
- /// The context.
- /// </param>
- /// <param name="returnUrl">
- /// The return url after users have completed authenticating against external website.
- /// </param>
- public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) {
+ /// <param name="context">The context.</param>
+ /// <param name="returnUrl">The return url after users have completed authenticating against external website.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// A task that completes with the asynchronous operation.
+ /// </returns>
+ public virtual Task RequestAuthenticationAsync(HttpContextBase context, Uri returnUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(context, "context");
Requires.NotNull(returnUrl, "returnUrl");
string redirectUrl = this.GetServiceLoginUrl(returnUrl).AbsoluteUri;
context.Response.Redirect(redirectUrl, endResponse: true);
+ return MessagingUtilities.CompletedTask;
}
/// <summary>
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
- /// <param name="context">
- /// The context.
- /// </param>
+ /// <param name="context">The context.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// An instance of <see cref="AuthenticationResult"/> containing authentication result.
+ /// An instance of <see cref="AuthenticationResult" /> containing authentication result.
/// </returns>
- public AuthenticationResult VerifyAuthentication(HttpContextBase context) {
+ /// <exception cref="System.InvalidOperationException">Always thrown.</exception>
+ public Task<AuthenticationResult> VerifyAuthenticationAsync(HttpContextBase context, CancellationToken cancellationToken = default(CancellationToken)) {
throw new InvalidOperationException(WebResources.OAuthRequireReturnUrl);
}
@@ -89,10 +96,11 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// </summary>
/// <param name="context">The context.</param>
/// <param name="returnPageUrl">The return URL which should match the value passed to RequestAuthentication() method.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// An instance of <see cref="AuthenticationResult"/> containing authentication result.
+ /// An instance of <see cref="AuthenticationResult" /> containing authentication result.
/// </returns>
- public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl) {
+ public virtual async Task<AuthenticationResult> VerifyAuthenticationAsync(HttpContextBase context, Uri returnPageUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(context, "context");
string code = context.Request.QueryString["code"];
@@ -105,19 +113,15 @@ namespace DotNetOpenAuth.AspNet.Clients {
return AuthenticationResult.Failed;
}
- IDictionary<string, string> userData = this.GetUserData(accessToken);
+ var userData = this.GetUserData(accessToken);
if (userData == null) {
return AuthenticationResult.Failed;
}
- string id = userData["id"];
- string name;
-
// Some oAuth providers do not return value for the 'username' attribute.
// In that case, try the 'name' attribute. If it's still unavailable, fall back to 'id'
- if (!userData.TryGetValue("username", out name) && !userData.TryGetValue("name", out name)) {
- name = id;
- }
+ string id = userData["id"];
+ string name = userData["username"] ?? userData["name"] ?? id;
// add the access token to the user data dictionary just in case page developers want to use it
userData["accesstoken"] = accessToken;
@@ -152,7 +156,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <returns>
/// A dictionary contains key-value pairs of user data
/// </returns>
- protected abstract IDictionary<string, string> GetUserData(string accessToken);
+ protected abstract NameValueCollection GetUserData(string accessToken);
/// <summary>
/// Queries the access token from the specified authorization code.
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs
index 6b4061a..2a68bd8 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Collections.Generic;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.RelyingParty;
+ using System.Collections.Specialized;
/// <summary>
/// Represents Google OpenID client.
@@ -32,10 +33,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// The response message.
/// </param>
/// <returns>A dictionary of profile data; or null if no data is available.</returns>
- protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response) {
+ protected override NameValueCollection GetExtraData(IAuthenticationResponse response) {
FetchResponse fetchResponse = response.GetExtension<FetchResponse>();
if (fetchResponse != null) {
- var extraData = new Dictionary<string, string>();
+ var extraData = new NameValueCollection();
extraData.AddItemIfNotEmpty("email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email));
extraData.AddItemIfNotEmpty("country", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.Country));
extraData.AddItemIfNotEmpty("firstName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.First));
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs
index a41b504..901741b 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs
@@ -8,11 +8,14 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
using Validation;
+ using System.Collections.Specialized;
/// <summary>
/// Base classes for OpenID clients.
@@ -79,51 +82,47 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <summary>
/// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url.
/// </summary>
- /// <param name="context">
- /// The context of the current request.
- /// </param>
- /// <param name="returnUrl">
- /// The return url after users have completed authenticating against external website.
- /// </param>
+ /// <param name="context">The context of the current request.</param>
+ /// <param name="returnUrl">The return url after users have completed authenticating against external website.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// A task that completes with the asynchronous operation.
+ /// </returns>
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings",
Justification = "We don't have a Uri object handy.")]
- public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) {
+ public virtual async Task RequestAuthenticationAsync(HttpContextBase context, Uri returnUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(returnUrl, "returnUrl");
var realm = new Realm(returnUrl.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped));
- IAuthenticationRequest request = RelyingParty.CreateRequest(this.providerIdentifier, realm, returnUrl);
+ IAuthenticationRequest request = await RelyingParty.CreateRequestAsync(this.providerIdentifier, realm, returnUrl, cancellationToken);
// give subclasses a chance to modify request message, e.g. add extension attributes, etc.
this.OnBeforeSendingAuthenticationRequest(request);
- request.RedirectToProvider();
+ await request.RedirectToProviderAsync(context);
}
/// <summary>
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
- /// <param name="context">
- /// The context of the current request.
- /// </param>
+ /// <param name="context">The context of the current request.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
- /// An instance of <see cref="AuthenticationResult"/> containing authentication result.
+ /// An instance of <see cref="AuthenticationResult" /> containing authentication result.
/// </returns>
- public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) {
- IAuthenticationResponse response = RelyingParty.GetResponse();
+ /// <exception cref="System.InvalidOperationException">Thrown if no OpenID response was found in the incoming HTTP request.</exception>
+ public virtual async Task<AuthenticationResult> VerifyAuthenticationAsync(HttpContextBase context, CancellationToken cancellationToken = default(CancellationToken)) {
+ IAuthenticationResponse response = await RelyingParty.GetResponseAsync(context.Request, cancellationToken);
if (response == null) {
throw new InvalidOperationException(WebResources.OpenIDFailedToGetResponse);
}
if (response.Status == AuthenticationStatus.Authenticated) {
string id = response.ClaimedIdentifier;
- string username;
-
- Dictionary<string, string> extraData = this.GetExtraData(response) ?? new Dictionary<string, string>();
+ var extraData = this.GetExtraData(response) ?? new NameValueCollection();
// try to look up username from the 'username' or 'email' property. If not found, fall back to 'friendly id'
- if (!extraData.TryGetValue("username", out username) && !extraData.TryGetValue("email", out username)) {
- username = response.FriendlyIdentifierForDisplay;
- }
+ string username = extraData["username"] ?? extraData["email"] ?? response.FriendlyIdentifierForDisplay;
return new AuthenticationResult(true, this.ProviderName, id, username, extraData);
}
@@ -142,7 +141,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// The response message.
/// </param>
/// <returns>Always null.</returns>
- protected virtual Dictionary<string, string> GetExtraData(IAuthenticationResponse response) {
+ protected virtual NameValueCollection GetExtraData(IAuthenticationResponse response) {
return null;
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs
index bd420fc..d282d4f 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System.Collections.Generic;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.RelyingParty;
+ using System.Collections.Specialized;
/// <summary>
/// The yahoo open id client.
@@ -32,10 +33,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// The response message.
/// </param>
/// <returns>A dictionary of profile data; or null if no data is available.</returns>
- protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response) {
+ protected override NameValueCollection GetExtraData(IAuthenticationResponse response) {
FetchResponse fetchResponse = response.GetExtension<FetchResponse>();
if (fetchResponse != null) {
- var extraData = new Dictionary<string, string>();
+ var extraData = new NameValueCollection();
extraData.AddItemIfNotEmpty("email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email));
extraData.AddItemIfNotEmpty("fullName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.FullName));